import 'server-only'

import { createHash } from 'node:crypto'
import { createAdminClient } from '@/lib/supabase/admin'
import { sendPlatformEmail } from '@/lib/email/send'
import { SUPPORT_EMAIL } from '@/lib/app-url'
import { isMissingColumn } from '@/lib/db-compat'
import { DASHBOARD_LINKS, DEFAULT_TEMPLATES } from '@/lib/email-templates'
import { getCompanyContext, listCompanyAudit, logCompanyEvent } from '@/lib/data/companies'
import { markLeadDecision, markLeadSignedUp } from '@/lib/data/broker-lead-hooks'
import {
  actorPhone, bulkInviteMembers, claimCompanyInvitation, companyAdminRecipients, emitCompanyEmail, fmtDate, inviteExistingAccount, loadManagement, markVerificationResult, type CarrierCompanyInfo, type PersonRow,
} from '@/lib/data/carrier-company'
import { canManageCarrierCompany, permissionLevel } from '@/lib/domain/carrier-company'
import {
  BROKER_AUDIT, HISTORICAL_CONFIRMATION, brokerCompanyView, brokerRoleLabel, matchBrokerLead, normalizeEmail, normalizeName,
  normalizePhone, verificationExpiry, type BrokerCompanyView, type LeadMatch,
} from '@/lib/domain/broker-company'
import type { BrokerAgentLead, Company, CompanyAuditEvent, CompanyClaim, CompanyMembership, VerificationEmailLog } from '@/types/db'
import type { SessionUser } from '@/lib/auth'

/**
 * Broker Dashboard → Broker Company data access (2026-09-19). Rules in
 * src/lib/domain/broker-company.ts. Shares the membership service with the
 * carrier side (approve / reject / revoke / permission / profile live in
 * carrier-company.ts under the broker `flow`); this file owns what only
 * brokers have — pre-verified historical records and the verification email
 * with its communication log. Tolerates migration 0022 not being applied.
 */

const missing = (e: { message?: string } | null | undefined) => !!e && /does not exist|schema cache/i.test(e.message ?? '')
/** Any 0021/0022 column absent on this database → retry with the 0013 shape. */
const missingColumnAny = (e: { message?: string } | null | undefined) => !!e && /column|schema cache|constraint/i.test(e.message ?? '')

/** A lead created by a Company Admin's invitation — verified on sight, no "do you still represent?" question. */
export const INVITATION_SOURCE = 'COMPANY_ADMIN_INVITATION'

/* ---------------- historical records ---------------- */

export async function findLeadMatch(person: { email: string; phone?: string | null; fullName?: string | null }): Promise<LeadMatch> {
  const admin = createAdminClient()
  const email = normalizeEmail(person.email)
  const phone = normalizePhone(person.phone)
  const name = normalizeName(person.fullName)
  // Candidate rows by any of the three keys; the domain rule decides the strength.
  const ors = [`email_normalized.eq.${email}`]
  if (phone) ors.push(`phone_digits.eq.${phone}`)
  const { data, error } = await admin.from('broker_agent_leads').select('*').eq('claim_status', 'unclaimed').or(ors.join(','))
  if (missing(error)) return { strength: 'none', lead: null }
  let leads = (data ?? []) as BrokerAgentLead[]
  if (leads.length === 0 && name) {
    const [first, ...rest] = name.split(' ')
    const { data: byName } = await admin.from('broker_agent_leads').select('*').eq('claim_status', 'unclaimed').ilike('first_name', first).ilike('last_name', rest.join(' ') || first)
    leads = (byName ?? []) as BrokerAgentLead[]
  }
  return matchBrokerLead(person, leads)
}

/* ---------------- read ---------------- */

export interface BrokerCompanyInfo extends Omit<CarrierCompanyInfo, 'view'> {
  view: BrokerCompanyView
  /** The historical record asking to be confirmed (view = historical_confirm). */
  lead: BrokerAgentLead | null
  /** A weak (name / phone) historical hint — shown to HeavyHaul admins only, never auto-verified. */
  weakMatch: { by: 'phone' | 'name'; company: string | null } | null
  /** Broker-only lists for the management view. */
  awaitingConfirmation: PersonRow[]
  noLongerCurrent: PersonRow[]
  manualReview: PersonRow[]
  verificationLog: VerificationEmailLog[]
  /** HeavyHaul admin: pre-verified contacts for this broker company. */
  leads: BrokerAgentLead[]
}

