import { describe, expect, it } from 'vitest'
import {
  brokerCompanyView, leadCollision, matchBrokerLead, matchImportedCompany, normalizePhone, parseEmailList,
} from '@/lib/domain/broker-company'
import { renderTemplateClean, DEFAULT_TEMPLATES } from '@/lib/email-templates'
import type { BrokerAgentLead, CompanyMembership } from '@/types/db'

/**
 * Broker Company relationships (Nash, 2026-09-19): two onboarding paths.
 * New agent → MC → verification email → company approves. Pre-verified
 * agent → exact-email match to our historical records → "do you still
 * represent…?" → verified. Name alone never verifies.
 */

const lead = (over: Partial<BrokerAgentLead>): BrokerAgentLead => ({
  id: 'l1', first_name: 'John', last_name: 'Smith', email: 'john@abcfreight.com', email_normalized: 'john@abcfreight.com',
  phone: '(555) 123-4567', phone_digits: '5551234567', broker_company_id: 'c1', broker_company_name: 'ABC Freight Brokerage LLC',
  mc_number: '123456', usdot_number: null, historical_relationship_verified: true, historical_verification_source: 'INTERNAL_HISTORICAL_RECORDS',
  historical_verified_at: null, claim_status: 'unclaimed', relationship_confirmation_status: 'not_confirmed', invitation_status: 'not_invited',
  invited_at: null, claimed_user_id: null, claimed_at: null, confirmed_at: null, manual_review_reason: null, import_batch: null, source_row: null,
  created_at: '2026-09-19', updated_at: '2026-09-19', ...over,
})
const m = (over: Partial<CompanyMembership>): CompanyMembership => ({
  id: 'm1', user_id: 'u1', company_id: 'c1', role: 'freight_broker', status: 'approved', approved_by: null, approved_at: null,
  revoked_by: null, revoked_at: null, created_at: '2026-09-19', ...over,
})

describe('historical matching (§16)', () => {
  const leads = [lead({})]
  it('exact email → strong match (Scenario 2)', () => {
    const r = matchBrokerLead({ email: 'John@ABCFreight.com' }, leads)
    expect(r.strength).toBe('strong')
  })
  it('same name, different email → weak, never auto-verified (Scenario 4)', () => {
    const r = matchBrokerLead({ email: 'johnsmith@gmail.com', fullName: 'John Smith' }, leads)
    expect(r.strength).toBe('weak')
    if (r.strength === 'weak') expect(r.by).toBe('name')
  })
  it('phone match without email → weak', () => {
    const r = matchBrokerLead({ email: 'x@y.com', phone: '+1 555-123-4567' }, leads)
    expect(r.strength).toBe('weak')
  })
  it('claimed leads and unverified records do not match', () => {
    expect(matchBrokerLead({ email: 'john@abcfreight.com' }, [lead({ claim_status: 'claimed' })]).strength).toBe('none')
    expect(matchBrokerLead({ email: 'john@abcfreight.com' }, [lead({ historical_relationship_verified: false })]).strength).toBe('none')
  })
  it('phone normalisation drops the country code', () => {
    expect(normalizePhone('+1 (555) 123-4567')).toBe('5551234567')
    expect(normalizePhone('123')).toBeNull()
  })
})

describe('which Broker Company view', () => {
  it('strong historical match comes first, even with nothing else on file', () => {
    expect(brokerCompanyView({ membership: null, claim: null, historicalMatch: true, viewerIsPlatformAdmin: false })).toBe('historical_confirm')
  })
  it('verified beats a stale historical flag; admin permission → management', () => {
    expect(brokerCompanyView({ membership: m({}), claim: null, historicalMatch: true, viewerIsPlatformAdmin: false })).toBe('verified')
    expect(brokerCompanyView({ membership: m({ permission_level: 'company_admin' }), claim: null, historicalMatch: false, viewerIsPlatformAdmin: false })).toBe('company_admin')
  })
  it('pending / manual review / rejected / revoked / no longer current / none', () => {
    expect(brokerCompanyView({ membership: m({ status: 'pending' }), claim: null, historicalMatch: false, viewerIsPlatformAdmin: false })).toBe('pending')
    expect(brokerCompanyView({ membership: m({ status: 'pending' }), claim: { claim_status: 'admin_review_required' }, historicalMatch: false, viewerIsPlatformAdmin: false })).toBe('manual_review')
    expect(brokerCompanyView({ membership: m({ status: 'rejected' }), claim: null, historicalMatch: false, viewerIsPlatformAdmin: false })).toBe('rejected')
    expect(brokerCompanyView({ membership: m({ status: 'revoked' }), claim: null, historicalMatch: false, viewerIsPlatformAdmin: false })).toBe('revoked')
    expect(brokerCompanyView({ membership: m({ status: 'no_longer_current' }), claim: null, historicalMatch: false, viewerIsPlatformAdmin: false })).toBe('no_longer_current')
    expect(brokerCompanyView({ membership: null, claim: null, historicalMatch: false, viewerIsPlatformAdmin: false })).toBe('none')
    expect(brokerCompanyView({ membership: null, claim: null, historicalMatch: false, viewerIsPlatformAdmin: true })).toBe('company_admin')
  })
})

