import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createAdminClient } from '@/lib/supabase/admin'
import { publicOrigin } from '@/lib/app-url'
import { normalizePhone } from '@/lib/domain/pilot-network'
import {
  loadCapabilityTypes,
  loadPilotTemplates,
  loadProfile,
  loadProfileHistory,
  logPilotNetworkAction,
  pilotNetworkAvailable,
  renderForProfile,
  sendToProfile,
  suppressProfile,
} from '@/lib/data/pilot-network'
import { migrationMissing, requireInternal } from '../_guard'

/**
 * Pilot lead actions (§12): approve, send, preview, resend, mark duplicate /
 * invalid / do-not-contact, edit, add note, history. Every action is audited
 * (§26). Sends are recorded, never delivered (answer 1).
 */

const actionSchema = z.object({
  id: z.string().uuid(),
  action: z.enum(['mark_ready', 'approve', 'send', 'resend', 'preview', 'mark_duplicate', 'mark_invalid', 'mark_do_not_contact', 'add_note', 'edit', 'history']),
  template_key: z.string().trim().max(80).optional(),
  note: z.string().trim().max(2000).optional(),
  edit: z
    .object({
      name: z.string().trim().min(1).max(160),
      company_name: z.string().trim().max(160).nullable(),
      email: z.string().trim().email().max(200),
      phone: z.string().trim().max(40).nullable(),
      primary_state: z.string().trim().length(2),
      related_states: z.array(z.string().trim().length(2)).max(60),
      capability_keys: z.array(z.string().trim().max(80)).max(100),
      admin_notes: z.string().trim().max(4000).nullable(),
    })
    .optional(),
})

export async function POST(req: NextRequest) {
  const guard = await requireInternal()
  if (!guard.ok) return guard.response
  const parsed = actionSchema.safeParse(await req.json().catch(() => ({})))
  if (!parsed.success) return NextResponse.json({ error: 'Invalid request.' }, { status: 400 })
  const input = parsed.data
  const admin = createAdminClient()
  if (!(await pilotNetworkAvailable(admin))) return migrationMissing()
  const profile = await loadProfile(input.id, admin)
  if (!profile) return NextResponse.json({ error: 'Pilot lead not found.' }, { status: 404 })
  const { actor } = guard
  const now = new Date().toISOString()

  switch (input.action) {
    case 'history': {
      const history = await loadProfileHistory(profile.id, admin)
      return NextResponse.json({ ok: true, ...history })
    }
    case 'mark_ready':
    case 'approve': {
      const status = input.action === 'approve' ? 'approved_for_invitation' : 'ready_for_review'
      await admin.from('pilot_profiles').update({ invitation_status: status, updated_at: now }).eq('id', profile.id)
      await logPilotNetworkAction({ actorId: actor.id, actorLabel: actor.label, action: input.action === 'approve' ? 'invitation_approved' : 'profile_marked_ready', entityType: 'profile', entityId: profile.id, detail: { from: profile.invitation_status } }, admin)
      return NextResponse.json({ ok: true })
    }
    case 'preview': {
      const templates = await loadPilotTemplates(admin)
      const template = templates.find((t) => t.key === (input.template_key || 'pilot_invitation_initial'))
      if (!template) return NextResponse.json({ error: 'Template not found.' }, { status: 404 })
      const rendered = await renderForProfile(template, profile, publicOrigin(req), admin)
      return NextResponse.json({ ok: true, to: profile.email, ...rendered })
    }
    case 'send':
    case 'resend': {
      const out = await sendToProfile(
        {
          profile,
          templateKey: input.template_key || 'pilot_invitation_initial',
          kind: 'invitation_sent',
          requireApproval: input.action === 'send',
          origin: publicOrigin(req),
          actorId: actor.id,
          actorLabel: actor.label,
        },
        admin,
      )
      if (!out.ok) return NextResponse.json({ error: out.block === 'delivery_failed' ? `ZeptoMail refused the email: ${out.error ?? 'unknown error'}` : `Not sent: ${out.block.replace(/_/g, ' ')}.` }, { status: out.block === 'delivery_failed' ? 502 : 409 })
      return NextResponse.json({ ok: true, status: out.status, message_id: out.message_id })
    }
    case 'mark_duplicate':
    case 'mark_invalid':
    case 'mark_do_not_contact': {
      const reason = input.action === 'mark_duplicate' ? 'duplicate' : input.action === 'mark_invalid' ? 'invalid_email' : 'do_not_contact'
      await suppressProfile(profile, reason, actor, input.note, admin)
      return NextResponse.json({ ok: true })
    }
    case 'add_note': {
      if (!input.note) return NextResponse.json({ error: 'Note is empty.' }, { status: 400 })
      const stamp = `${now.slice(0, 16).replace('T', ' ')} · ${actor.label}: ${input.note}`
      const notes = profile.admin_notes ? `${profile.admin_notes}\n${stamp}` : stamp
      await admin.from('pilot_profiles').update({ admin_notes: notes, updated_at: now }).eq('id', profile.id)
      await logPilotNetworkAction({ actorId: actor.id, actorLabel: actor.label, action: 'admin_note_added', entityType: 'profile', entityId: profile.id, detail: { note: input.note } }, admin)
      return NextResponse.json({ ok: true })
    }
    case 'edit': {
      if (!input.edit) return NextResponse.json({ error: 'Nothing to edit.' }, { status: 400 })
      const e = input.edit
      const states = [...new Set([e.primary_state.toUpperCase(), ...e.related_states.map((s) => s.toUpperCase())])]
      const { error } = await admin
        .from('pilot_profiles')
        .update({
          name: e.name,
          company_name: e.company_name || null,
          email: e.email.toLowerCase(),
          phone: e.phone || null,
          phone_digits: normalizePhone(e.phone),
          primary_state: e.primary_state.toUpperCase(),
          related_states: states,
          admin_notes: e.admin_notes,
          updated_at: now,
        })
        .eq('id', profile.id)
      if (error) return NextResponse.json({ error: error.message.includes('duplicate') ? 'Another lead already uses that email.' : 'Could not save.' }, { status: 409 })
      // Capabilities edited by staff: kept links stay as they are; new ones are HHA reviewed; removed ones go.
      const types = await loadCapabilityTypes(admin)
      const keepIds = types.filter((t) => e.capability_keys.includes(t.key)).map((t) => t.id)
      const current = new Set(profile.capabilities.map((c) => c.capability_type_id))
      const toAdd = keepIds.filter((id) => !current.has(id))
      const toRemove = [...current].filter((id) => !keepIds.includes(id))
      if (toRemove.length) await admin.from('pilot_profile_capabilities').delete().eq('profile_id', profile.id).in('capability_type_id', toRemove)
      if (toAdd.length) await admin.from('pilot_profile_capabilities').insert(toAdd.map((id) => ({ profile_id: profile.id, capability_type_id: id, data_status: 'hha_reviewed', source: 'admin edit', confirmed_at: now })))
      await logPilotNetworkAction({ actorId: actor.id, actorLabel: actor.label, action: 'profile_edited', entityType: 'profile', entityId: profile.id, detail: { fields: Object.keys(e), capabilities_added: toAdd.length, capabilities_removed: toRemove.length } }, admin)
      return NextResponse.json({ ok: true })
    }
  }
}