const EMPTY: BrokerCompanyInfo = {
  available: true, view: 'none', isPlatformAdmin: false, canManage: false, company: null, membership: null, claim: null, pendingInfo: null,
  pendingRequests: [], verifiedDispatchers: [], pastRelationships: [], audit: [], verificationRecords: [], adminCompanies: [], invitations: [],
  lead: null, weakMatch: null, awaitingConfirmation: [], noLongerCurrent: [], manualReview: [], verificationLog: [], leads: [],
}

export async function loadBrokerCompanyInfo(user: SessionUser, opts: { companyId?: string | null; profile?: { full_name: string; phone: string | null } | null } = {}): Promise<BrokerCompanyInfo> {
  const admin = createAdminClient()
  const isPlatformAdmin = user.role === 'admin'

  if (isPlatformAdmin) {
    const list = await admin.from('companies').select('id, display_name, mc_number, dot_number').eq('company_type', 'broker').is('merged_into', null).order('display_name')
    if (list.error) return { ...EMPTY, available: false, isPlatformAdmin: true }
    const adminCompanies = (list.data ?? []) as BrokerCompanyInfo['adminCompanies']
    const chosenId = opts.companyId && adminCompanies.some((c) => c.id === opts.companyId) ? opts.companyId : adminCompanies[0]?.id ?? null
    if (!chosenId) return { ...EMPTY, isPlatformAdmin: true, view: 'company_admin', canManage: true, adminCompanies }
    const { data: company } = await admin.from('companies').select('*').eq('id', chosenId).maybeSingle()
    return { ...EMPTY, isPlatformAdmin: true, view: 'company_admin', canManage: true, adminCompanies, company: (company ?? null) as Company | null, ...(await loadBrokerManagement(chosenId, true)) }
  }

  let ctx = await getCompanyContext(user.id)
  if (!ctx.available) return { ...EMPTY, available: false }
  if (ctx.membership?.status !== 'approved' && (await claimCompanyInvitation(user, 'broker'))) ctx = await getCompanyContext(user.id)
  let membership = ctx.membership
  let company = ctx.company
  let claim = ctx.claim

  // Pre-verified path: an exact-email match to our records, not yet answered.
  let lead: BrokerAgentLead | null = null
  let weakMatch: BrokerCompanyInfo['weakMatch'] = null
  if (membership?.status !== 'approved') {
    const match = await findLeadMatch({ email: user.email, phone: opts.profile?.phone, fullName: opts.profile?.full_name || user.name })
    if (match.strength === 'strong' && match.lead.historical_verification_source === INVITATION_SOURCE) {
      // Invited by the company's own admin: verified at first sign-in (2026-09-19).
      const claimed = await claimInvitedLead(user, match.lead)
      if (claimed) {
        membership = claimed.membership
        company = claimed.company ?? company
        claim = null
      }
    } else if (match.strength === 'strong') {
      lead = match.lead
      const ensured = await ensureHistoricalMembership(user, match.lead)
      if (ensured) {
        membership = ensured.membership
        company = ensured.company ?? company
        claim = null
      }
    } else if (match.strength === 'weak') {
      weakMatch = { by: match.by, company: match.lead.broker_company_name }
    }
  }

  const view = brokerCompanyView({ membership, claim, historicalMatch: !!lead, viewerIsPlatformAdmin: false })
  const canManage = !!company && canManageCarrierCompany({ membership, companyId: company.id, viewerIsPlatformAdmin: false })
  const pendingInfo =
    view === 'pending' && membership
      ? { sentTo: claim?.approval_sent_to ?? company?.corporate_email ?? null, requestedAt: membership.requested_at ?? claim?.created_at ?? membership.created_at, expiresAt: claim?.expires_at ?? null, method: claim?.verification_method ?? null }
      : null
  const management = canManage && company ? await loadBrokerManagement(company.id, false) : {}
  return { ...EMPTY, view, company, membership, claim, canManage, pendingInfo, lead, weakMatch, ...management }
}

