import "server-only";
import { eq } from "drizzle-orm";
import { db } from "@/lib/db/client";
import { emailTemplates, type EmailTemplate } from "@/lib/db/schema";
import { EMAIL_TEMPLATE_DEFAULTS } from "./template-defaults";

const templateCache = new Map<string, { value: EmailTemplate; at: number }>();
const CACHE_MS = 30_000;

function fallbackTemplate(slug: string): EmailTemplate | null {
  const def = EMAIL_TEMPLATE_DEFAULTS.find((t) => t.slug === slug);
  if (!def) return null;
  return {
    slug: def.slug,
    name: def.name,
    description: def.description ?? "",
    subject: def.subject,
    body: def.body,
    variables: def.variables ?? [],
    updatedAt: new Date(0),
    updatedBy: null,
  };
}

/**
 * Load one template, falling back to the hardcoded default if the admin
 * has never customised it (or the table isn't seeded yet).
 */
export async function loadTemplate(slug: string): Promise<EmailTemplate> {
  const cached = templateCache.get(slug);
  if (cached && Date.now() - cached.at < CACHE_MS) return cached.value;
  try {
    const [row] = await db
      .select()
      .from(emailTemplates)
      .where(eq(emailTemplates.slug, slug))
      .limit(1);
    if (row) {
      templateCache.set(slug, { value: row, at: Date.now() });
      return row;
    }
  } catch (err) {
    console.error("[email-templates] DB read failed, using fallback", err);
  }
  const fallback = fallbackTemplate(slug);
  if (!fallback) throw new Error(`Unknown email template: ${slug}`);
  return fallback;
}

export function clearTemplateCache(slug?: string): void {
  if (slug) templateCache.delete(slug);
  else templateCache.clear();
}

export async function listTemplates(): Promise<EmailTemplate[]> {
  try {
    const rows = await db.select().from(emailTemplates);
    const map = new Map(rows.map((r) => [r.slug, r]));
    // Merge defaults so the admin page always shows every template, even
    // if one has never been edited.
    return EMAIL_TEMPLATE_DEFAULTS.map((d) => map.get(d.slug) ?? fallbackTemplate(d.slug)!);
  } catch {
    return EMAIL_TEMPLATE_DEFAULTS.map((d) => fallbackTemplate(d.slug)!);
  }
}

export function defaultsFor(slug: string) {
  return EMAIL_TEMPLATE_DEFAULTS.find((t) => t.slug === slug) ?? null;
}

/**
 * Very small mustache-style replacer — {{key}} → vars[key]. Unknown keys are
 * replaced with empty strings so a missing variable won't render "{{x}}" to
 * the recipient.
 */
export function renderTemplate(
  tpl: Pick<EmailTemplate, "subject" | "body">,
  vars: Record<string, string | number | null | undefined>,
): { subject: string; body: string } {
  const replace = (input: string) =>
    input.replace(/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g, (_, key) => {
      const v = vars[key];
      return v === null || v === undefined ? "" : String(v);
    });
  return { subject: replace(tpl.subject), body: replace(tpl.body) };
}
