import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { getSessionUser } from '@/lib/auth'
import { canAccessSurface } from '@/lib/domain/moderator-access'
import { createAdminClient } from '@/lib/supabase/admin'
import { validateTemplateMeta } from '@/lib/domain/email-policy'

/**
 * Save an email template edit (admin only). Every save also writes a version
 * row so a bad edit can be restored ("if an email template is edited
 * incorrectly, it can confuse carriers, brokers, and Synchron"). Sending is
 * the email backend — this stores content only.
 */

const schema = z.object({
  key: z.string().trim().min(1).max(80),
  name: z.string().trim().min(1).max(160),
  subject: z.string().trim().min(1).max(300),
  body: z.string().trim().min(1).max(20_000),
  recipients_note: z.string().trim().max(500).optional().or(z.literal('')),
  cc_rules: z.string().trim().max(500).optional().or(z.literal('')),
  trigger_note: z.string().trim().max(500).optional().or(z.literal('')),
  internal_notes: z.string().trim().max(2000).optional().or(z.literal('')),
  cta_text: z.string().trim().max(120).optional().or(z.literal('')),
  footer: z.string().trim().max(2000).optional().or(z.literal('')),
  support_contact: z.string().trim().max(200).optional().or(z.literal('')),
  email_stream: z.enum(['transactional', 'updates']).optional(),
  category_key: z.string().trim().max(60).optional(),
  required: z.boolean().optional(),
  active: z.boolean(),
  reason: z.string().trim().max(300).optional().or(z.literal('')),
})

export async function POST(req: NextRequest) {
  const user = await getSessionUser()
  if (!user || !canAccessSurface(user, 'email_templates')) {
    return NextResponse.json({ error: 'Admin only.' }, { status: 403 })
  }

  const parsed = schema.safeParse(await req.json().catch(() => ({})))
  if (!parsed.success) {
    return NextResponse.json({ error: 'Invalid template.' }, { status: 400 })
  }
  const input = parsed.data
  // §28: a marketing template can never be sent through the transactional agent, and vice versa.
  if (input.email_stream && input.category_key) {
    const v = validateTemplateMeta({ email_stream: input.email_stream, category_key: input.category_key, required: !!input.required })
    if (!v.ok) return NextResponse.json({ error: v.error }, { status: 400 })
  }

  const admin = createAdminClient()
  // Previous copy + version number (migration 0022, §34) — tolerated when the columns are missing.
  const { data: previous } = await admin.from('email_templates').select('id, subject, body, version').eq('key', input.key).maybeSingle()
  const nextVersion = ((previous?.version as number | null) ?? 0) + 1
  const row = {
    key: input.key,
    name: input.name,
    subject: input.subject,
    body: input.body,
    recipients_note: input.recipients_note || null,
    cc_rules: input.cc_rules || null,
    trigger_note: input.trigger_note || null,
    internal_notes: input.internal_notes || null,
    active: input.active,
    updated_by: user.name || user.email,
    updated_at: new Date().toISOString(),
  }
  const extras = { cta_text: input.cta_text || null, footer: input.footer || null, support_contact: input.support_contact || null, version: nextVersion, ...(input.email_stream && input.category_key ? { email_stream: input.email_stream, category_key: input.category_key, required: !!input.required, unsubscribe_required: input.email_stream === 'updates' } : {}) }
  let saved = await admin.from('email_templates').upsert({ ...row, ...extras }, { onConflict: 'key' }).select().single()
  if (saved.error && /column|schema cache/i.test(saved.error.message)) {
    saved = await admin.from('email_templates').upsert({ ...row, cta_text: input.cta_text || null, footer: input.footer || null }, { onConflict: 'key' }).select().single()
  }
  const tpl = saved.data
  if (saved.error || !tpl) {
    return NextResponse.json(
      { error: 'Could not save — is migration 0008 applied?' },
      { status: 500 },
    )
  }

  // Version history: every save is restorable and names its number.
  const version = {
    template_id: tpl.id,
    subject: input.subject,
    body: input.body,
    edited_by: user.name || user.email,
    reason: input.reason || null,
  }
  const v = await admin.from('email_template_versions').insert({
    ...version, version: nextVersion, template_key: input.key,
    previous_subject: previous?.subject ?? null, previous_body: previous?.body ?? null,
  })
  if (v.error && /column|schema cache/i.test(v.error.message)) await admin.from('email_template_versions').insert(version)

  return NextResponse.json({ ok: true, template: tpl, version: nextVersion })
}
