export type UserRole = 'broker' | 'dispatcher' | 'driver' | 'admin'
export type TripRole = 'broker' | 'dispatcher' | 'driver' | 'pilot' | 'shipper' | 'admin'
export type TripStatus = 'draft' | 'waiting_for_permits' | 'active' | 'completed' | 'cancelled'
export type PermitSource = 'upload' | 'synchron'
export type DocumentKind = 'rate_confirmation' | 'permit' | 'provision' | 'route' | 'other'
export type ExtractionStatus = 'pending' | 'processed' | 'failed' | 'skipped'
export type WarningKind =
  | 'dimension_mismatch'
  | 'expired'
  | 'expiring'
  | 'curfew'
  | 'escort'
  | 'missing_permit'
  | 'other'
export type WarningSeverity = 'info' | 'warning' | 'danger'
export type ParticipantStatus = 'invited' | 'active' | 'removed'
export type RequestType = 'permit_request' | 'route_request'
export type RequestStatus = 'requested' | 'in_progress' | 'fulfilled' | 'cancelled'

export interface Profile {
  id: string
  email: string
  full_name: string
  phone: string | null
  company_name: string | null
  default_role: UserRole
  /**
   * Agent chat languages (2026-09-07, Task 71). Nash: "one language, English,
   * first, and then a button to add… It should stick to your profile." Absent
   * before migration 0011 → treat as ['en'] / 'en'.
   */
  chat_languages?: string[] | null
  primary_language?: string | null
  created_at: string
}

export interface BrokerPage {
  id: string
  owner_id: string
  slug: string
  display_name: string
  intro_message: string | null
  enabled: boolean
  /** Default permit-handling rules (intake doc §22): 'ask' = choose per trip. */
  default_permit_policy: 'synchron_required' | 'upload_allowed' | 'ask'
  default_payment_party: 'broker' | 'carrier' | 'ask'
  /** The verified company this intake page belongs to (Task 94; migration 0013). */
  company_id?: string | null
  created_at: string
}

export interface Trip {
  id: string
  ref_code: string
  created_by: string | null
  broker_page_id: string | null
  status: TripStatus
  permit_source: PermitSource
  carrier_name: string
  unit_number: string | null
  origin: string
  destination: string
  commodity: string
  load_length_in: number | null
  load_width_in: number | null
  load_height_in: number | null
  load_weight_lbs: number | null
  overall_length_in: number | null
  overall_width_in: number | null
  overall_height_in: number | null
  overall_weight_lbs: number | null
  permit_policy: 'synchron_required' | 'upload_allowed' | null
  /** Who pays Synchron for permit processing (Synchron flow only; null = n/a). */
  payment_responsible_party: 'broker' | 'carrier' | null
  pickup_date: string | null
  delivery_date: string | null
  notes: string | null
  completed_at: string | null
  created_at: string
  updated_at: string
}

export interface TripParticipant {
  id: string
  trip_id: string
  user_id: string | null
  email: string
  name: string
  phone: string | null
  phone_ext: string | null
  role: TripRole
  status: ParticipantStatus
  invited_by: string | null
  /**
   * When THIS participant marked the trip complete for themselves
   * (2026-09-07). Nash: "this marks it complete for me as the user… I don't
   * want to force close, force complete for all users this trip."
   */
  completed_at: string | null
  /** When they answered the "someone else completed this trip" prompt. */
  completion_prompt_dismissed_at: string | null
  /** False = this participant's agent Q&A on this trip is hidden from others. */
  share_chat: boolean
  created_at: string
}

export interface TripInvitation {
  id: string
  trip_id: string
  participant_id: string | null
  email: string
  role: TripRole
  token: string
  invited_by: string | null
  expires_at: string
  accepted_at: string | null
  accepted_by: string | null
  created_at: string
}

export interface TripDocument {
  id: string
  trip_id: string
  kind: DocumentKind
  storage_path: string
  file_name: string
  mime_type: string | null
  size_bytes: number | null
  uploaded_by: string | null
  uploader_label: string
  created_at: string
}

export interface Permit {
  id: string
  trip_id: string
  document_id: string | null
  state_code: string
  permit_number: string | null
  effective_date: string | null
  expiration_date: string | null
  permit_length_in: number | null
  permit_width_in: number | null
  permit_height_in: number | null
  permit_weight_lbs: number | null
  extraction: Record<string, unknown> | null
  extraction_status: ExtractionStatus
  created_at: string
}

export interface TripWarning {
  id: string
  trip_id: string
  permit_id: string | null
  kind: WarningKind
  severity: WarningSeverity
  message: string
  resolved: boolean
  created_at: string
}

