import Link from 'next/link'
import { AppShell } from '@/components/app/app-shell'
import { BackLink } from '@/components/app/back-link'
import { requireSurface } from '@/lib/auth/surface-guard'
import { createAdminClient } from '@/lib/supabase/admin'
import { nowMs } from '@/lib/domain/time'

type Area = 'all' | 'trip' | 'permit' | 'email' | 'security' | 'intake' | 'company' | 'roles' | 'pilot' | 'broker' | 'moderation' | 'integration' | 'ai' | 'system'
type Window = '30m' | '24h' | '7d'
type LogRow = {
  id: string
  at: string
  area: Exclude<Area, 'all'>
  event: string
  outcome: string
  summary: string
  tripId?: string | null
  tripRef?: string | null
}

const WINDOW_MS: Record<Window, number> = { '30m': 30 * 60_000, '24h': 24 * 60 * 60_000, '7d': 7 * 24 * 60 * 60_000 }
const AREAS: Area[] = ['all', 'trip', 'permit', 'email', 'security', 'intake', 'company', 'roles', 'pilot', 'broker', 'moderation', 'integration', 'ai', 'system']
const LIMIT = 150

const label = (value: string) => value.replaceAll('_', ' ').replace(/\b\w/g, (letter) => letter.toUpperCase())
const brief = (value: unknown) => String(value ?? '').slice(0, 300)
const tripArea = (action: string): Exclude<Area, 'all'> =>
  action.startsWith('synchron_') ? 'integration' : /permit|dimension|warning|document/.test(action) ? 'permit' : 'trip'
const outcomeClass = (outcome: string) => {
  if (['failed', 'hard_bounced', 'soft_bounced', 'complained', 'blocked', 'rejected'].includes(outcome)) return 'bg-red-50 text-red-700'
  if (['skipped', 'suppressed', 'recorded_not_delivered', 'pending', 'retry'].includes(outcome)) return 'bg-amber-50 text-amber-800'
  return 'bg-green-50 text-green-700'
}

