/**
 * One account, several roles, one active mode (Nash, 2026-09-24).
 *
 * "A single person may legitimately be a Carrier Dispatcher, a Carrier Driver,
 * a Freight Broker… One User Account → Multiple Roles / Memberships → One Active
 * Mode at a time." The user says MODE; the code says context.
 *
 * A context is a role AT a company — never a bare role, because the same
 * person may dispatch for two carriers (§8). Pure rules; the I/O lives in
 * src/lib/data/modes.ts.
 */
import { PAGE_CONTEXT_LABELS, dashboardPath, type PageContext } from '@/lib/page-context'

/* --------------------------------------------------------------- roles */

export type RoleType =
  | 'carrier_dispatcher'
  | 'carrier_driver'
  | 'freight_broker'
  | 'pilot_company_dispatch'
  | 'pilot_driver'
  /** Carrier office roles with Carrier Dispatcher powers (Nash, 2026-09-30, migration 0050). */
  | 'carrier_safety_manager'
  | 'carrier_permit_manager'
  | 'carrier_accounting'
  | 'carrier_fleet_manager'
export const ROLE_TYPES: RoleType[] = [
  'carrier_dispatcher', 'carrier_driver', 'freight_broker', 'pilot_company_dispatch', 'pilot_driver',
  'carrier_safety_manager', 'carrier_permit_manager', 'carrier_accounting', 'carrier_fleet_manager',
]

/**
 * The carrier office roles. Nash (2026-09-30): "they all will have the same
 * powers as dispatchers do … Safety Manager, Permit Manager, Accounting,
 * Fleet Manager … any Carrier Dispatch will have the same powers as any other
 * Carrier members besides the Carrier drivers." One mode, one workspace, one
 * trip role (`dispatcher`); only the title differs.
 */
export const CARRIER_DISPATCH_ROLES: RoleType[] = [
  'carrier_dispatcher', 'carrier_safety_manager', 'carrier_permit_manager', 'carrier_accounting', 'carrier_fleet_manager',
]
export function isCarrierDispatchRole(role: string | null | undefined): role is RoleType {
  return !!role && (CARRIER_DISPATCH_ROLES as string[]).includes(role)
}
/** The roles a carrier company may hand out (invites, sign-up, Roles & Workspaces). */
export const CARRIER_COMPANY_ROLES: RoleType[] = [...CARRIER_DISPATCH_ROLES, 'carrier_driver']

/** What the user calls each mode. */
export const MODE_LABELS: Record<RoleType, string> = {
  carrier_dispatcher: 'Carrier Dispatch Mode',
  carrier_driver: 'Carrier Driver Mode',
  freight_broker: 'Freight Broker Mode',
  pilot_company_dispatch: 'Pilot Company Mode',
  pilot_driver: 'Pilot Driver Mode',
  carrier_safety_manager: 'Carrier Dispatch Mode',
  carrier_permit_manager: 'Carrier Dispatch Mode',
  carrier_accounting: 'Carrier Dispatch Mode',
  carrier_fleet_manager: 'Carrier Dispatch Mode',
}

/** The role's own name, for a list of relationships. */
export const ROLE_LABELS: Record<RoleType, string> = {
  carrier_dispatcher: 'Carrier Dispatcher',
  carrier_driver: 'Carrier Driver',
  freight_broker: 'Freight Broker',
  pilot_company_dispatch: 'Pilot Company Dispatcher',
  pilot_driver: 'Pilot Driver',
  carrier_safety_manager: 'Safety Manager',
  carrier_permit_manager: 'Permit Manager',
  carrier_accounting: 'Accounting',
  carrier_fleet_manager: 'Fleet Manager',
}

