import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { getSessionUser } from '@/lib/auth'
import { setSessionCookie } from '@/lib/auth/session'
import { findEnvUserById } from '@/lib/auth/env-users'
import { effectiveRole, getAccountOverride } from '@/lib/auth/accounts'
import { createAdminClient } from '@/lib/supabase/admin'
import { ensureSelfAccount } from '@/lib/auth/self-accounts'
import { issueEmailCode, verifyEmailCode } from '@/lib/security/verification-codes'
import { clientIp, rateLimit } from '@/lib/security/rate-limit'
import { logSecurityEvent } from '@/lib/security/events'
import { verifyBotCheck } from '@/lib/data/intake-guard'
import { publicOrigin } from '@/lib/app-url'
import { emailPattern } from '@/lib/like'

/**
 * Inline authentication on the public intake page (2026-09-22, §9–§11):
 *   POST { op: 'start',  email, slug?, bot_token? }        → one-time code emailed
 *   POST { op: 'verify', email, code, name?, phone? }      → account created or
 *                                                             recognised, session set
 *   GET                                                     → who am I
 * No password, no multi-page registration. The verified email is the account.
 */
const schema = z.discriminatedUnion('op', [
  z.object({ op: z.literal('start'), email: z.string().trim().email().max(200), slug: z.string().max(80).optional(), bot_token: z.string().max(4000).optional() }),
  z.object({ op: z.literal('verify'), email: z.string().trim().email().max(200), code: z.string().trim().min(6).max(8), name: z.string().trim().max(120).optional(), phone: z.string().trim().max(40).optional() }),
])

export async function GET() {
  const user = await getSessionUser()
  return NextResponse.json(user ? { signedIn: true, email: user.email, name: user.name, role: user.role } : { signedIn: false })
}

export async function POST(req: NextRequest) {
  const parsed = schema.safeParse(await req.json().catch(() => ({})))
  if (!parsed.success) return NextResponse.json({ error: 'Enter a valid email address.' }, { status: 400 })
  const input = parsed.data
  const ip = clientIp(req.headers)
  const userAgent = req.headers.get('user-agent')
  const email = input.email.toLowerCase()

  if (input.op === 'start') {
    const gate = rateLimit(`intake-auth:${ip}`, 10, 15 * 60_000)
    if (!gate.allowed) return NextResponse.json({ error: 'Too many requests from your network. Try again in a few minutes.' }, { status: 429 })
    const bot = await verifyBotCheck(input.bot_token ?? null, ip)
    if (bot.configured && !bot.passed) return NextResponse.json({ error: 'We could not confirm you are not a bot. Reload the page and try again.' }, { status: 403 })
    const r = await issueEmailCode({ email, ip, origin: publicOrigin(req) })
    if (r.ok) return NextResponse.json({ ok: true, status: r.status, ...(r.devCode ? { dev_code: r.devCode } : {}) })
    return NextResponse.json({ error: r.error }, { status: /migration/i.test(r.error) ? 503 : /too many/i.test(r.error) ? 429 : 400 })
  }

  const v = await verifyEmailCode({ email, code: input.code, ip })
  if (!v.ok) return NextResponse.json({ error: v.error }, { status: 400 })

  // An admin-provisioned login with this email signs in as itself; otherwise the email is a self-service account.
  const admin = createAdminClient()
  const { data: envProfile } = await admin.from('profiles').select('id, full_name').ilike('email', emailPattern(email)).maybeSingle()
  const envUser = envProfile ? findEnvUserById(envProfile.id) : null
  let session: { sub: string; email: string; name: string; role: 'broker' | 'dispatcher' | 'driver' | 'admin'; company: string | null }
  let created = false
  if (envUser) {
    const role = effectiveRole(envUser, await getAccountOverride(envUser.id))
    if (role === 'admin') return NextResponse.json({ error: 'Admin accounts must use password sign-in.' }, { status: 403 })
    session = { sub: envUser.id, email: envUser.email, name: envUser.name, role, company: envUser.company }
  } else {
    const r = await ensureSelfAccount({ email, name: input.name, phone: input.phone, role: 'dispatcher' })
    if (!r.ok) return NextResponse.json({ error: r.error }, { status: 400 })
    if (r.account.blocked_at) return NextResponse.json({ error: 'This account is blocked. Contact support.' }, { status: 403 })
    if (r.account.role === 'admin') return NextResponse.json({ error: 'Admin accounts must use password sign-in.' }, { status: 403 })
    session = { sub: r.account.id, email: r.account.email, name: r.account.name, role: r.account.role, company: null }
    created = r.created
  }
  await setSessionCookie({ ...session, internal: false, origin_sub: session.sub, auth_method: 'email_code' })
  await logSecurityEvent({ event: 'login_success', username: email, userId: session.sub, ip, userAgent, detail: { via: 'email_code', created, role: session.role } })
  return NextResponse.json({ ok: true, created, email: session.email, name: session.name, role: session.role })
}
