'use client'

import { useCallback } from 'react'
import { usePreviewValue, writePreviewValue } from '@/lib/demo/pilot-store'
import type {
  DueDateKey,
  ExpenseCategory,
  ExpenseOwnerType,
  InvoiceCalculation,
  InvoiceStatus,
  PlanName,
  RecipientType,
} from '@/lib/domain/invoicing'
import type { PilotAccountType } from '@/lib/domain/pilot'


/**
 * Replica records for pilot invoicing & expenses (Phase 1, 2026-09-12).
 * Shapes follow the article's §34 data objects so the backend swap is
 * mechanical. Lives in sessionStorage through the preview store — nothing
 * reaches a server, no email leaves the app.
 */

export interface InvoiceLineItem {
  id: string
  type: 'mileage' | 'daily' | 'overnight' | 'expense' | 'custom' | 'discount'
  description: string
  quantity: number
  rate: number
  amount: number
  included: boolean
  notes?: string
}

export interface InvoiceRecipient {
  id: string
  recipientType: RecipientType
  email: string
  name: string
  sentStatus: 'pending' | 'sent'
  sentAt?: string
}

export interface PilotInvoice {
  id: string
  assignmentId: string
  tripRef: string
  ownerType: PilotAccountType
  ownerName: string
  ownerContact: string
  billToCompany: string
  billToContactName: string
  billToContactEmail: string
  status: InvoiceStatus
  invoiceNumber: string
  invoiceDate: string
  dueDateKey: DueDateKey | null
  dueDate: string | null
  /** Trip details snapshot (§17). */
  statesCovered: string[]
  permitsCovered: string[]
  serviceDates: string
  pilotRole: string
  pilotDriverName: string
  vehicleUsed: string
  truckReference: string
  /** Billing inputs (§9). */
  miles: number
  ratePerMile: number
  days: number
  dailyRate: number
  overnights: number
  overnightFee: number
  customItems: { id: string; description: string; amount: number; notes: string }[]
  /** Ids of expenses included on this invoice. */
  expenseIds: string[]
  calc: InvoiceCalculation
  paymentInstructions: string
  preferredPaymentMethod: string
  notes: string
  recipients: InvoiceRecipient[]
  createdBy: string
  createdAt: string
  updatedAt: string
  sentAt?: string
  paidAt?: string
}

export interface PilotExpense {
  id: string
  assignmentId: string
  tripRef: string
  ownerType: ExpenseOwnerType
  ownerName: string
  createdBy: string
  category: ExpenseCategory
  description: string
  amount: number
  expenseDate: string
  /** File name only — bytes are not stored in the replica. */
  receiptName: string | null
  notes: string
  billable: boolean
  includeOnInvoice: boolean
  status: 'recorded'
  createdAt: string
}

export interface InvoiceLogEntry {
  at: string
  action: string
  detail: string
}

const INVOICES_KEY = 'hha-pilot-preview-invoices'
const EXPENSES_KEY = 'hha-pilot-preview-expenses'
const LOG_KEY = 'hha-pilot-preview-invoice-log'
const PAYMENT_KEY = 'hha-pilot-preview-payment-prefs'
const PLAN_KEY = 'hha-pilot-preview-owner-plan'
const DRIVER_PLAN_KEY = 'hha-pilot-preview-driver-plan'
const VIEWER_PLAN_KEY = 'hha-pilot-preview-viewer-plan'
const SIGNUP_AGE_KEY = 'hha-pilot-preview-signup-age-days'

const EMPTY_INVOICES: PilotInvoice[] = []
const EMPTY_EXPENSES: PilotExpense[] = []
const EMPTY_LOG: InvoiceLogEntry[] = []

export function useInvoices() {
  const invoices = usePreviewValue<PilotInvoice[]>(INVOICES_KEY, EMPTY_INVOICES)
  const save = useCallback(
    (next: PilotInvoice) => {
      const list = invoices.some((i) => i.id === next.id)
        ? invoices.map((i) => (i.id === next.id ? next : i))
        : [next, ...invoices]
      writePreviewValue(INVOICES_KEY, list)
    },
    [invoices],
  )
  return { invoices, save }
}

