import type { BrokerAgentLead, CompanyClaim, CompanyMembership, CompanyRole } from '@/types/db'
import { permissionLevel } from '@/lib/domain/carrier-company'

/**
 * Broker Dashboard → Broker Company (Nash, 2026-09-19).
 *
 * Same three objects as the carrier side — user, company, membership — with
 * one broker-only path: PRE-VERIFIED freight brokers. "We already have
 * historical business records for some freight brokers… they should
 * not have to complete the full company verification process again if their
 * identity matches our existing records. However, they must confirm that
 * they still represent that company."
 *
 *   New freight broker    account → MC → company → verification email →
 *                         company approves → Verified Freight Broker
 *   Pre-verified agent    account → we recognise the email → "do you still
 *                         represent…?" → yes → Verified Freight Broker
 *
 * "Pre-create trusted relationship evidence, not user accounts."
 * Pure rules; the data layer does the I/O.
 */

export type BrokerCompanyView =
  | 'none'
  /** We found a historical record for this email — ask them to confirm. */
  | 'historical_confirm'
  | 'pending'
  | 'manual_review'
  | 'verified'
  | 'company_admin'
  | 'rejected'
  | 'revoked'
  | 'no_longer_current'

export const BROKER_RELATIONSHIP_LABELS: Record<string, string> = {
  pending: 'Waiting for Verification',
  historical_pending_confirmation: 'Awaiting Historical Confirmation',
  approved: 'Verified',
  rejected: 'Not Verified',
  revoked: 'Relationship Revoked',
  no_longer_current: 'No Longer Current',
  manual_review: 'Manual Review',
}

/** Role as the broker side reads it. */
export function brokerRoleLabel(role: CompanyRole): string {
  switch (role) {
    case 'company_owner':
      return 'Company Owner'
    case 'billing_admin':
      return 'Billing Admin'
    case 'viewer':
      return 'Viewer'
    default:
      return 'Freight Broker'
  }
}

export function brokerCompanyView(params: {
  membership: Pick<CompanyMembership, 'status' | 'role' | 'permission_level'> | null
  claim: Pick<CompanyClaim, 'claim_status'> | null
  /** A strong (exact-email) historical match still waiting for the person's answer. */
  historicalMatch: boolean
  viewerIsPlatformAdmin: boolean
}): BrokerCompanyView {
  if (params.viewerIsPlatformAdmin) return 'company_admin'
  const m = params.membership
  if (m?.status === 'approved') return permissionLevel(m) === 'company_admin' ? 'company_admin' : 'verified'
  // The historical question comes before any pending flow — answering it is faster than waiting.
  if (params.historicalMatch || m?.status === 'historical_pending_confirmation') return 'historical_confirm'
  if (m?.status === 'manual_review' || params.claim?.claim_status === 'admin_review_required') return 'manual_review'
  if (m?.status === 'pending') return 'pending'
  if (m?.status === 'rejected') return 'rejected'
  if (m?.status === 'revoked') return 'revoked'
  if (m?.status === 'no_longer_current') return 'no_longer_current'
  if (params.claim && ['pending_corporate_approval', 'company_verification_pending', 'company_claimed', 'company_match_found'].includes(params.claim.claim_status)) return 'pending'
  return 'none'
}

/* ---------------- historical matching ---------------- */

export function normalizeEmail(e: string | null | undefined): string {
  return (e ?? '').trim().toLowerCase()
}
export function normalizePhone(p: string | null | undefined): string | null {
  const d = (p ?? '').replace(/\D/g, '')
  if (d.length < 10) return null
  return d.length === 11 && d.startsWith('1') ? d.slice(1) : d
}
export function normalizeName(n: string | null | undefined): string {
  return (n ?? '').trim().toLowerCase().replace(/\s+/g, ' ')
}

export type LeadMatch =
  /** Exact email — the only match that may skip company verification. */
  | { strength: 'strong'; lead: BrokerAgentLead; by: 'email' }
  /** Name / phone only — supporting evidence; never verifies on its own. */
  | { strength: 'weak'; lead: BrokerAgentLead; by: 'phone' | 'name' }
  | { strength: 'none'; lead: null }

/**
 * §16: "The safest primary match is exact email… If the user signs up using
 * a different email than the historical record, do not automatically
 * verify. Even if the name matches, require normal verification or manual
 * review."
 */
export function matchBrokerLead(
  person: { email: string; phone?: string | null; fullName?: string | null },
  leads: BrokerAgentLead[],
): LeadMatch {
  const open = leads.filter((l) => l.claim_status === 'unclaimed' && l.historical_relationship_verified)
  const email = normalizeEmail(person.email)
  const byEmail = open.find((l) => l.email_normalized === email)
  if (byEmail) return { strength: 'strong', lead: byEmail, by: 'email' }
  const phone = normalizePhone(person.phone)
  if (phone) {
    const byPhone = open.find((l) => l.phone_digits === phone)
    if (byPhone) return { strength: 'weak', lead: byPhone, by: 'phone' }
  }
  const name = normalizeName(person.fullName)
  if (name) {
    const byName = open.find((l) => normalizeName(`${l.first_name ?? ''} ${l.last_name ?? ''}`) === name)
    if (byName) return { strength: 'weak', lead: byName, by: 'name' }
  }
  return { strength: 'none', lead: null }
}

/** What a "Yes, I still represent this company" answer writes to the membership. */
export const HISTORICAL_CONFIRMATION = {
  verification_method: 'historical_relationship_plus_user_confirmation',
  verification_provider: 'INTERNAL_HISTORICAL_RECORDS',
} as const

/* ---------------- import matching (§26) ---------------- */

