import { describe, expect, it } from 'vitest'
import {
  canViewPilotPaperwork,
  PAPERWORK_REQUESTED_ACTION,
  paperworkRequestsFromEvents,
  PILOT_ACCESS_SHARED_ACTION,
  pilotAccessFromEvents,
} from '@/lib/domain/pilot'
import { DEFAULT_TEMPLATES, renderTemplate, TEMPLATE_SAMPLE_DATA, TEMPLATE_VARIABLES } from '@/lib/email-templates'

/**
 * Pilot paperwork on the My Pilot tab (Nash, 2026-09-17).
 *
 * Seeing it: "the carrier dispatch usually is the one that invites a pilot
 * dispatch and then the pilot dispatch invites the driver. Now the carrier
 * dispatch should see the paperwork for the pilot dispatch and for the pilot
 * driver… The broker shall not see the paperwork if he was not the one that
 * initiated the invitation for that pilot company."
 *
 * Requesting it: "can be done only by the person that invited the pilot" —
 * the same relation as sharing permits, pinned in pilot-access-sharing.test.
 */

const CARRIER_DISPATCH = 'u-carrier-dispatch'
const BROKER = 'u-broker'
const PILOT_DISPATCH = 'u-pilot-dispatch'
const PILOT_DRIVER = 'u-pilot-driver'
const OTHER_DISPATCHER = 'u-other-dispatcher'

// The chain Nash described: carrier dispatch → pilot dispatch → pilot driver.
const participants = [
  { id: 'row-cd', user_id: CARRIER_DISPATCH, invited_by: null, role: 'dispatcher' },
  { id: 'row-broker', user_id: BROKER, invited_by: CARRIER_DISPATCH, role: 'broker' },
  { id: 'row-pd', user_id: PILOT_DISPATCH, invited_by: CARRIER_DISPATCH, role: 'pilot' },
  { id: 'row-pdrv', user_id: PILOT_DRIVER, invited_by: PILOT_DISPATCH, role: 'pilot' },
  { id: 'row-other', user_id: OTHER_DISPATCHER, invited_by: null, role: 'dispatcher' },
]
const pilotDispatch = participants[2]
const pilotDriver = participants[3]

describe('who may see a pilot’s paperwork', () => {
  it('the carrier dispatch who brought the pilot company in sees the pilot dispatch AND the driver they added', () => {
    expect(canViewPilotPaperwork({ pilot: pilotDispatch, participants, viewerUserId: CARRIER_DISPATCH, viewerIsAdmin: false })).toBe(true)
    expect(canViewPilotPaperwork({ pilot: pilotDriver, participants, viewerUserId: CARRIER_DISPATCH, viewerIsAdmin: false })).toBe(true)
  })

  it('the pilot dispatch sees the driver they invited', () => {
    expect(canViewPilotPaperwork({ pilot: pilotDriver, participants, viewerUserId: PILOT_DISPATCH, viewerIsAdmin: false })).toBe(true)
  })

  it('a broker who did not initiate the invitation sees nothing — for the dispatch or its driver', () => {
    expect(canViewPilotPaperwork({ pilot: pilotDispatch, participants, viewerUserId: BROKER, viewerIsAdmin: false })).toBe(false)
    expect(canViewPilotPaperwork({ pilot: pilotDriver, participants, viewerUserId: BROKER, viewerIsAdmin: false })).toBe(false)
  })

  it('a broker who DID bring the pilot company in sees the whole chain under it', () => {
    const brokerChain = [
      { id: 'row-broker', user_id: BROKER, invited_by: null, role: 'broker' },
      { id: 'row-pd', user_id: PILOT_DISPATCH, invited_by: BROKER, role: 'pilot' },
      { id: 'row-pdrv', user_id: PILOT_DRIVER, invited_by: PILOT_DISPATCH, role: 'pilot' },
    ]
    expect(canViewPilotPaperwork({ pilot: brokerChain[1], participants: brokerChain, viewerUserId: BROKER, viewerIsAdmin: false })).toBe(true)
    expect(canViewPilotPaperwork({ pilot: brokerChain[2], participants: brokerChain, viewerUserId: BROKER, viewerIsAdmin: false })).toBe(true)
  })

  it('another dispatcher on the trip who is not in the chain sees nothing', () => {
    expect(canViewPilotPaperwork({ pilot: pilotDriver, participants, viewerUserId: OTHER_DISPATCHER, viewerIsAdmin: false })).toBe(false)
  })

  it('the chain stops at a non-pilot: a pilot invited by a driver is not "under" whoever invited the driver', () => {
    const chain = [
      { id: 'r1', user_id: 'u-dispatch', invited_by: null, role: 'dispatcher' },
      { id: 'r2', user_id: 'u-truck-driver', invited_by: 'u-dispatch', role: 'driver' },
      { id: 'r3', user_id: 'u-pilot', invited_by: 'u-truck-driver', role: 'pilot' },
    ]
    // The truck driver invited the pilot — the truck driver sees the paperwork…
    expect(canViewPilotPaperwork({ pilot: chain[2], participants: chain, viewerUserId: 'u-truck-driver', viewerIsAdmin: false })).toBe(true)
    // …the dispatcher who merely invited the truck driver does not.
    expect(canViewPilotPaperwork({ pilot: chain[2], participants: chain, viewerUserId: 'u-dispatch', viewerIsAdmin: false })).toBe(false)
  })

  it('admin always sees it', () => {
    expect(canViewPilotPaperwork({ pilot: pilotDriver, participants, viewerUserId: 'u-admin', viewerIsAdmin: true })).toBe(true)
  })

  it('is safe on a cycle in the data', () => {
    const loop = [
      { id: 'a', user_id: 'u-a', invited_by: 'u-b', role: 'pilot' },
      { id: 'b', user_id: 'u-b', invited_by: 'u-a', role: 'pilot' },
    ]
    expect(canViewPilotPaperwork({ pilot: loop[0], participants: loop, viewerUserId: 'u-nobody', viewerIsAdmin: false })).toBe(false)
  })
})