/** Which of the five page groups a role opens (§11 — they never merge). */
export const ROLE_CONTEXT: Record<RoleType, PageContext> = {
  carrier_dispatcher: 'carrier',
  carrier_driver: 'carrier-driver',
  freight_broker: 'broker',
  pilot_company_dispatch: 'pilot-company',
  pilot_driver: 'pilot-driver',
  carrier_safety_manager: 'carrier',
  carrier_permit_manager: 'carrier',
  carrier_accounting: 'carrier',
  carrier_fleet_manager: 'carrier',
}

export function contextForRoleType(role: RoleType): PageContext {
  return ROLE_CONTEXT[role]
}

/** The role behind a page group, for resolving a deep link into a mode. */
export function roleTypesForContext(ctx: PageContext): RoleType[] {
  return ROLE_TYPES.filter((r) => ROLE_CONTEXT[r] === ctx)
}

/** The account role an env / self-service login carries, as a role type. */
export function roleTypeForAccountRole(accountRole: string): RoleType | null {
  if (accountRole === 'dispatcher') return 'carrier_dispatcher'
  if (accountRole === 'driver') return 'carrier_driver'
  if (accountRole === 'broker') return 'freight_broker'
  return null
}

/* ------------------------------------------------------------ contexts */

export type ContextStatus = 'active' | 'pending' | 'removed_by_user' | 'revoked'

export interface UserContext {
  /** membership_roles.id, or `account:<role_type>` for a role with no company behind it. */
  key: string
  roleType: RoleType
  pageContext: PageContext
  status: ContextStatus
  companyId: string | null
  companyName: string | null
  /** company_memberships.permission_level. */
  permission: 'member' | 'company_admin'
  /** True when the role comes from the account itself rather than a company relationship. */
  independent: boolean
  addedAt: string | null
  removedAt: string | null
  removedBy: string | null
}

export const ACCOUNT_KEY_PREFIX = 'account:'

export function accountContextKey(role: RoleType): string {
  return `${ACCOUNT_KEY_PREFIX}${role}`
}

export function isAccountContextKey(key: string | null | undefined): boolean {
  return !!key && key.startsWith(ACCOUNT_KEY_PREFIX)
}

export function roleTypeFromAccountKey(key: string): RoleType | null {
  const raw = key.slice(ACCOUNT_KEY_PREFIX.length)
  return (ROLE_TYPES as string[]).includes(raw) ? (raw as RoleType) : null
}

/** How a context reads in a menu: "Carrier Dispatcher — ABC Transport LLC". */
export function contextLabel(c: UserContext): string {
  return `${ROLE_LABELS[c.roleType]} — ${c.companyName ?? 'Independent'}`
}

export function contextDashboard(c: UserContext): string {
  return dashboardPath(c.pageContext)
}

export function contextGroupLabel(c: UserContext): string {
  return PAGE_CONTEXT_LABELS[c.pageContext]
}

/** §6 / §28: only a verified, active role is a mode the person can enter. */
export function switchableContexts(contexts: UserContext[]): UserContext[] {
  return contexts.filter((c) => c.status === 'active')
}

export function pendingContexts(contexts: UserContext[]): UserContext[] {
  return contexts.filter((c) => c.status === 'pending')
}

/** §29: rejected and revoked roles are history, never a mode. */
export function pastContexts(contexts: UserContext[]): UserContext[] {
  return contexts.filter((c) => c.status === 'removed_by_user' || c.status === 'revoked')
}

export function findContext(contexts: UserContext[], key: string | null | undefined): UserContext | null {
  if (!key) return null
  return contexts.find((c) => c.key === key) ?? null
}

/* -------------------------------------------------------------- landing */

export type Landing =
  /** One active role, or a usable default — open it. */
  | { kind: 'open'; context: UserContext }
  /** Several active roles and no usable default — ask (§6). */
  | { kind: 'choose'; contexts: UserContext[] }
  /** Nothing active: pending or past roles only. */
  | { kind: 'none'; pending: UserContext[] }

/**
 * Where a sign-in lands (§5, §6, §7). A single active role opens straight
 * away; a stored default opens straight away; otherwise the person chooses.
 */
