import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createHash, randomBytes } from 'node:crypto'
import { getSessionUser } from '@/lib/auth'
import { createAdminClient } from '@/lib/supabase/admin'
import { publicOrigin } from '@/lib/app-url'
import { sendPlatformEmail } from '@/lib/email/send'
import { logSecurityEvent } from '@/lib/security/events'
import { clientIp } from '@/lib/security/rate-limit'

/**
 * Change the address HeavyHaul Agent delivers to (2026-09-22, §14). Logins
 * come from the account list, so the verified DELIVERY address lives on the
 * profile. A verification email goes to the new address (transactional,
 * account_security — never blocked by marketing preferences); the switch
 * happens when the link is opened. The old address keeps its suppression.
 */
const schema = z.union([z.object({ email: z.string().trim().email().max(200) }), z.object({ reset: z.literal(true) })])

export async function POST(req: NextRequest) {
  const user = await getSessionUser()
  if (!user) return NextResponse.json({ error: 'Sign in first.' }, { status: 401 })
  const parsed = schema.safeParse(await req.json().catch(() => ({})))
  if (!parsed.success) return NextResponse.json({ error: 'Enter a valid email address.' }, { status: 400 })
  const admin = createAdminClient()
  if ('reset' in parsed.data) {
    // Back to the default: deliver to the sign-in email (2026-09-23).
    const { error } = await admin.from('profiles').update({ delivery_email: null, pending_email: null, pending_email_token_hash: null, pending_email_sent_at: null }).eq('id', user.id)
    if (error) return NextResponse.json({ error: error.message }, { status: 400 })
    return NextResponse.json({ ok: true })
  }
  const email = parsed.data.email.toLowerCase()
  const token = randomBytes(24).toString('base64url')
  const { error } = await admin.from('profiles').update({ pending_email: email, pending_email_token_hash: createHash('sha256').update(token).digest('hex'), pending_email_sent_at: new Date().toISOString() }).eq('id', user.id)
  if (error) return NextResponse.json({ error: /column|schema cache/i.test(error.message) ? 'Changing the delivery address needs database migration 0028.' : error.message }, { status: 400 })
  const r = await sendPlatformEmail({
    templateKey: 'email_verification', to: email, userId: null, actorUserId: user.id, clean: true,
    data: { user_name: user.name || user.email, verification_link: `${publicOrigin(req)}/email/verify/${token}` },
  })
  await logSecurityEvent({ event: 'admin_role_change', userId: user.id, actorUserId: user.id, actorLabel: user.name || user.email, ip: clientIp(req.headers), detail: { kind: 'delivery_email_change_requested', to: email, email_status: r.status } })
  if (r.status === 'suppressed') return NextResponse.json({ error: `That address cannot receive email (${r.reason?.replace(/_/g, ' ')}). Try a different one.` }, { status: 409 })
  if (r.status === 'failed') return NextResponse.json({ error: `Could not send the verification email: ${r.reason}` }, { status: 502 })
  return NextResponse.json({ ok: true, status: r.status })
}