describe('what a share actually changes on the tab (the bug: nothing was shown after sharing)', () => {
  it('the tab reads the share event, so "Currently: States: CA" appears after sharing California', () => {
    const history = [
      { action: 'participant_invited', detail: { email: 'pilot@example.com', pilot_access: 'Decide later' } },
      { action: PILOT_ACCESS_SHARED_ACTION, detail: { email: 'pilot@example.com', pilot_access: 'States: CA' } },
    ]
    expect(pilotAccessFromEvents(history)['pilot@example.com']).toBe('States: CA')
  })
})

describe('paperwork request history', () => {
  it('keeps the newest request per pilot', () => {
    const at = paperworkRequestsFromEvents([
      { action: PAPERWORK_REQUESTED_ACTION, detail: { email: 'P@e.com' }, created_at: '2026-09-10T00:00:00Z' },
      { action: PAPERWORK_REQUESTED_ACTION, detail: { email: 'p@e.com' }, created_at: '2026-09-17T00:00:00Z' },
      { action: 'document_uploaded', detail: { email: 'p@e.com' }, created_at: '2026-09-18T00:00:00Z' },
    ])
    expect(at).toEqual({ 'p@e.com': '2026-09-17T00:00:00Z' })
  })
})

describe('the paperwork request email', () => {
  const template = DEFAULT_TEMPLATES.find((t) => t.key === 'pilot_paperwork_request')!

  it('ships as a default template the admin can edit', () => {
    expect(template).toBeDefined()
    expect(template.subject).toContain('{{requester_name}}')
    expect(template.body).toContain('{{paperwork_list}}')
  })

  it('every variable it uses is registered and has sample data — so the admin preview never shows a raw placeholder', () => {
    const used = [...`${template.subject}\n${template.body}`.matchAll(/\{\{(\w+)\}\}/g)].map((m) => m[1])
    for (const v of used) {
      expect(TEMPLATE_VARIABLES as readonly string[]).toContain(v)
      expect(TEMPLATE_SAMPLE_DATA[v]).toBeDefined()
    }
    const rendered = renderTemplate(template.body, TEMPLATE_SAMPLE_DATA)
    expect(rendered).not.toMatch(/\{\{\w+\}\}/)
  })
})