export interface ImportedLeadRow {
  first_name?: string | null
  last_name?: string | null
  email?: string | null
  phone?: string | null
  company?: string | null
  mc?: string | null
  usdot?: string | null
}

/** Match a broker company for an imported row: MC first, USDOT second, legal name only as a tiebreaker. */
export function matchImportedCompany(
  row: ImportedLeadRow,
  companies: { id: string; legal_name: string; mc_number: string | null; dot_number: string | null }[],
): { kind: 'match'; id: string; by: 'mc' | 'usdot' | 'name' } | { kind: 'none' } | { kind: 'ambiguous'; reason: string } {
  const mc = (row.mc ?? '').replace(/\D/g, '')
  if (mc) {
    const hits = companies.filter((c) => c.mc_number === mc)
    if (hits.length === 1) return { kind: 'match', id: hits[0].id, by: 'mc' }
    if (hits.length > 1) return { kind: 'ambiguous', reason: `MC ${mc} matches ${hits.length} companies` }
  }
  const dot = (row.usdot ?? '').replace(/\D/g, '')
  if (dot) {
    const hits = companies.filter((c) => c.dot_number === dot)
    if (hits.length === 1) return { kind: 'match', id: hits[0].id, by: 'usdot' }
    if (hits.length > 1) return { kind: 'ambiguous', reason: `USDOT ${dot} matches ${hits.length} companies` }
  }
  const name = normalizeName(row.company)
  if (name) {
    const hits = companies.filter((c) => normalizeName(c.legal_name) === name)
    if (hits.length === 1) return { kind: 'match', id: hits[0].id, by: 'name' }
    if (hits.length > 1) return { kind: 'ambiguous', reason: `name "${row.company}" matches ${hits.length} companies` }
  }
  return { kind: 'none' }
}

/** A lead row that would collide with an existing one is flagged, never silently merged. */
export function leadCollision(
  row: ImportedLeadRow,
  companyId: string | null,
  existing: Pick<BrokerAgentLead, 'email_normalized' | 'phone_digits' | 'first_name' | 'last_name' | 'broker_company_id'>[],
): { kind: 'same' | 'new' } | { kind: 'ambiguous'; reason: string } {
  const email = normalizeEmail(row.email)
  const byEmail = existing.filter((l) => l.email_normalized === email)
  if (byEmail.length > 0) {
    if (byEmail.some((l) => l.broker_company_id === companyId)) return { kind: 'same' }
    return { kind: 'ambiguous', reason: `${email} already on file for a different company` }
  }
  const phone = normalizePhone(row.phone)
  const name = normalizeName(`${row.first_name ?? ''} ${row.last_name ?? ''}`)
  const byPerson = existing.filter(
    (l) => (phone && l.phone_digits === phone) || (name && normalizeName(`${l.first_name ?? ''} ${l.last_name ?? ''}`) === name && l.broker_company_id === companyId),
  )
  if (byPerson.some((l) => l.broker_company_id !== companyId)) return { kind: 'ambiguous', reason: 'same person (phone/name) on file with a different company and a different email' }
  return { kind: 'new' }
}

/* ---------------- events / audit ---------------- */

export const BROKER_EMAIL_EVENTS = [
  'broker_company_invitation',
  'broker_relationship_verification_request',
  'broker_relationship_verified',
  'broker_relationship_rejected',
  'broker_relationship_reminder',
  'broker_lead_invitation',
  'broker_company_admin_invitation',
  'broker_relationship_revoked',
] as const
export type BrokerEmailEvent = (typeof BROKER_EMAIL_EVENTS)[number]

export const BROKER_AUDIT = {
  requested: 'broker_relationship_requested',
  emailSent: 'verification_email_sent',
  approved: 'broker_relationship_approved',
  rejected: 'broker_relationship_rejected',
  revoked: 'broker_relationship_revoked',
  imported: 'historical_relationship_imported',
  confirmed: 'historical_relationship_confirmed',
  noLongerCurrent: 'historical_relationship_no_longer_current',
  adminOverride: 'admin_manual_override',
  invited: 'freight_broker_invited',
  bulkInvited: 'freight_brokers_bulk_invited',
  reinstated: 'broker_relationship_reinstated',
} as const

export const BROKER_AUDIT_LABELS: Record<string, string> = {
  [BROKER_AUDIT.requested]: 'Broker relationship requested',
  [BROKER_AUDIT.emailSent]: 'Verification email sent',
  [BROKER_AUDIT.approved]: 'Broker relationship approved',
  [BROKER_AUDIT.rejected]: 'Broker relationship rejected',
  [BROKER_AUDIT.revoked]: 'Broker relationship revoked',
  [BROKER_AUDIT.imported]: 'Historical relationship imported',
  [BROKER_AUDIT.confirmed]: 'Historical relationship confirmed',
  [BROKER_AUDIT.noLongerCurrent]: 'Historical relationship marked no longer current',
  [BROKER_AUDIT.adminOverride]: 'Admin manual override',
  [BROKER_AUDIT.invited]: 'Freight broker invited by Company Admin',
  [BROKER_AUDIT.bulkInvited]: 'Bulk invitation sent by Company Admin',
  [BROKER_AUDIT.reinstated]: 'Freight broker reinstated by Company Admin',
}

/** Verification links expire with the claim token (14 days from the request). */
export function verificationExpiry(requestedAt: string, days = 14): string {
  return new Date(new Date(requestedAt).getTime() + days * 86_400_000).toISOString()
}

/* Bulk invite parsing lives in src/lib/domain/company-invites.ts (shared with carriers). */
export { BULK_INVITE_LIMIT, parseEmailList } from '@/lib/domain/company-invites'