export interface ServiceRequest {
  id: string
  trip_id: string
  type: RequestType
  state_code: string | null
  notes: string | null
  status: RequestStatus
  requested_by: string | null
  requester_label: string
  route_type: 'express' | 'extended' | null
  /** Google Maps parts — 1..N links (Texas routes can run to 12 parts). */
  route_links: string[] | null
  /** GPX file the driver sends to the in-cab truck GPS over Bluetooth. */
  route_gpx_url: string | null
  /** Deep link that opens this route in the Hummer GPS app. */
  route_hummer_url: string | null
  notify: string[] | null
  /** How a route was paid (Task 69): a prepaid Express Route credit, or the cart. */
  paid_with?: 'credit' | 'card' | null
  /** Who is liable for a permit order (Task 75). */
  payer?: 'requester' | 'broker' | 'carrier' | null
  /** The expired permit this permit request re-orders (Task 75). */
  replaces_permit_id?: string | null
  /** Synchron's own order number, when the adapter returned one (Task 84). */
  vendor_order_id?: string | null
  created_at: string
  updated_at: string
}

export interface ChatMessage {
  id: string
  trip_id: string
  user_id: string | null
  author_label: string
  author_role: string
  is_ai: boolean
  content: string
  state_code: string | null
  permit_id: string | null
  confidence: string | null
  sources: string[] | null
  feedback: number | null
  /** True = visible only to `private_for_user_id` (2026-09-07 sharing toggle). */
  is_private: boolean
  private_for_user_id: string | null
  /** For an AI message: the participant question it answers. */
  answer_to_message_id: string | null
  created_at: string
}

/** Editable system email template (admin dashboard; sending = email backend). */
export interface EmailTemplate {
  id: string
  key: string
  name: string
  subject: string
  body: string
  recipients_note: string | null
  cc_rules: string | null
  trigger_note: string | null
  internal_notes: string | null
  active: boolean
  updated_by: string | null
  updated_at: string
  created_at: string
}

export interface EmailTemplateVersion {
  id: string
  template_id: string
  subject: string
  body: string
  edited_by: string | null
  reason: string | null
  created_at: string
}

/** Unit profile for one trip: axles + truck info + trailer info (driver feedback 2026-09-04). */
export interface TripUnit {
  id: string
  trip_id: string
  axle_count: number | null
  axle_spacings_in: number[] | null
  axle_weights_lbs: number[] | null
  truck_unit_number: string | null
  truck_vin: string | null
  truck_make: string | null
  truck_model: string | null
  truck_year: number | null
  trailer_unit_number: string | null
  trailer_vin: string | null
  trailer_make: string | null
  trailer_model: string | null
  trailer_year: number | null
  trailer_axle_count: number | null
  /** Kingpin to rear axle (KPTRA), inches — the last spacing (Task 76). */
  kingpin_to_rear_axle_in?: number | null
  created_at: string
  updated_at: string
}

export type TicketStatus =
  | 'new'
  | 'in_review'
  | 'needs_more_context'
  | 'escalated'
  | 'correction_proposed'
  | 'approved_for_knowledge_update'
  | 'knowledge_updated'
  | 'no_change_needed'
  | 'closed'
  | 'duplicate'

/** AI-answer review ticket (moderator dashboard) — feedback is a review trigger, never truth. */
export interface ReviewTicket {
  id: string
  trip_id: string
  message_id: string
  question_message_id: string | null
  user_id: string | null
  user_role: string | null
  state_code: string | null
  permit_id: string | null
  confidence: string | null
  /** What opened the ticket: user 👎, user report, or an AI-side signal (§5). */
  trigger: 'thumbs_down' | 'reported' | 'low_confidence_repeat' | 'no_source'
  feedback_reason: string | null
  user_comment: string | null
  category: string | null
  priority: 'high' | 'medium' | 'low' | null
  status: TicketStatus
  assigned_to: string | null
  moderator_notes: string | null
  decision: string | null
  correction: string | null
  correction_explanation: string | null
  correction_source: string | null
  correction_state: string | null
  correction_topic: string | null
  applies_to: 'this_permit' | 'all_permits' | null
  applies_states: 'one_state' | 'multiple_states' | null
  update_state_notes: boolean
  create_qa: boolean
  update_prompt_logic: boolean
  escalate_developer: boolean
  confidence_review:
    | 'appropriate'
    | 'too_high'
    | 'too_low'
    | 'should_have_escalated'
    | 'missing'
    | null
  source_alignment:
    | 'permit_matches_provision'
    | 'permit_conflicts_provision'
    | 'notes_add_exception'
    | 'internal_qa_used'
    | 'no_permit_available'
    | 'low_source_confidence'
    | null
  request_reference: string | null
  sources: string[] | null
  channel: string
  audience: string | null
  ui_context: string | null
  source_versions: Record<string, string> | null
  /** Asker's chat language at the time (§11 "language used"). */
  language: string | null
  /** Question → answer latency in ms (§11 "response time"). */
  response_ms: number | null
  /** Master ticket this one was merged into (§23). */
  duplicate_of: string | null
  close_reason: string | null
  /** Set on terminal statuses; drives average resolution time (§21). */
  resolved_at: string | null
  /** Knowledge-update routing (§17). */
  update_type:
    | 'state_note'
    | 'qa_entry'
    | 'prompt_logic'
    | 'retrieval'
    | 'ocr_parsing'
    | 'product_ui'
    | null
  /** Visibility class for a Q&A entry born from this correction (§18). */
  qa_visibility:
    | 'internal_only'
    | 'broker_facing'
    | 'carrier_facing'
    | 'driver_facing'
    | 'processing_team_only'
    | 'training_only'
    | 'do_not_use'
    | null
  created_at: string
  updated_at: string
}