describe('import matching (§26)', () => {
  const companies = [
    { id: 'a', legal_name: 'ABC FREIGHT BROKERAGE LLC', mc_number: '123456', dot_number: '111' },
    { id: 'b', legal_name: 'XYZ LOGISTICS', mc_number: '222222', dot_number: null },
    { id: 'c', legal_name: 'XYZ LOGISTICS', mc_number: '333333', dot_number: null },
  ]
  it('MC first, USDOT second, name only as a tiebreaker', () => {
    expect(matchImportedCompany({ mc: 'MC-123456' }, companies)).toEqual({ kind: 'match', id: 'a', by: 'mc' })
    expect(matchImportedCompany({ usdot: '111' }, companies)).toEqual({ kind: 'match', id: 'a', by: 'usdot' })
    expect(matchImportedCompany({ company: 'abc freight brokerage llc' }, companies)).toEqual({ kind: 'match', id: 'a', by: 'name' })
    expect(matchImportedCompany({ company: 'NEW CO' }, companies)).toEqual({ kind: 'none' })
  })
  it('two companies with the same name → ambiguous, never silently merged', () => {
    expect(matchImportedCompany({ company: 'XYZ Logistics' }, companies).kind).toBe('ambiguous')
  })
  it('lead collisions: same email other company → ambiguous; same email same company → same', () => {
    const existing = [lead({})]
    expect(leadCollision({ email: 'john@abcfreight.com' }, 'c1', existing)).toEqual({ kind: 'same' })
    expect(leadCollision({ email: 'john@abcfreight.com' }, 'c9', existing).kind).toBe('ambiguous')
    expect(leadCollision({ email: 'new@x.com', first_name: 'Jane', last_name: 'Doe' }, 'c1', existing)).toEqual({ kind: 'new' })
  })
})

describe('renderTemplateClean (§31)', () => {
  it('omits rows whose variables are missing and keeps the rest', () => {
    const out = renderTemplateClean('Name: {{requester_full_name}}\nPhone: {{requester_phone}}\nUSDOT Number: {{usdot_number}}\n\n\nMC: {{mc_number}}', { requester_full_name: 'John Smith', mc_number: '123456' })
    expect(out).toBe('Name: John Smith\n\nMC: 123456')
    expect(out).not.toMatch(/null|undefined|\{\{/)
  })
  it('the required broker verification template exists with the required subject', () => {
    const t = DEFAULT_TEMPLATES.find((x) => x.key === 'broker_relationship_verification_request')!
    expect(t.subject).toBe('Please verify {{requester_full_name}} for {{company_name}} on HeavyHaul Agent')
    for (const k of ['broker_company_invitation', 'broker_company_bulk_invitation', 'company_dispatcher_invitation', 'company_dispatcher_bulk_invitation', 'broker_relationship_verified', 'broker_relationship_rejected', 'broker_relationship_reminder', 'broker_lead_invitation', 'broker_company_admin_invitation', 'broker_relationship_revoked']) {
      expect(DEFAULT_TEMPLATES.some((x) => x.key === k)).toBe(true)
    }
  })
})

describe('bulk invite paste parser', () => {
  it('accepts lines, commas, semicolons, spaces and "Name <email>"; de-dupes; reports invalid', () => {
    const r = parseEmailList('John Smith <John@ABCFreight.com>, maria@abcfreight.com;  sam@x.io\njohn@abcfreight.com\nnot-an-email\n"dana@abcfreight.com"')
    expect(r.emails).toEqual(['john@abcfreight.com', 'maria@abcfreight.com', 'sam@x.io', 'dana@abcfreight.com'])
    expect(r.invalid).toEqual(['not-an-email'])
  })
})