async function loadBrokerManagement(companyId: string, platformAdmin: boolean) {
  const admin = createAdminClient()
  const base = await loadManagement(companyId, brokerRoleLabel)
  // 0022 statuses come back as "pending" rows from the shared loader; split them out by raw status.
  const { data: rows } = await admin.from('company_memberships').select('id, status').eq('company_id', companyId)
  const statusOf = new Map(((rows ?? []) as { id: string; status: string }[]).map((r) => [r.id, r.status]))
  const all = [...base.pendingRequests, ...base.verifiedDispatchers, ...base.pastRelationships]
  const pick = (s: string) => all.filter((r) => statusOf.get(r.membershipId) === s)
  const [log, leads] = await Promise.all([
    admin.from('verification_emails').select('*').eq('company_id', companyId).order('sent_at', { ascending: false }).limit(50),
    platformAdmin
      ? admin.from('broker_agent_leads').select('*').eq('broker_company_id', companyId).order('created_at', { ascending: false }).limit(200)
      : admin.from('broker_agent_leads').select('*').eq('broker_company_id', companyId).eq('historical_verification_source', INVITATION_SOURCE).order('created_at', { ascending: false }).limit(200),
  ])
  return {
    ...base,
    pendingRequests: base.pendingRequests.filter((r) => statusOf.get(r.membershipId) === 'pending'),
    awaitingConfirmation: pick('historical_pending_confirmation'),
    noLongerCurrent: pick('no_longer_current'),
    manualReview: pick('manual_review'),
    verificationLog: ((log.data ?? []) as VerificationEmailLog[]),
    leads: ((leads.data ?? []) as BrokerAgentLead[]),
  }
}

/** Every unclaimed / awaiting / no-longer-current / manual-review lead — the HeavyHaul admin's list (§38). */
export async function listAllLeads(limit = 500): Promise<BrokerAgentLead[]> {
  const admin = createAdminClient()
  const { data, error } = await admin.from('broker_agent_leads').select('*').order('created_at', { ascending: false }).limit(limit)
  if (missing(error)) return []
  return (data ?? []) as BrokerAgentLead[]
}

/**
 * First time we recognise the person: a membership in
 * `historical_pending_confirmation` so admins can see "awaiting historical
 * confirmation". Nothing is activated. Skipped silently before 0022.
 */
async function ensureHistoricalMembership(user: SessionUser, lead: BrokerAgentLead): Promise<{ membership: CompanyMembership; company: Company | null } | null> {
  if (!lead.broker_company_id) return null
  const admin = createAdminClient()
  const { data: company } = await admin.from('companies').select('*').eq('id', lead.broker_company_id).maybeSingle()
  const { data: existing } = await admin.from('company_memberships').select('*').eq('user_id', user.id).eq('company_id', lead.broker_company_id).maybeSingle()
  if (existing) return { membership: existing as CompanyMembership, company: (company ?? null) as Company | null }
  const { data: created, error } = await admin.from('company_memberships').insert({
    user_id: user.id, company_id: lead.broker_company_id, role: 'freight_broker', status: 'historical_pending_confirmation',
    permission_level: 'member', requested_at: new Date().toISOString(), historically_verified: true, historical_verified_at: lead.historical_verified_at, broker_lead_id: lead.id,
  }).select('*').single()
  if (error) return null // 0022 not applied — the question is still asked; the row is written on confirmation
  return { membership: created as CompanyMembership, company: (company ?? null) as Company | null }
}