/** Technical problem raised from a review ticket with full context (§24). */
export interface DeveloperIssue {
  id: string
  ticket_id: string
  error_category: string
  summary: string | null
  context: Record<string, unknown> | null
  status: 'open' | 'done'
  created_by: string | null
  created_at: string
}

/** Admin-configurable moderation settings: categories, state reviewers (§3, §22). */
export interface ModerationSetting {
  key: string
  value: unknown
  updated_by: string | null
  updated_at: string
}

export interface TicketEvent {
  id: string
  ticket_id: string
  actor: string | null
  action: string
  detail: Record<string, unknown> | null
  created_at: string
}

export interface TripEvent {
  id: string
  trip_id: string
  actor_id: string | null
  actor_label: string
  action: string
  detail: Record<string, unknown> | null
  created_at: string
}

/* ---------------- Company verification & agent approval (Tasks 88–94) ---------------- */

export type CompanyType = 'broker' | 'carrier'
/** Article §23 verification levels 0–4. */
export type CompanyVerificationStatus =
  | 'unverified'
  | 'public_data_matched'
  | 'corporate_contact_confirmed'
  | 'company_admin_approved'
  | 'manual_verified'
/** Article §12 role levels (carrier companies read manager/agent). */
export type CompanyRole =
  | 'company_owner'
  | 'company_admin'
  | 'broker_manager'
  | 'broker_agent'
  | 'billing_admin'
  | 'viewer'
export type MembershipStatus = 'pending' | 'approved' | 'rejected' | 'revoked'
/** Article §4 company-relationship statuses (absence of a claim = no company connected). */
export type ClaimStatus =
  | 'company_claimed'
  | 'company_match_found'
  | 'company_verification_pending'
  | 'pending_corporate_approval'
  | 'approved'
  | 'rejected'
  | 'revoked'
  | 'admin_review_required'
/** Article §8 verification methods. */
export type VerificationMethod =
  | 'corporate_email_domain'
  | 'corporate_email_approval'
  | 'company_admin_approval'
  | 'manual_review'

export interface Company {
  id: string
  legal_name: string
  display_name: string
  dba_name: string | null
  company_type: CompanyType
  mc_number: string | null
  dot_number: string | null
  physical_address: string | null
  mailing_address: string | null
  corporate_email: string | null
  corporate_phone: string | null
  website: string | null
  logo_url: string | null
  verification_status: CompanyVerificationStatus
  verification_level: number
  source_fmcsa_id: string | null
  source_sos_id: string | null
  agents_see_all_trips: boolean
  notification_recipients: string[]
  locked: boolean
  merged_into: string | null
  is_placeholder: boolean
  created_at: string
  updated_at: string
}

export interface CompanyMembership {
  id: string
  user_id: string
  company_id: string
  role: CompanyRole
  status: MembershipStatus
  approved_by: string | null
  approved_at: string | null
  revoked_by: string | null
  revoked_at: string | null
  created_at: string
}

export interface CompanyClaim {
  id: string
  user_id: string
  company_id: string
  requested_role: CompanyRole
  claim_status: ClaimStatus
  verification_method: VerificationMethod
  mc_number: string | null
  approval_sent_to: string | null
  approval_token: string
  expires_at: string
  approver_name: string | null
  approver_email: string | null
  approver_ip: string | null
  decided_at: string | null
  review_reason: string | null
  review_notes: string | null
  info_request: string | null
  created_at: string
  updated_at: string
}

export interface CompanyVerificationRecord {
  id: string
  company_id: string
  source: 'fmcsa' | 'sos' | 'corporate_email' | 'company_admin' | 'manual' | 'local'
  source_data: Record<string, unknown> | null
  match_score: 'high' | 'medium' | 'low' | 'none'
  verified_fields: string[]
  verified_at: string | null
  status: string
  created_at: string
}

/** A dispatcher's or broker's saved person (Tasks 98/99, 2026-09-09). */
export type ContactRole = 'driver' | 'broker' | 'dispatcher'

export interface CarrierContact {
  id: string
  owner_id: string
  name: string
  email: string
  phone: string | null
  phone_ext: string | null
  role: ContactRole
  /** Set once this person has a HeavyHaul Agent account. */
  user_id: string | null
  /** When an account invitation was recorded (email delivery is backend-later). */
  invited_at: string | null
  /** Last time they were added to a trip — orders the picker. */
  last_used_at: string | null
  created_at: string
  updated_at: string
}

export interface CompanyAuditEvent {
  id: string
  actor_user_id: string | null
  actor_label: string
  company_id: string | null
  event_type: string
  old_value: Record<string, unknown> | null
  new_value: Record<string, unknown> | null
  ip_address: string | null
  created_at: string
}

