import { describe, expect, it } from 'vitest'
import {
  businessLicenseDaysLeft,
  canViewSharedPermits,
  computeReadiness,
  PILOT_CAPABILITIES,
  PILOT_COMPANY_DOCUMENTS,
  PILOT_DRIVER_DOCUMENTS,
  onboardingTasks,
  pilotCanViewRateConfirmation,
  VEHICLE_PHOTO_SIDES,
  type ReadinessInput,
} from '@/lib/domain/pilot'
import { pilotPreviewView } from '@/lib/role-view'

/** Pilot car domain rules (article, 2026-09-12). */

const driverBase: ReadinessInput = {
  accountType: 'pilot_driver',
  name: 'Dana Whitfield',
  phone: '(614) 555-0198',
  emailVerified: true,
  documents: {
    w9: 'Uploaded',
    driver_license: 'Uploaded',
    insurance: 'Uploaded',
    pilot_certification: 'Uploaded',
  },
  createdAt: '2026-09-01',
  today: '2026-09-12',
}

describe('document slots (§10, §11)', () => {
  it('pilot driver: W-9, license, insurance, certification required; state certs optional', () => {
    const required = PILOT_DRIVER_DOCUMENTS.filter((s) => s.required).map((s) => s.key)
    expect(required).toEqual(['w9', 'driver_license', 'insurance', 'pilot_certification'])
    const optional = PILOT_DRIVER_DOCUMENTS.filter((s) => !s.required).map((s) => s.label)
    expect(optional).toEqual([
      'Optional State Certification',
      'Utah Certification, if applicable',
      'Washington Certification, if applicable',
    ])
  })

  it('pilot company: insurance, W-9 and business license required', () => {
    expect(PILOT_COMPANY_DOCUMENTS.filter((s) => s.required).map((s) => s.key)).toEqual([
      'insurance',
      'w9',
      'business_license',
    ])
  })

  it('W-9 never expires; insurance, licenses and certifications do (§59)', () => {
    expect(PILOT_DRIVER_DOCUMENTS.find((s) => s.key === 'w9')!.expires).toBe(false)
    expect(PILOT_DRIVER_DOCUMENTS.find((s) => s.key === 'insurance')!.expires).toBe(true)
  })

  it('four required vehicle photos and eleven capabilities (§33, §35)', () => {
    expect(VEHICLE_PHOTO_SIDES).toEqual(['Front', 'Back', 'Left side', 'Right side'])
    expect(PILOT_CAPABILITIES).toHaveLength(11)
    expect(PILOT_CAPABILITIES[0]).toBe('Lead pilot')
  })
})

describe('readiness (§12, §60)', () => {
  it('a complete, validated driver is Ready for Assignment', () => {
    expect(computeReadiness(driverBase)).toBe('Ready for Assignment')
  })

  it('admin verification promotes to Verified Pilot', () => {
    expect(computeReadiness({ ...driverBase, adminVerified: true })).toBe('Verified Pilot')
  })

  it('missing name or phone is Incomplete Profile, before anything else', () => {
    expect(computeReadiness({ ...driverBase, phone: '' })).toBe('Incomplete Profile')
  })

  it('an unvalidated email blocks permits (§9)', () => {
    const status = computeReadiness({ ...driverBase, emailVerified: false })
    expect(status).toBe('Email Not Verified')
    expect(canViewSharedPermits(status)).toBe(false)
  })

  it('missing insurance is called out by name', () => {
    expect(
      computeReadiness({ ...driverBase, documents: { ...driverBase.documents, insurance: 'Not Uploaded' } }),
    ).toBe('Insurance Missing')
  })

  it('any other missing required document is Documents Missing', () => {
    expect(
      computeReadiness({ ...driverBase, documents: { ...driverBase.documents, pilot_certification: undefined } }),
    ).toBe('Documents Missing')
  })

  it('expired documents block even a fully uploaded profile', () => {
    expect(
      computeReadiness({ ...driverBase, documents: { ...driverBase.documents, insurance: 'Expired' } }),
    ).toBe('Expired Documents')
  })

  it('a rejected document needs admin review', () => {
    expect(
      computeReadiness({ ...driverBase, documents: { ...driverBase.documents, driver_license: 'Rejected' } }),
    ).toBe('Admin Review Required')
  })
})

describe('pilot company 30-day business license window (§11)', () => {
  const companyBase: ReadinessInput = {
    accountType: 'pilot_company',
    name: 'Maria Lopez',
    phone: '(614) 555-0142',
    emailVerified: true,
    documents: { insurance: 'Approved', w9: 'Uploaded' },
    createdAt: '2026-09-04',
    today: '2026-09-12',
  }

  it('counts the days left from account creation', () => {
    expect(businessLicenseDaysLeft('2026-09-04', '2026-09-12')).toBe(22)
    expect(businessLicenseDaysLeft('2026-09-04', '2026-10-04')).toBe(0)
    expect(businessLicenseDaysLeft('2026-09-04', '2026-10-05')).toBe(-1)
  })

  it('inside the window the company may still view permits', () => {
    const status = computeReadiness(companyBase)
    expect(status).toBe('Business License Due in 22 Days')
    expect(canViewSharedPermits(status)).toBe(true)
  })

  it('other missing required documents come first', () => {
    expect(computeReadiness({ ...companyBase, documents: { insurance: 'Approved' } })).toBe('Documents Missing')
  })

  it('after 30 days without a license the account is flagged for admin review', () => {
    const status = computeReadiness({ ...companyBase, today: '2026-10-05' })
    expect(status).toBe('Admin Review Required')
    expect(canViewSharedPermits(status)).toBe(false)
  })

  it('an uploaded license makes the company Ready for Assignment', () => {
    expect(
      computeReadiness({ ...companyBase, documents: { ...companyBase.documents, business_license: 'Uploaded' } }),
    ).toBe('Ready for Assignment')
  })
})