export function resolveLanding(contexts: UserContext[], defaultKey: string | null | undefined): Landing {
  const active = switchableContexts(contexts)
  if (active.length === 0) return { kind: 'none', pending: pendingContexts(contexts) }
  if (active.length === 1) return { kind: 'open', context: active[0] }
  const preferred = findContext(active, defaultKey)
  if (preferred) return { kind: 'open', context: preferred }
  return { kind: 'choose', contexts: active }
}

/* ------------------------------------------------------------ switching */

export type SwitchDecision = { ok: true; context: UserContext } | { ok: false; reason: string }

/**
 * §26: a person may only enter a role they actually hold, that is active, and
 * whose company relationship is verified. The requested key is never trusted.
 */
export function decideSwitch(contexts: UserContext[], key: string): SwitchDecision {
  const found = findContext(contexts, key)
  if (!found) return { ok: false, reason: 'That workspace is not on your account.' }
  if (found.status === 'pending') return { ok: false, reason: `${contextLabel(found)} is still waiting for verification.` }
  if (found.status === 'revoked') return { ok: false, reason: `Your access to ${contextLabel(found)} was revoked.` }
  if (found.status === 'removed_by_user') return { ok: false, reason: `You removed ${contextLabel(found)} from your account.` }
  return { ok: true, context: found }
}

/* ------------------------------------------------------------- removal */

export type RemovalDecision = { ok: true; warning: string } | { ok: false; reason: string }

/**
 * §19–§22, §32: a person may drop a role they no longer need. The company
 * relationship and every other role survive. The only Company Admin of a
 * company cannot walk away and orphan it.
 */
export function decideRemoval(params: {
  contexts: UserContext[]
  key: string
  /** How many active Company Admins that company has, including this person. */
  companyAdminCount: number
}): RemovalDecision {
  const target = findContext(params.contexts, params.key)
  if (!target) return { ok: false, reason: 'That workspace is not on your account.' }
  if (target.independent) return { ok: false, reason: 'This role comes from your account itself. Ask HeavyHaul Agent support to change it.' }
  if (target.status !== 'active' && target.status !== 'pending') return { ok: false, reason: 'That role is already inactive.' }
  const siblings = params.contexts.filter((c) => c.companyId === target.companyId && c.key !== target.key && c.status === 'active')
  if (target.permission === 'company_admin' && params.companyAdminCount <= 1 && siblings.length === 0) {
    return { ok: false, reason: `You are the only Company Admin for ${target.companyName ?? 'this company'}. Assign another Company Admin before removing this role.` }
  }
  const keeps = siblings.length
    ? ` You stay ${siblings.map((s) => ROLE_LABELS[s.roleType]).join(' and ')} for ${target.companyName ?? 'the same company'}.`
    : ''
  return {
    ok: true,
    warning: `You will lose access to ${MODE_LABELS[target.roleType].replace(' Mode', '')} tools and ${ROLE_LABELS[target.roleType].toLowerCase()} trip views for ${target.companyName ?? 'this company'}. Your HeavyHaul Agent account and your other roles stay active.${keeps}`,
  }
}

/**
 * §30, §31: what happens after a role is removed — the default may need
 * clearing, and someone standing in the removed role must be moved out.
 */
export function afterRemoval(params: { contexts: UserContext[]; removedKey: string; defaultKey: string | null; activeKey: string | null }): {
  clearDefault: boolean
  nextActive: UserContext | null
  needsChoice: boolean
  redirect: string
} {
  const remaining = switchableContexts(params.contexts).filter((c) => c.key !== params.removedKey)
  const clearDefault = params.defaultKey === params.removedKey
  const wasActive = params.activeKey === params.removedKey
  if (remaining.length === 0) return { clearDefault, nextActive: null, needsChoice: false, redirect: '/profile' }
  if (remaining.length === 1) return { clearDefault, nextActive: remaining[0], needsChoice: false, redirect: wasActive || clearDefault ? contextDashboard(remaining[0]) : '/settings/roles' }
  const keptDefault = clearDefault ? null : findContext(remaining, params.defaultKey)
  if (wasActive) return { clearDefault, nextActive: keptDefault, needsChoice: !keptDefault, redirect: keptDefault ? contextDashboard(keptDefault) : '/modes' }
  return { clearDefault, nextActive: null, needsChoice: clearDefault, redirect: '/settings/roles' }
}

