import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { getSessionUser } from '@/lib/auth'
import { readSession, setSessionCookie } from '@/lib/auth/session'
import { clientIp } from '@/lib/security/rate-limit'
import { adminWorkspace, contextDashboard, isAdminPreview, ADMIN_HOME } from '@/lib/domain/modes'
import { logRoleAction, removeRole, setAdminDefaultWorkspace, setDefaultContext, switchContext } from '@/lib/data/modes'
import { loadActiveMode } from '@/lib/data/active-mode'
import { afterRemoval } from '@/lib/domain/modes'

/**
 * Switch Mode, default mode, and removing a role (Nash, 2026-09-24).
 *
 * Every request is checked against the roles the person actually holds — the
 * key in the request is never trusted (§25, §26). An admin previewing a
 * product view creates no membership (§16, §27).
 */
const schema = z.discriminatedUnion('op', [
  z.object({ op: z.literal('switch'), key: z.string().min(1).max(120), set_default: z.boolean().optional() }),
  z.object({ op: z.literal('set_default'), key: z.string().min(1).max(120).nullable() }),
  z.object({ op: z.literal('remove_role'), key: z.string().min(1).max(120) }),
  z.object({ op: z.literal('admin_preview'), workspace: z.string().min(1).max(60), set_default: z.boolean().optional() }),
  z.object({ op: z.literal('exit_preview') }),
])

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: 'Check the request and try again.' }, { status: 400 })
  const input = parsed.data
  const session = await readSession()
  if (!session) return NextResponse.json({ error: 'Sign in first.' }, { status: 401 })
  const actor = { id: user.id, label: user.name || user.email }
  const account = { id: user.id, email: user.email, name: user.name, role: user.role }
  const ip = clientIp(req.headers)

  /* ---- Admin preview: authorised platform access, never a membership ---- */
  if (input.op === 'admin_preview') {
    if (user.role !== 'admin') return NextResponse.json({ error: 'Only the HeavyHaul Agent admin can open a product preview.' }, { status: 403 })
    const w = adminWorkspace(input.workspace)
    if (!w) return NextResponse.json({ error: 'Unknown workspace.' }, { status: 400 })
    await setSessionCookie({ ...session, preview: isAdminPreview(w) ? w.key : null })
    if (input.set_default) await setAdminDefaultWorkspace(account, w.key, actor)
    await logRoleAction({ userId: user.id, action: isAdminPreview(w) ? 'admin_preview_entered' : 'admin_preview_exited', actor, detail: { workspace: w.key, ip } })
    return NextResponse.json({ ok: true, next: w.href, preview: isAdminPreview(w) })
  }
  if (input.op === 'exit_preview') {
    if (user.role !== 'admin') return NextResponse.json({ error: 'Nothing to exit.' }, { status: 403 })
    await setSessionCookie({ ...session, preview: null })
    await logRoleAction({ userId: user.id, action: 'admin_preview_exited', actor, detail: { ip } })
    return NextResponse.json({ ok: true, next: ADMIN_HOME })
  }

  /* ---------------------------- regular users ---------------------------- */
  if (input.op === 'switch') {
    const r = await switchContext(account, input.key, actor)
    if (!r.ok) return NextResponse.json({ error: r.error }, { status: 403 })
    await setSessionCookie({ ...session, ctx: input.key, preview: null })
    if (input.set_default) await setDefaultContext(account, input.key, actor)
    return NextResponse.json({ ok: true, next: contextDashboard(r.context), mode: { key: r.context.key, label: r.context.roleType, company: r.context.companyName } })
  }

  if (input.op === 'set_default') {
    const r = await setDefaultContext(account, input.key, actor)
    return r.ok ? NextResponse.json({ ok: true }) : NextResponse.json({ error: r.error }, { status: 400 })
  }

  // remove_role
  const mode = await loadActiveMode()
  const r = await removeRole(account, input.key, actor)
  if (!r.ok) return NextResponse.json({ error: r.error }, { status: 400 })
  const next = afterRemoval({
    contexts: mode?.contexts ?? [],
    removedKey: input.key,
    defaultKey: mode?.defaultKey ?? null,
    activeKey: user.contextKey ?? null,
  })
  // §31: they must not carry on inside the role they just removed.
  if (user.contextKey === input.key) await setSessionCookie({ ...session, ctx: next.nextActive?.key ?? null })
  return NextResponse.json({ ok: true, removed: r.removed.roleType, next: next.redirect, needs_choice: next.needsChoice, cleared_default: next.clearDefault })
}