describe('rate confirmation (§15)', () => {
  it('is never visible to a pilot, whatever the scope', () => {
    expect(pilotCanViewRateConfirmation()).toBe(false)
  })
})

describe('pilot preview views are internal-only (Task 96 rule)', () => {
  it('resolves for internal accounts', () => {
    expect(pilotPreviewView('pilot-dispatch', true)).toBe('pilot-dispatch')
    expect(pilotPreviewView('pilot-driver', true)).toBe('pilot-driver')
  })
  it('is ignored for customers and unknown values', () => {
    expect(pilotPreviewView('pilot-dispatch', false)).toBeNull()
    expect(pilotPreviewView('driver', true)).toBeNull()
    expect(pilotPreviewView(undefined, true)).toBeNull()
  })
})

describe('post-login onboarding tasks (Nash, 2026-09-12)', () => {
  const base = { accountType: 'pilot_driver' as const, documents: {}, vehiclePhotos: null, capabilityCount: 0 }

  it('lists steps 4, 5 and 6 with what is missing', () => {
    const tasks = onboardingTasks(base)
    expect(tasks.map((t) => t.step)).toEqual([4, 5, 6])
    expect(tasks[0].missing).toEqual(['W-9', 'Driver license', 'Certificate of insurance', 'Pilot car / escort certification'])
    expect(tasks[1].missing).toEqual(['Add your vehicle'])
    expect(tasks[2].done).toBe(false)
  })

  it('an independent driver is the only one who can upload documents', () => {
    expect(onboardingTasks(base)[0].owner).toBe('Only you')
  })

  it('a company-connected driver shares document upload with the company; vehicle and capabilities stay with the driver', () => {
    const tasks = onboardingTasks({ ...base, companyName: 'ABC Pilot Cars' })
    expect(tasks[0].owner).toBe('You or ABC Pilot Cars')
    expect(tasks[1].owner).toBe('Only you')
    expect(tasks[2].owner).toBe('Only you')
  })

  it('counts missing photos on the vehicle and marks steps done', () => {
    const tasks = onboardingTasks({
      ...base,
      documents: { w9: 'Uploaded', driver_license: 'Uploaded', insurance: 'Uploaded', pilot_certification: 'Uploaded' },
      vehiclePhotos: 3,
      capabilityCount: 2,
    })
    expect(tasks[0].done).toBe(true)
    expect(tasks[1].missing).toEqual(['1 of 4 photos'])
    expect(tasks[2].done).toBe(true)
  })

  it('pilot company: the company owns all three steps', () => {
    const tasks = onboardingTasks({ ...base, accountType: 'pilot_company' })
    expect(tasks.every((t) => t.owner === 'Your company')).toBe(true)
    expect(tasks[0].missing).toEqual(['Certificate of insurance', 'W-9', 'Business license'])
  })
})

describe('pilot access chosen at invite time (Nash, 2026-09-12)', () => {
  it('describes every choice in one line for the trip history', async () => {
    const { describePilotAccess } = await import('@/lib/domain/pilot')
    expect(describePilotAccess({ type: 'full_trip' })).toBe('Full trip (all states)')
    expect(describePilotAccess({ type: 'states', states: ['OH', 'PA'] })).toBe('States: OH, PA')
    expect(describePilotAccess({ type: 'permits', permit_ids: ['x'], labels: ['OH · 123'] })).toBe('Permits: OH · 123')
    expect(describePilotAccess({ type: 'decide_later' })).toBe('Decide later')
    expect(describePilotAccess(undefined)).toBe('Decide later')
    expect(describePilotAccess({ type: 'states', states: [] })).toBe('Decide later')
  })

  it('anyone a pilot adds inherits exactly the pilot\'s access', async () => {
    const { inheritedPilotAccess } = await import('@/lib/domain/pilot')
    expect(inheritedPilotAccess({ type: 'states', states: ['OH'] })).toEqual({ type: 'states', states: ['OH'] })
    expect(inheritedPilotAccess(null)).toEqual({ type: 'decide_later' })
  })

  it('a pilot dispatch adds drivers; a pilot driver adds only a dispatch', async () => {
    const { PILOT_INVITE_TARGETS } = await import('@/lib/domain/pilot')
    expect(PILOT_INVITE_TARGETS.pilot_company).toEqual(['Pilot driver'])
    expect(PILOT_INVITE_TARGETS.pilot_driver).toEqual(['Pilot dispatch'])
  })
})