/** First sign-in of an invited freight broker: the membership the admin already verified. */
async function claimInvitedLead(user: SessionUser, lead: BrokerAgentLead): Promise<{ membership: CompanyMembership; company: Company | null } | null> {
  if (!lead.broker_company_id) return null
  const admin = createAdminClient()
  const now = new Date().toISOString()
  const permission = (lead.source_row?.permission_level as string | undefined) === 'company_admin' ? 'company_admin' : 'member'
  const invitedBy = (lead.source_row?.invited_by as string | undefined) ?? 'Company Admin'
  const full = {
    user_id: user.id, company_id: lead.broker_company_id, role: 'freight_broker', status: 'approved', permission_level: permission,
    approved_by: invitedBy, approved_at: now, confirmed_at: now, requested_at: lead.invited_at ?? now, verification_method: 'company_admin_invitation',
    verification_provider: 'COMPANY_ADMIN', historically_verified: false, broker_lead_id: lead.id, updated_at: now, revoked_by: null, revoked_at: null,
  }
  const base = { user_id: user.id, company_id: lead.broker_company_id, role: 'freight_broker', status: 'approved', approved_by: invitedBy, approved_at: now, revoked_by: null, revoked_at: null }
  let up = await admin.from('company_memberships').upsert(full, { onConflict: 'user_id,company_id' }).select('*').single()
  if (up.error && missingColumnAny(up.error)) {
    up = await admin.from('company_memberships').upsert(base, { onConflict: 'user_id,company_id' }).select('*').single()
  }
  if (up.error || !up.data) return null
  await admin.from('broker_agent_leads').update({ claim_status: 'claimed', claimed_user_id: user.id, claimed_at: now, relationship_confirmation_status: 'confirmed_current', confirmed_at: now, updated_at: now }).eq('id', lead.id)
  await markLeadSignedUp({ leadId: lead.id, email: user.email, userId: user.id, via: 'company_admin_invitation' })
  await markLeadDecision({ leadId: lead.id, userId: user.id, decision: 'confirmed', actorLabel: user.name || user.email })
  await admin.from('company_claims').update({ claim_status: 'approved', decided_at: now, updated_at: now, approver_name: invitedBy })
    .eq('user_id', user.id).eq('company_id', lead.broker_company_id).not('claim_status', 'in', '("approved","rejected","revoked")')
  const { data: company } = await admin.from('companies').select('*').eq('id', lead.broker_company_id).maybeSingle()
  await logCompanyEvent({
    companyId: lead.broker_company_id, actorUserId: user.id, actorLabel: user.name || user.email, eventType: BROKER_AUDIT.confirmed,
    oldValue: { lead_id: lead.id, invitation_status: lead.invitation_status }, newValue: { lead_id: lead.id, user_id: user.id, status: 'approved', permission_level: permission, via: 'company_admin_invitation' },
  })
  return { membership: up.data as CompanyMembership, company: (company ?? null) as Company | null }
}

/**
 * Company Admin invites a freight broker by name + email (Nash, 2026-09-19:
 * "I have my list of 10 verified that I know they work for me… all I need to
 * put is his email and his name and hit invite… a verified relation").
 *
 *   account exists   → membership approved right now (company_admin_invitation / COMPANY_ADMIN)
 *   no account yet   → a pre-verified invited contact; verified on first sign-in with that email
 * Either way the invitation email goes out from the admin-managed template.
 */