/* --------------------------------------------------------- deep links */

export type DeepLinkDecision =
  | { kind: 'open' }
  | { kind: 'switch'; context: UserContext; message: string }
  | { kind: 'deny'; message: string }

/**
 * §34: a link to something that belongs to another of the person's workspaces
 * offers to switch. A link to something they hold no role for is refused —
 * holding one role never opens another's resource.
 */
export function decideDeepLink(params: {
  contexts: UserContext[]
  activeKey: string | null
  /** The page group the link opens. */
  required: PageContext
  /** The company the resource belongs to, when known. */
  companyId?: string | null
  resourceLabel?: string
}): DeepLinkDecision {
  const active = findContext(params.contexts, params.activeKey)
  if (active && active.pageContext === params.required && (!params.companyId || active.companyId === params.companyId)) return { kind: 'open' }
  const candidates = switchableContexts(params.contexts).filter(
    (c) => c.pageContext === params.required && (!params.companyId || c.companyId === params.companyId),
  )
  if (candidates.length === 0) {
    return { kind: 'deny', message: `${params.resourceLabel ?? 'This item'} belongs to a workspace you do not have access to.` }
  }
  const target = candidates[0]
  return {
    kind: 'switch',
    context: target,
    message: `${params.resourceLabel ?? 'This item'} belongs to your ${contextLabel(target)} workspace.`,
  }
}

/* ---------------------------------------------------------------- admin */

/**
 * §13–§17: one elevated platform role, called Admin. Its universal access
 * comes from the platform role, never from pretend memberships, so opening a
 * product view is a preview and creates nothing.
 */
export interface AdminWorkspace {
  key: string
  label: string
  href: string
  group: 'admin' | 'product'
  /** The page group it previews; null for admin tools. */
  pageContext: PageContext | null
}

export const ADMIN_WORKSPACES: AdminWorkspace[] = [
  { key: 'admin_dashboard', label: 'Admin Dashboard', href: '/admin/users', group: 'admin', pageContext: null },
  { key: 'moderator_tools', label: 'Moderator Tools', href: '/admin/moderation', group: 'admin', pageContext: null },
  { key: 'broker', label: 'Broker Dashboard', href: '/fb-dashboard', group: 'product', pageContext: 'broker' },
  { key: 'carrier', label: 'Carrier Dashboard', href: '/cd-dashboard', group: 'product', pageContext: 'carrier' },
  { key: 'pilot_company', label: 'Pilot Company Dashboard', href: '/pd-dashboard', group: 'product', pageContext: 'pilot-company' },
  { key: 'carrier_driver', label: 'Carrier Driver App', href: '/ct-dashboard', group: 'product', pageContext: 'carrier-driver' },
  { key: 'pilot_driver', label: 'Pilot Driver App', href: '/pc-dashboard', group: 'product', pageContext: 'pilot-driver' },
]

export const ADMIN_HOME = '/admin/moderation'

export function adminWorkspace(key: string | null | undefined): AdminWorkspace | null {
  return ADMIN_WORKSPACES.find((w) => w.key === key) ?? null
}

export function adminWorkspaceForContext(ctx: PageContext): AdminWorkspace | null {
  return ADMIN_WORKSPACES.find((w) => w.pageContext === ctx) ?? null
}

/** §16: previewing a product view is never a membership. */
export function isAdminPreview(w: AdminWorkspace | null): boolean {
  return !!w && w.group === 'product'
}
