import 'server-only'

import { NextResponse } from 'next/server'
import { getSessionUser, getMyParticipant } from '@/lib/auth'
import type { SessionUser } from '@/lib/auth'
import { adminParticipantFor } from '@/lib/domain/participants'
import type { CompanyMembership, TripParticipant } from '@/types/db'

export type Guard =
  | {
      ok: true
      user: SessionUser
      /**
       * The caller's trip role context. For an admin acting on a trip they
       * are not on, a synthetic row with role `admin` and an empty id.
       */
      participant: TripParticipant
      /**
       * The caller's REAL participant row — null when an admin is acting
       * from outside the trip. Anything that writes to the caller's OWN row
       * (chat privacy, personal completion) must use this, not `participant`.
       */
      row: TripParticipant | null
    }
  | { ok: false; response: NextResponse }

/**
 * Require a signed-in user who may act on this trip: an active participant,
 * or an admin (who may act on every trip, participant or not).
 */
export async function requireParticipant(tripId: string): Promise<Guard> {
  const user = await getSessionUser()
  if (!user) {
    return { ok: false, response: NextResponse.json({ error: 'Sign in first.' }, { status: 401 }) }
  }
  const participant = await getMyParticipant(tripId)
  if (participant) return { ok: true, user, participant, row: participant }
  if (user.role === 'admin') {
    return { ok: true, user, participant: adminParticipantFor(tripId, user), row: null }
  }
  return {
    ok: false,
    response: NextResponse.json({ error: 'You are not a participant on this trip.' }, { status: 403 }),
  }
}

/* ------------------------------------------------ company admin context */

export type CompanyAdminGuard =
  | {
      ok: true
      user: SessionUser
      companyId: string
      company: { id: string; display_name: string; legal_name: string; company_type: string; locked: boolean }
      /** True when a platform admin is acting without a membership. */
      platformAdmin: boolean
    }
  | { ok: false; response: NextResponse }

/**
 * Require Company Admin permission in the caller's ACTIVE mode (Auto-Participants
 * task 7.1, 2026-09-30). Company Admin is `company_memberships.permission_level`,
 * never a role type (§8); the mode names the company, the membership is
 * re-read, and a locked company answers 423 like the company-info APIs.
 * A platform admin may name any company with `companyId`.
 */
export async function requireCompanyAdminContext(opts: { companyId?: string | null } = {}): Promise<CompanyAdminGuard> {
  const user = await getSessionUser()
  if (!user) return { ok: false, response: NextResponse.json({ error: 'Sign in first.' }, { status: 401 }) }
  const { loadActiveMode } = await import('@/lib/data/active-mode')
  const { canManageCarrierCompany } = await import('@/lib/domain/carrier-company')
  const { createAdminClient } = await import('@/lib/supabase/admin')
  const admin = createAdminClient()
  const mode = await loadActiveMode()
  const platformAdmin = user.role === 'admin'
  const companyId = platformAdmin && opts.companyId ? opts.companyId : mode?.active?.companyId ?? null
  if (!companyId) {
    return { ok: false, response: NextResponse.json({ error: platformAdmin ? 'Name a company.' : 'Switch to a company mode first.' }, { status: 403 }) }
  }
  if (!platformAdmin) {
    if (mode?.active?.permission !== 'company_admin') {
      return { ok: false, response: NextResponse.json({ error: 'Company Admin permission is required in this mode.' }, { status: 403 }) }
    }
    const { data: m } = await admin.from('company_memberships').select('status, role, permission_level, company_id').eq('user_id', user.id).eq('company_id', companyId).maybeSingle()
    if (!canManageCarrierCompany({ membership: (m as Pick<CompanyMembership, 'status' | 'role' | 'permission_level' | 'company_id'> | null) ?? null, companyId, viewerIsPlatformAdmin: false })) {
      return { ok: false, response: NextResponse.json({ error: 'Company Admin permission is required.' }, { status: 403 }) }
    }
  }
  const { data: company } = await admin.from('companies').select('id, display_name, legal_name, company_type, locked').eq('id', companyId).maybeSingle()
  if (!company) return { ok: false, response: NextResponse.json({ error: 'Company not found.' }, { status: 404 }) }
  const c = company as { id: string; display_name: string; legal_name: string; company_type: string; locked: boolean }
  if (c.locked && !platformAdmin) return { ok: false, response: NextResponse.json({ error: 'This company is locked.' }, { status: 423 }) }
  return { ok: true, user, companyId, company: c, platformAdmin }
}