export async function inviteFreightBroker(params: {
  company: Company
  name: string
  email: string
  makeAdmin: boolean
  actor: { id: string; label: string; email: string; isPlatformAdmin: boolean; ip: string | null }
  templateKey?: string
}) {
  const { company, actor } = params
  const email = normalizeEmail(params.email)
  const name = params.name.trim()
  if (!email.includes('@')) return { ok: false as const, error: 'Enter a valid email address.' }
  if (email === normalizeEmail(actor.email)) return { ok: false as const, error: 'That is you.' }
  const admin = createAdminClient()
  const now = new Date().toISOString()
  const [first, ...rest] = name.split(/\s+/)
  const permission = params.makeAdmin ? 'company_admin' : 'member'
  const emailData = {
    requester_first_name: first ?? '', requester_last_name: rest.join(' '), requester_full_name: name, requester_email: email, user_name: name, user_email: email,
    invited_by: actor.label, invited_by_email: actor.email, invited_by_phone: await actorPhone(actor.id), company_name: company.legal_name, company_display_name: company.display_name, mc_number: company.mc_number ?? '', usdot_number: company.dot_number ?? '',
    requested_role: 'Freight Broker',
  }

  const viaAccount = await inviteExistingAccount({ company, name, email, makeAdmin: params.makeAdmin, actor, templateKey: params.templateKey })
  if (viaAccount.ok) return { ok: true as const, outcome: 'verified' as const, name: viaAccount.name }
  if (!viaAccount.noAccount) return { ok: false as const, error: viaAccount.error }

  // No account yet: a pre-verified invited contact (needs migration 0022).
  const lead = {
    first_name: first || null, last_name: rest.join(' ') || null, email: params.email.trim(), email_normalized: email, phone: null, phone_digits: null,
    broker_company_id: company.id, broker_company_name: company.legal_name, mc_number: company.mc_number, usdot_number: company.dot_number,
    historical_relationship_verified: true, historical_verification_source: INVITATION_SOURCE, historical_verified_at: now,
    claim_status: 'unclaimed', relationship_confirmation_status: 'not_confirmed', invitation_status: 'invited', invited_at: now, claimed_user_id: null,
    manual_review_reason: null, import_batch: 'company_admin_invitation', source_row: { invited_by: actor.label, invited_by_user_id: actor.id, permission_level: permission }, updated_at: now,
  }
  const { data: found, error: fErr } = await admin.from('broker_agent_leads').select('id, claim_status, broker_company_id').eq('email_normalized', email).maybeSingle()
  if (missing(fErr)) return { ok: false as const, error: 'Inviting someone without a HeavyHaul Agent account needs database migration 0022. People who already have an account can be invited now.' }
  if (found && found.claim_status === 'claimed') return { ok: false as const, error: 'This email already claimed a profile — invite them through their account email.' }
  if (found && found.broker_company_id && found.broker_company_id !== company.id) return { ok: false as const, error: 'This email is on file for a different broker company — contact HeavyHaul Agent support.' }
  const w = found ? await admin.from('broker_agent_leads').update(lead).eq('id', found.id) : await admin.from('broker_agent_leads').insert(lead)
  if (w.error) return { ok: false as const, error: w.error.message }
  await logCompanyEvent({
    companyId: company.id, actorUserId: actor.id, actorLabel: actor.label, ip: actor.ip, eventType: BROKER_AUDIT.invited,
    newValue: { email, name, status: 'invited_no_account', permission_level: permission, via: 'company_admin_invitation', by_platform_admin: actor.isPlatformAdmin },
  })
  await emitCompanyEmail({ event: params.templateKey ?? 'broker_company_invitation', to: [email], data: emailData, companyId: company.id, actorUserId: actor.id, clean: true })
  return { ok: true as const, outcome: 'invited' as const, name: name || email }
}

/**
 * Bulk invite (Nash, 2026-09-19): "invite by copy-paste a list of 40
 * different emails… without a need for a name… they all get the same
 * subject, the same email." One message per address from the
 * broker_company_bulk_invitation template; each address is handled exactly
 * like a single invite (account → verified now; none → verified on sign-up).
 */
export async function bulkInviteFreightBrokers(params: {
  company: Company
  emails: string[]
  makeAdmin: boolean
  actor: { id: string; label: string; email: string; isPlatformAdmin: boolean; ip: string | null }
}) {
  return bulkInviteMembers({
    ...params,
    inviteOne: (email) => inviteFreightBroker({ company: params.company, name: '', email, makeAdmin: params.makeAdmin, actor: params.actor, templateKey: 'broker_company_bulk_invitation' }),
  })
}

/* ---------------- historical confirmation (§14–§17) ---------------- */

