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 { logSecurityEvent } from '@/lib/security/events'
import { clientIp } from '@/lib/security/rate-limit'

/** Admin → Intake Security actions (2026-09-22, §34). Every action is logged. */
const schema = z.discriminatedUnion('op', [
  z.object({ op: z.literal('page'), page_id: z.string().uuid(), intake_enabled: z.boolean().optional(), protection_mode: z.boolean().optional(), who_can_submit: z.enum(['verified_email', 'verified_company', 'invited_only']).optional() }),
  z.object({ op: z.literal('block'), kind: z.enum(['ip', 'email', 'user']), value: z.string().trim().min(1).max(200), reason: z.string().trim().max(300).optional(), hours: z.number().int().min(1).max(24 * 365).optional() }),
  z.object({ op: z.literal('unblock'), id: z.string().uuid() }),
  z.object({ op: z.literal('trust'), user_id: z.string().uuid(), level: z.number().int().min(0).max(4) }),
  z.object({ op: z.literal('release'), submission_id: z.string().uuid() }),
  z.object({ op: z.literal('limits'), patch: z.record(z.string(), z.number().int().min(0).max(100000)) }),
])

export async function POST(req: NextRequest) {
  const user = await getSessionUser()
  if (!user || !canAccessSurface(user, 'intake_security')) return NextResponse.json({ error: 'You do not have access to this page.' }, { status: 403 })
  const parsed = schema.safeParse(await req.json().catch(() => ({})))
  if (!parsed.success) return NextResponse.json({ error: 'Invalid request.' }, { status: 400 })
  const input = parsed.data
  const admin = createAdminClient()
  const actorLabel = user.name || user.email
  const log = (detail: Record<string, unknown>) => logSecurityEvent({ event: 'admin_role_change', actorUserId: user.id, actorLabel, ip: clientIp(req.headers), detail: { kind: 'intake_admin_action', ...detail } })
  switch (input.op) {
    case 'page': {
      const { op: _o, page_id, ...patch } = input; void _o
      const update: Record<string, unknown> = { ...patch }
      if (patch.protection_mode === false) Object.assign(update, { protection_reason: null, protection_until: null })
      if (patch.protection_mode === true) Object.assign(update, { protection_reason: `set by ${actorLabel}`, protection_until: null })
      const { error } = await admin.from('broker_pages').update(update).eq('id', page_id)
      if (error) return NextResponse.json({ error: error.message }, { status: 400 })
      await log({ op: 'page', page_id, patch })
      return NextResponse.json({ ok: true })
    }
    case 'block': {
      const value = input.kind === 'email' ? input.value.toLowerCase() : input.value
      const { error } = await admin.from('intake_blocks').upsert({ kind: input.kind, value, reason: input.reason ?? null, until: input.hours ? new Date(Date.now() + input.hours * 3_600_000).toISOString() : null, created_by: actorLabel }, { onConflict: 'kind,value' })
      if (error) return NextResponse.json({ error: error.message }, { status: 400 })
      if (input.kind === 'user') await admin.from('auth_accounts').update({ blocked_at: new Date().toISOString(), blocked_reason: input.reason ?? 'blocked by admin' }).eq('user_id', value)
      await log({ op: 'block', kind: input.kind, value, hours: input.hours ?? null })
      return NextResponse.json({ ok: true })
    }
    case 'unblock': {
      const { data } = await admin.from('intake_blocks').select('kind, value').eq('id', input.id).maybeSingle()
      await admin.from('intake_blocks').delete().eq('id', input.id)
      if (data?.kind === 'user') await admin.from('auth_accounts').update({ blocked_at: null, blocked_reason: null }).eq('user_id', data.value)
      await log({ op: 'unblock', ...data })
      return NextResponse.json({ ok: true })
    }
    case 'trust': {
      const { error } = await admin.from('auth_accounts').update({ intake_trust_level: input.level }).eq('user_id', input.user_id)
      if (error) return NextResponse.json({ error: error.message }, { status: 400 })
      await log({ op: 'trust', user_id: input.user_id, level: input.level })
      return NextResponse.json({ ok: true })
    }
    case 'release': {
      const { error } = await admin.from('intake_submissions').update({ status: 'accepted', processing_status: 'queued', reason: `released by ${actorLabel}` }).eq('id', input.submission_id)
      if (error) return NextResponse.json({ error: error.message }, { status: 400 })
      await log({ op: 'release', submission_id: input.submission_id })
      return NextResponse.json({ ok: true })
    }
    case 'limits': {
      const { error } = await admin.from('intake_settings').update({ ...input.patch, updated_by: actorLabel, updated_at: new Date().toISOString() }).eq('id', 1)
      if (error) return NextResponse.json({ error: error.message }, { status: 400 })
      await log({ op: 'limits', patch: input.patch })
      return NextResponse.json({ ok: true })
    }
  }
}