/** Admin-only read model over the existing audit logs plus operation_events. */
export default async function OperationsPage({ searchParams }: {
  searchParams: Promise<{ window?: string | string[]; area?: string | string[]; trip?: string | string[] }>
}) {
  const { profile } = await requireSurface('operations')
  const query = await searchParams
  const selectedWindow = typeof query.window === 'string' ? query.window : ''
  const selectedArea = typeof query.area === 'string' ? query.area : ''
  const window: Window = selectedWindow === '30m' || selectedWindow === '7d' ? selectedWindow : '24h'
  const area: Area = AREAS.includes(selectedArea as Area) ? selectedArea as Area : 'all'
  const trip = (typeof query.trip === 'string' ? query.trip : '').trim().slice(0, 40)
  const since = new Date(nowMs() - WINDOW_MS[window]).toISOString()
  const admin = createAdminClient()

  const [operations, trips, emails, security, intake, companies, roles, pilots, brokers, permitCosts, access, tickets, ruleEvents] = await Promise.all([
    admin.from('operation_events').select('id,area,event,outcome,trip_id,permit_id,document_id,detail,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('trip_events').select('id,trip_id,actor_label,action,detail,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('email_messages').select('id,recipient_email,template_key,status,subject,error,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('security_events').select('id,event,username,actor_label,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('intake_submissions').select('id,trip_id,status,reason,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('company_audit_log').select('id,event_type,actor_label,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('role_audit_log').select('id,action,actor_label,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('pilot_network_audit_log').select('id,action,entity_type,actor_label,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('broker_lead_events').select('id,event_type,actor_label,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('permit_cost_history').select('id,trip_id,permit_id,previous_amount,new_amount,source,actor_label,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('moderator_access_log').select('id,surface,action,actor_label,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    admin.from('ticket_events').select('id,action,actor,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
    // Auto-Participant rule audit (migration 0049, §34).
    admin.from('auto_participant_rule_events').select('id,event,actor_label,trip_id,created_at').gte('created_at', since).order('created_at', { ascending: false }).limit(LIMIT),
  ])

  // Rule events are mirrored into operation_events as `auto_participant_*`;
  // when the direct source loaded, show each event once (the direct row).
  const mirroredRuleEvent = (row: { event: string }) => !ruleEvents.error && row.event.startsWith('auto_participant_')
  const rows: LogRow[] = [
    ...((operations.data ?? []) as Array<{ id: string; area: Exclude<Area, 'all'>; event: string; outcome: string; trip_id: string | null; permit_id: string | null; document_id: string | null; detail: Record<string, unknown> | null; created_at: string }>).filter((row) => !mirroredRuleEvent(row)).map((row) => ({
      id: `operation:${row.id}`, at: row.created_at, area: row.area, event: row.event, outcome: row.outcome,
      summary: [row.permit_id ? `Permit ${row.permit_id.slice(0, 8)}` : '', row.document_id ? `Document ${row.document_id.slice(0, 8)}` : '', Object.entries(row.detail ?? {}).map(([key, value]) => `${label(key)}: ${brief(value)}`).join(' · ')].filter(Boolean).join(' · '),
      tripId: row.trip_id,
    })),
    ...((trips.data ?? []) as Array<{ id: string; trip_id: string; actor_label: string; action: string; created_at: string }>).map((row) => ({
      id: `trip:${row.id}`, at: row.created_at, area: tripArea(row.action), event: row.action, outcome: 'success', summary: `By ${brief(row.actor_label)}`, tripId: row.trip_id,
    })),
    ...((emails.data ?? []) as Array<{ id: string; recipient_email: string; template_key: string | null; status: string; subject: string | null; error: string | null; created_at: string }>).map((row) => ({
      id: `email:${row.id}`, at: row.created_at, area: 'email' as const, event: row.template_key || 'email', outcome: row.status,
      summary: `${brief(row.recipient_email)}${row.subject ? ` · ${brief(row.subject)}` : ''}${row.error ? ` · ${brief(row.error)}` : ''}`,
    })),
    ...((security.data ?? []) as Array<{ id: string; event: string; username: string | null; actor_label: string | null; created_at: string }>).map((row) => ({
      id: `security:${row.id}`, at: row.created_at, area: 'security' as const, event: row.event,
      outcome: /failed|denied|locked|limited/.test(row.event) ? 'failed' : 'success', summary: brief(row.actor_label || row.username),
    })),
    ...((intake.data ?? []) as Array<{ id: string; trip_id: string | null; status: string; reason: string | null; created_at: string }>).map((row) => ({
      id: `intake:${row.id}`, at: row.created_at, area: 'intake' as const, event: 'submission', outcome: row.status,
      summary: row.reason ? brief(row.reason) : 'Broker intake submission', tripId: row.trip_id,
    })),
    ...((companies.data ?? []) as Array<{ id: string; event_type: string; actor_label: string; created_at: string }>).map((row) => ({
      id: `company:${row.id}`, at: row.created_at, area: 'company' as const, event: row.event_type, outcome: 'success', summary: `By ${brief(row.actor_label)}`,
    })),
    ...((roles.data ?? []) as Array<{ id: string; action: string; actor_label: string; created_at: string }>).map((row) => ({
      id: `roles:${row.id}`, at: row.created_at, area: 'roles' as const, event: row.action, outcome: 'success', summary: `By ${brief(row.actor_label)}`,
    })),
    ...((pilots.data ?? []) as Array<{ id: string; action: string; entity_type: string; actor_label: string; created_at: string }>).map((row) => ({
      id: `pilot:${row.id}`, at: row.created_at, area: 'pilot' as const, event: row.action, outcome: 'success', summary: `${label(row.entity_type)} · By ${brief(row.actor_label)}`,
    })),
    ...((brokers.data ?? []) as Array<{ id: string; event_type: string; actor_label: string | null; created_at: string }>).map((row) => ({
      id: `broker:${row.id}`, at: row.created_at, area: 'broker' as const, event: row.event_type,
      outcome: row.event_type.includes('failed') ? 'failed' : row.event_type.includes('skipped') ? 'skipped' : 'success', summary: row.actor_label ? `By ${brief(row.actor_label)}` : 'Broker lead activity',
    })),
    ...((permitCosts.data ?? []) as Array<{ id: string; trip_id: string; permit_id: string; previous_amount: number | null; new_amount: number | null; source: string; actor_label: string; created_at: string }>).map((row) => ({
      id: `cost:${row.id}`, at: row.created_at, area: 'permit' as const, event: 'permit_cost_changed', outcome: 'success',
      summary: `${row.source} · ${row.previous_amount ?? '—'} → ${row.new_amount ?? '—'} · By ${brief(row.actor_label)}`, tripId: row.trip_id,
    })),
    ...((access.data ?? []) as Array<{ id: string; surface: string; action: string; actor_label: string; created_at: string }>).map((row) => ({
      id: `access:${row.id}`, at: row.created_at, area: 'security' as const, event: `moderator_${row.action}`, outcome: 'success', summary: `${label(row.surface)} · By ${brief(row.actor_label)}`,
    })),
    ...((tickets.data ?? []) as Array<{ id: string; action: string; actor: string | null; created_at: string }>).map((row) => ({
      id: `ticket:${row.id}`, at: row.created_at, area: 'moderation' as const, event: row.action, outcome: 'success', summary: row.actor ? `By ${brief(row.actor)}` : 'Review ticket activity',
    })),
    ...((ruleEvents.data ?? []) as Array<{ id: string; event: string; actor_label: string; trip_id: string | null; created_at: string }>).map((row) => ({
      id: `auto-participant:${row.id}`, at: row.created_at, area: 'system' as const, event: row.event, outcome: 'success', summary: `Auto-Participant rule · By ${brief(row.actor_label)}`, tripId: row.trip_id,
    })),
  ]

  const tripIds = [...new Set(rows.map((row) => row.tripId).filter((id): id is string => !!id))]
  const unavailable = Object.entries({ trips, emails, security, intake, companies, roles, pilots, brokers, permitCosts, access, tickets, ruleEvents })
    .filter(([, result]) => !!result.error)
    .map(([name]) => name)
  const tripRefs = new Map<string, string>()
  if (tripIds.length) {
    const chunks = Array.from({ length: Math.ceil(tripIds.length / 100) }, (_, index) => tripIds.slice(index * 100, (index + 1) * 100))
    const refs = await Promise.all(chunks.map((ids) => admin.from('trips').select('id,ref_code').in('id', ids)))
    for (const result of refs) for (const row of result.data ?? []) tripRefs.set(row.id, row.ref_code)
  }
  const visible = rows
    .map((row) => ({ ...row, tripRef: row.tripId ? tripRefs.get(row.tripId) ?? null : null }))
    .filter((row) => area === 'all' || row.area === area)
    .filter((row) => !trip || [row.tripRef, row.summary, row.event].some((value) => value?.toLowerCase().includes(trip.toLowerCase())))
    .sort((a, b) => b.at.localeCompare(a.at))
    .slice(0, 300)

  return (
    <AppShell profile={profile}>
      <main className="mx-auto max-w-6xl space-y-5 px-4 py-8">
        <BackLink />
        <div>
          <h1 className="text-2xl font-bold">Operations log</h1>
          <p className="mt-1 text-sm text-neutral-500">Admin-only activity across trips, permits, email, access, intake, companies, roles, and outreach. Times are shown in UTC.</p>
        </div>
        {operations.error && <p className="rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900">New workflow outcomes could not be loaded. Apply migration 0042 if it is pending; existing logs remain visible.</p>}
        {unavailable.length > 0 && <p className="rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900">Some existing log sources could not be loaded: {unavailable.join(', ')}.</p>}
        <form className="flex flex-wrap items-end gap-3 rounded-xl border bg-white p-4" method="get">
          <label className="text-xs font-semibold text-neutral-600">Window<select name="window" defaultValue={window} className="mt-1 block rounded-md border px-3 py-2 text-sm text-neutral-900"><option value="30m">Last 30 minutes</option><option value="24h">Last 24 hours</option><option value="7d">Last 7 days</option></select></label>
          <label className="text-xs font-semibold text-neutral-600">Area<select name="area" defaultValue={area} className="mt-1 block rounded-md border px-3 py-2 text-sm text-neutral-900">{AREAS.map((item) => <option key={item} value={item}>{label(item)}</option>)}</select></label>
          <label className="min-w-44 flex-1 text-xs font-semibold text-neutral-600">Trip or text<input name="trip" defaultValue={trip} placeholder="HH-20102137" className="mt-1 block w-full rounded-md border px-3 py-2 text-sm text-neutral-900" /></label>
          <button className="rounded-md bg-[#0f1b2d] px-4 py-2 text-sm font-semibold text-white">Search</button>
          <Link href="/admin/operations" className="px-2 py-2 text-sm text-neutral-600 underline">Reset</Link>
        </form>
        <p className="text-xs text-neutral-500">Showing {visible.length} recent records. Each source returns up to {LIMIT} records for the selected window.</p>
        <div className="overflow-x-auto rounded-xl border bg-white">
          <table className="min-w-[760px] w-full text-left text-sm">
            <thead className="border-b bg-neutral-50 text-xs uppercase tracking-wide text-neutral-500"><tr><th className="px-4 py-3">Time</th><th className="px-4 py-3">Area</th><th className="px-4 py-3">Event</th><th className="px-4 py-3">Outcome</th><th className="px-4 py-3">Trip</th><th className="px-4 py-3">Details</th></tr></thead>
            <tbody className="divide-y">
              {visible.map((row) => <tr key={row.id}>
                <td className="whitespace-nowrap px-4 py-3 text-xs text-neutral-500"><time dateTime={row.at} title={row.at}>{new Date(row.at).toLocaleString('en-US', { timeZone: 'UTC', hour12: false })} UTC</time></td>
                <td className="px-4 py-3 font-medium">{label(row.area)}</td>
                <td className="px-4 py-3">{label(row.event)}</td>
                <td className="px-4 py-3"><span className={`rounded-full px-2 py-1 text-xs font-semibold ${outcomeClass(row.outcome)}`}>{label(row.outcome)}</span></td>
                <td className="px-4 py-3">{row.tripRef ? <Link className="font-medium underline" href={`/fb-trip-workspace/${encodeURIComponent(row.tripRef)}`}>{row.tripRef}</Link> : '—'}</td>
                <td className="max-w-md break-words px-4 py-3 text-xs text-neutral-600">{row.summary || '—'}</td>
              </tr>)}
              {!visible.length && <tr><td colSpan={6} className="px-4 py-10 text-center text-neutral-500">No log entries match this window and filter.</td></tr>}
            </tbody>
          </table>
        </div>
      </main>
    </AppShell>
  )
}