export async function confirmHistoricalRelationship(params: { user: SessionUser; decision: 'yes' | 'no'; ip: string | null }) {
  const { user, decision } = params
  const match = await findLeadMatch({ email: user.email })
  if (match.strength !== 'strong') return { ok: false as const, error: 'No historical record is waiting for your confirmation.' }
  const lead = match.lead
  if (!lead.broker_company_id) return { ok: false as const, error: 'This historical record is not linked to a broker company yet — contact support.' }
  const admin = createAdminClient()
  const now = new Date().toISOString()
  const actorLabel = user.name || user.email
  const { data: companyRow } = await admin.from('companies').select('*').eq('id', lead.broker_company_id).maybeSingle()
  const company = (companyRow ?? null) as Company | null
  if (!company) return { ok: false as const, error: 'The broker company on this record no longer exists.' }

  if (decision === 'yes') {
    const full = {
      user_id: user.id, company_id: company.id, role: 'freight_broker', status: 'approved', permission_level: 'member',
      approved_by: 'HeavyHaul Agent (historical record + your confirmation)', approved_at: now, confirmed_at: now,
      verification_method: HISTORICAL_CONFIRMATION.verification_method, verification_provider: HISTORICAL_CONFIRMATION.verification_provider,
      historically_verified: true, historical_verified_at: lead.historical_verified_at ?? now, broker_lead_id: lead.id, requested_at: now, updated_at: now,
      revoked_by: null, revoked_at: null,
    }
    const base = { user_id: user.id, company_id: company.id, role: 'freight_broker', status: 'approved', approved_by: full.approved_by, approved_at: now, revoked_by: null, revoked_at: null }
    let up = await admin.from('company_memberships').upsert(full, { onConflict: 'user_id,company_id' })
    if (up.error && missingColumnAny(up.error)) {
      up = await admin.from('company_memberships').upsert(base, { onConflict: 'user_id,company_id' })
    }
    if (up.error) return { ok: false as const, error: up.error.message }
    await admin.from('broker_agent_leads').update({ claim_status: 'claimed', claimed_user_id: user.id, claimed_at: now, relationship_confirmation_status: 'confirmed_current', confirmed_at: now, updated_at: now }).eq('id', lead.id)
    await markLeadSignedUp({ leadId: lead.id, email: user.email, userId: user.id, via: 'historical_confirmation' })
    await markLeadDecision({ leadId: lead.id, userId: user.id, decision: 'confirmed', actorLabel })
    await logCompanyEvent({
      companyId: company.id, actorUserId: user.id, actorLabel, ip: params.ip, eventType: BROKER_AUDIT.confirmed,
      oldValue: { lead_id: lead.id, relationship_confirmation_status: 'not_confirmed' },
      newValue: { lead_id: lead.id, user_id: user.id, status: 'approved', ...HISTORICAL_CONFIRMATION, confirmed_at: now },
    })
    return { ok: true as const, company: company.display_name }
  }

  // "No, I no longer represent this company" — the record stays; the person moves on to a normal MC request.
  await admin.from('broker_agent_leads').update({ claim_status: 'claimed', claimed_user_id: user.id, claimed_at: now, relationship_confirmation_status: 'no_longer_current', updated_at: now }).eq('id', lead.id)
  await markLeadSignedUp({ leadId: lead.id, email: user.email, userId: user.id, via: 'historical_confirmation' })
  await markLeadDecision({ leadId: lead.id, userId: user.id, decision: 'declined', actorLabel })
  const { error } = await admin.from('company_memberships').upsert(
    { user_id: user.id, company_id: company.id, role: 'freight_broker', status: 'no_longer_current', broker_lead_id: lead.id, historically_verified: true, updated_at: now },
    { onConflict: 'user_id,company_id' },
  )
  if (error && !isMissingColumn(error, 'status', 'broker_lead_id', 'historically_verified', 'updated_at')) return { ok: false as const, error: error.message }
  await logCompanyEvent({
    companyId: company.id, actorUserId: user.id, actorLabel, ip: params.ip, eventType: BROKER_AUDIT.noLongerCurrent,
    oldValue: { lead_id: lead.id, relationship_confirmation_status: 'not_confirmed' }, newValue: { lead_id: lead.id, user_id: user.id, relationship_confirmation_status: 'no_longer_current' },
  })
  return { ok: true as const, company: company.display_name }
}

/* ---------------- the verification email (§27–§35) ---------------- */

const TEMPLATE_KEY = 'broker_relationship_verification_request'
const REMINDER_KEY = 'broker_relationship_reminder'

async function activeTemplate(key: string) {
  const admin = createAdminClient()
  const { data } = await admin.from('email_templates').select('id, subject, body, active, version, footer, support_contact, cta_text').eq('key', key).maybeSingle()
  const d = DEFAULT_TEMPLATES.find((t) => t.key === key)
  if (data) return { id: data.id as string, subject: data.subject as string, body: data.body as string, active: !!data.active, version: (data.version as number | null) ?? 1, footer: (data.footer as string | null) ?? '', support: (data.support_contact as string | null) ?? '', cta: (data.cta_text as string | null) ?? '' }
  if (!d) return null
  return { id: null, subject: d.subject, body: d.body, active: true, version: 0, footer: '', support: '', cta: '' }
}

/**
 * Build the verification email for a claim from the ACTIVE admin template
 * and send it to the company (verified Company Admins, else the official
 * email on file). Secure links are the claim's one-time token — invalid
 * after approval, rejection, expiry or cancellation (the token route checks
 * claim_status and expires_at). Every send lands in verification_emails.
 */