export function useExpenses() {
  const expenses = usePreviewValue<PilotExpense[]>(EXPENSES_KEY, EMPTY_EXPENSES)
  const save = useCallback(
    (next: PilotExpense) => {
      const list = expenses.some((e) => e.id === next.id)
        ? expenses.map((e) => (e.id === next.id ? next : e))
        : [next, ...expenses]
      writePreviewValue(EXPENSES_KEY, list)
    },
    [expenses],
  )
  const remove = useCallback(
    (id: string) => writePreviewValue(EXPENSES_KEY, expenses.filter((e) => e.id !== id)),
    [expenses],
  )
  return { expenses, save, remove }
}

/** Article §35: "All invoice send actions must be logged." */
export function useInvoiceLog() {
  const log = usePreviewValue<InvoiceLogEntry[]>(LOG_KEY, EMPTY_LOG)
  const append = useCallback(
    (entry: Omit<InvoiceLogEntry, 'at'>) =>
      writePreviewValue(LOG_KEY, [{ at: new Date().toISOString(), ...entry }, ...log]),
    [log],
  )
  return { log, append }
}

/**
 * Nash: payment instructions are "a text field… many time when you go to
 * generate a new one, it kind of shows you the last one." Remembered per
 * browser; pre-filled into the next invoice and editable there.
 */
export interface PaymentPrefs {
  paymentInstructions: string
  preferredPaymentMethod: string
}
const EMPTY_PREFS: PaymentPrefs = { paymentInstructions: '', preferredPaymentMethod: '' }

export function usePaymentPrefs() {
  const prefs = usePreviewValue<PaymentPrefs>(PAYMENT_KEY, EMPTY_PREFS)
  const save = useCallback((next: PaymentPrefs) => writePreviewValue(PAYMENT_KEY, next), [])
  return { prefs, save }
}

/**
 * Admin-only preview switch for the assignment owner's plan. Real accounts
 * are all on Free until payments connect (CURRENT_PLAN); the switch lets the
 * locked and unlocked states be reviewed.
 */
export function useOwnerPlanPreview(fallback: PlanName) {
  const plan = usePreviewValue<PlanName>(PLAN_KEY, fallback)
  const setPlan = useCallback((next: PlanName) => writePreviewValue(PLAN_KEY, next), [])
  return { plan, setPlan }
}

/**
 * The VIEWING account's plan on a trip (broker or carrier — Nash, 2026-09-13:
 * pilot paperwork is Starter or higher). Real accounts are all on Free until
 * payments connect; the switch lets every state be reviewed.
 */
export function useViewerPlanPreview(fallback: PlanName) {
  const plan = usePreviewValue<PlanName>(VIEWER_PLAN_KEY, fallback)
  const setPlan = useCallback((next: PlanName) => writePreviewValue(VIEWER_PLAN_KEY, next), [])
  return { plan, setPlan }
}

/**
 * Admin preview of "days since sign-up" for the 90-day free window. Falls
 * back to the real account age when no preview value was set.
 */
export function useSignupAgePreview(fallbackDays: number) {
  const days = usePreviewValue<number>(SIGNUP_AGE_KEY, fallbackDays)
  const setDays = useCallback((next: number) => writePreviewValue(SIGNUP_AGE_KEY, next), [])
  return { days, setDays }
}

/** The pilot DRIVER's own plan (Nash: "only a pro driver can see those things"). */
export function useDriverPlanPreview(fallback: PlanName) {
  const plan = usePreviewValue<PlanName>(DRIVER_PLAN_KEY, fallback)
  const setPlan = useCallback((next: PlanName) => writePreviewValue(DRIVER_PLAN_KEY, next), [])
  return { plan, setPlan }
}

export function newId(prefix: string): string {
  return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`
}