describe('pilot dispatch documents gate on the trip workspace', () => {
  it('COI, W-9 and business license are all required to open a trip', async () => {
    const { missingWorkspaceDocs } = await import('@/lib/domain/pilot')
    expect(missingWorkspaceDocs({}).map((s) => s.key)).toEqual(['insurance', 'w9', 'business_license'])
    expect(missingWorkspaceDocs({ insurance: 'Approved', w9: 'Uploaded' }).map((s) => s.key)).toEqual(['business_license'])
    expect(missingWorkspaceDocs({ insurance: 'Approved', w9: 'Uploaded', business_license: 'Uploaded' })).toEqual([])
  })
})

describe('invoice default recipient = whoever invited the pilot (Nash, 2026-09-12)', () => {
  it('carrier dispatcher, carrier driver or broker', async () => {
    const { DEMO_PILOT_ASSIGNMENTS, inviterOf, tripContactsOf } = await import('@/lib/demo/pilot')
    const byDispatch = DEMO_PILOT_ASSIGNMENTS.find((a) => a.id === 'asg-1')!
    const byDriver = DEMO_PILOT_ASSIGNMENTS.find((a) => a.id === 'asg-2')!
    const byBroker = DEMO_PILOT_ASSIGNMENTS.find((a) => a.id === 'asg-3')!
    expect(inviterOf(byDispatch)).toEqual({ name: 'Kevin Ortiz', email: 'dispatch@ridgelinehh.com', role: 'Carrier dispatcher' })
    expect(inviterOf(byDriver)).toEqual({ name: 'Anita Shaw', email: 'anita.s@ridgelinehh.com', role: 'Carrier driver' })
    expect(inviterOf(byBroker)).toEqual({ name: 'Erin Blake', email: 'erin@summitfreight.com', role: 'Broker' })
    // The dropdown offers the dispatcher and the driver (and the broker when one is on the trip).
    expect(tripContactsOf(byDispatch).map((c) => c.role)).toEqual(['Carrier dispatcher', 'Carrier driver'])
    expect(tripContactsOf(byBroker).map((c) => c.role)).toContain('Broker')
  })
})

describe('pilot cars on the carrier driver state cards (Nash, 2026-09-12)', () => {
  it('reads each pilot\'s access from the invite history, latest wins', async () => {
    const { pilotAccessFromEvents } = await import('@/lib/domain/pilot')
    const access = pilotAccessFromEvents([
      { action: 'participant_invited', detail: { email: 'Pilot@abc.com', role: 'pilot', pilot_access: 'Decide later' } },
      { action: 'participant_invited', detail: { email: 'pilot@abc.com', role: 'pilot', pilot_access: 'States: OH, NM' } },
      { action: 'participant_invited', detail: { email: 'driver@x.com', role: 'driver' } },
      { action: 'document_uploaded', detail: { email: 'pilot@abc.com', pilot_access: 'Full trip (all states)' } },
    ])
    expect(access).toEqual({ 'pilot@abc.com': 'States: OH, NM' })
  })

  it('knows which states an access line covers', async () => {
    const { pilotAccessCoversState } = await import('@/lib/domain/pilot')
    expect(pilotAccessCoversState('Full trip (all states)', 'NM')).toBe(true)
    expect(pilotAccessCoversState('States: OH, NM', 'NM')).toBe(true)
    expect(pilotAccessCoversState('States: OH, NM', 'CA')).toBe(false)
    expect(pilotAccessCoversState('Permits: NM · 12345, OH · 998', 'NM')).toBe(true)
    expect(pilotAccessCoversState('Permits: NM · 12345', 'OH')).toBe(false)
    expect(pilotAccessCoversState('Decide later', 'NM')).toBe(false)
    expect(pilotAccessCoversState(undefined, 'NM')).toBe(false)
  })
})

describe('demo pilot car on New Mexico / Arizona trips (Nash, 2026-09-12)', () => {
  it('John Cena drives, Mark Cuban dispatches, on exactly those two states', async () => {
    const { DEMO_PILOT_ACCESS, demoPilotContacts, isDemoPilotState } = await import('@/lib/demo/pilot-cars')
    const { pilotAccessCoversState } = await import('@/lib/domain/pilot')
    expect(isDemoPilotState('NM')).toBe(true)
    expect(isDemoPilotState('AZ')).toBe(true)
    expect(isDemoPilotState('OH')).toBe(false)
    const pair = demoPilotContacts('trip-1')
    expect(pair.map((p) => [p.name, p.kind])).toEqual([
      ['John Cena', 'Pilot driver'],
      ['Mark Cuban', 'Pilot dispatch'],
    ])
    expect(pair.every((p) => p.role === 'pilot' && p.phone && p.email)).toBe(true)
    expect(pilotAccessCoversState(DEMO_PILOT_ACCESS, 'AZ')).toBe(true)
    expect(pilotAccessCoversState(DEMO_PILOT_ACCESS, 'TX')).toBe(false)
  })
})