export async function sendBrokerVerificationRequest(params: {
  claim: CompanyClaim
  company: Company
  requester: SessionUser
  origin: string
  kind: 'initial' | 'resend' | 'reminder'
}) {
  const { claim, company, requester } = params
  const admin = createAdminClient()
  const key = params.kind === 'reminder' ? REMINDER_KEY : TEMPLATE_KEY
  const tpl = await activeTemplate(key)
  const to = await companyAdminRecipients(company)
  const { data: prof } = await admin.from('profiles').select('full_name, phone').eq('id', requester.id).maybeSingle()
  const fullName = (prof?.full_name || requester.name || requester.email).trim()
  const [first, ...rest] = fullName.split(/\s+/)
  const approveLink = `${params.origin}/company-approval/${claim.approval_token}?decision=approve`
  const rejectLink = `${params.origin}/company-approval/${claim.approval_token}?decision=deny`
  const data: Record<string, string> = {
    requester_first_name: first ?? '',
    requester_last_name: rest.join(' '),
    requester_full_name: fullName,
    requester_email: requester.email,
    requester_phone: prof?.phone ?? '',
    requested_role: brokerRoleLabel(claim.requested_role),
    company_name: company.legal_name,
    company_display_name: company.display_name,
    mc_number: company.mc_number ?? '',
    usdot_number: company.dot_number ?? '',
    request_date: fmtDate(claim.created_at),
    verification_expiration_date: fmtDate(claim.expires_at || verificationExpiry(claim.created_at)),
    approve_link: approveLink,
    reject_link: rejectLink,
    approve_button: `${tpl?.cta || 'Approve request'} → ${approveLink}`,
    reject_button: `Reject request → ${rejectLink}`,
    support_email: tpl?.support || SUPPORT_EMAIL,
    company_footer: tpl?.footer ?? '',
    ...DASHBOARD_LINKS,
  }
  const tokenId = createHash('sha256').update(claim.approval_token).digest('hex').slice(0, 16)
  const results: { to: string; status: string }[] = []
  for (const recipient of to) {
    // The central sender applies the stream (transactional), suppression and the message log; this keeps the verification-specific log too.
    const r = await sendPlatformEmail({ templateKey: key, to: recipient, data, actorUserId: requester.id, clean: true, tags: { claim: claim.id, kind: params.kind } })
    results.push({ to: recipient, status: r.status })
    const { error: logErr } = await admin.from('verification_emails').insert({
      relationship_request_id: claim.id, company_id: company.id, requester_user_id: requester.id, requester_label: fullName, recipient,
      template_key: key, template_version: tpl?.version ?? null, template_version_id: tpl?.id ?? null, subject_sent: r.subject, kind: params.kind,
      delivery_status: r.status, provider: r.agent === 'none' ? null : 'zeptomail', message_id: r.messageId ?? null, error: r.reason ?? null, token_id: tokenId, final_result: 'pending',
    })
    if (logErr && !missing(logErr)) console.error('verification_emails insert failed', logErr.message)
  }
  await logCompanyEvent({
    companyId: company.id, actorUserId: requester.id, actorLabel: fullName, eventType: BROKER_AUDIT.emailSent,
    newValue: { claim_id: claim.id, kind: params.kind, template_key: key, template_version: tpl?.version ?? null, sent_to: to, results, token_id: tokenId },
  })
  return { sentTo: to, results, templateVersion: tpl?.version ?? null }
}

export async function cancelVerification(claim: CompanyClaim, reason: string) {
  const admin = createAdminClient()
  const now = new Date().toISOString()
  const { error } = await admin.from('company_claims').update({ token_cancelled_at: now, token_cancelled_reason: reason }).eq('id', claim.id)
  if (error && !isMissingColumn(error, 'token_cancelled_at')) console.error('claim cancel mark failed', error.message)
  await markVerificationResult(claim.user_id, claim.company_id, 'cancelled')
}

/** Audit rows the broker Company Info shows (shared log, broker labels applied in the UI). */
export async function brokerAudit(companyId: string): Promise<CompanyAuditEvent[]> {
  return listCompanyAudit(companyId, 60)
}

export { permissionLevel }
