import type { PaymentReadiness } from '@/lib/domain/purchases'

/**
 * Synchron Permits payment integration — the HHA-side CONTRACT (task §11).
 *
 * These are internal operation names, not Synchron endpoint names. Synchron
 * owns the Stripe account, the checkout session, the stored card and the
 * money; HHA only asks questions and receives answers. The real network
 * shapes are unknown until Synchron answers the integration questionnaire —
 * see docs/SYNCHRON-PAYMENTS-INTEGRATION.md for what is waiting on them.
 *
 * Nothing in this module ever sees a card number, a CVV or a Stripe secret.
 */

/** Which HHA billing customer a call is made for. Resolved server-side only. */
export interface BillingContext {
  hhaUserId: string
  hhaCompanyId: string | null
  /** Synchron 16-char user token (profiles.source_token), when known. */
  synchronUserToken: string | null
  /** Synchron 16-char carrier token (companies.source_token), when known. */
  synchronCarrierToken: string | null
  /** Synchron 8-digit order token for the trip, when the trip is linked. */
  synchronOrderToken: string | null
  hhaTripId: string
}

export interface CheckoutLine {
  purchaseItemId: string
  hhaPermitId: string | null
  synchronPermitToken: string | null
  stateCode: string | null
  productCode: string
  routeType: 'express' | 'extended'
  unitPriceCents: number
  quantity: number
  lineTotalCents: number
}

export interface RoutePurchaseRequest {
  purchaseReference: string
  purchaseId: string
  billing: BillingContext
  currency: string
  totalCents: number
  lines: CheckoutLine[]
  /** Where Synchron sends the customer back after checkout. */
  returnUrl: string
  cancelUrl: string
}

export interface CheckoutSession {
  /** Synchron's own id for this purchase, if it assigns one. */
  synchronPurchaseToken: string | null
  stripeCheckoutSessionId: string | null
  checkoutUrl: string
  expiresAt: string | null
}

export type ExternalPaymentStatus = 'pending' | 'paid' | 'failed' | 'expired' | 'cancelled' | 'refunded' | 'partially_refunded'

export interface PurchaseStatusReport {
  purchaseReference: string
  paymentStatus: ExternalPaymentStatus
  synchronPurchaseToken: string | null
  stripeCheckoutSessionId: string | null
  stripePaymentIntentId: string | null
  stripeChargeId: string | null
  paymentConfirmedAt: string | null
  /** Stable id of the report so a repeated delivery is a no-op. */
  externalEventId: string
}

export type ExternalFulfillmentStatus = 'queued' | 'processing' | 'needs_review' | 'completed' | 'failed'

export interface PurchaseItemReport {
  purchaseItemId: string
  fulfillmentStatus: ExternalFulfillmentStatus
  routeLinks?: string[]
  routeGpxUrl?: string | null
  routeHummerUrl?: string | null
}

/** Safe card summary — the only card data HHA ever handles. */
export interface CardOnFile {
  id: string
  brand: string
  last4: string
  expMonth: number
  expYear: number
  available: boolean
  isDefault: boolean
}

export interface CustomerPaymentStatus {
  readiness: PaymentReadiness
  cards: CardOnFile[]
}

export interface CardSetupSession {
  /** Synchron-hosted secure page where the card is entered or confirmed. */
  setupUrl: string
  setupReference: string
}

export interface CardSetupStatus {
  setupReference: string
  status: 'pending' | 'confirmed' | 'failed'
  card: CardOnFile | null
  /** One-time token proving the customer confirmed a card (with CVV) for this order. */
  paymentConfirmationToken: string | null
}

export interface PermitOrderSubmission {
  billing: BillingContext
  serviceRequestIds: string[]
  stateCodes: string[]
  paymentConfirmationToken: string
}

export interface PermitOrderReceipt {
  accepted: boolean
  synchronOrderToken: string | null
  /** Safe reference for `service_requests.payment_method_ref`. */
  paymentMethodRef: string | null
}

export class SynchronApiNotConfiguredError extends Error {
  readonly operation: string
  constructor(operation: string) {
    super(`Synchron payments API is not connected yet: ${operation}. See docs/SYNCHRON-PAYMENTS-INTEGRATION.md.`)
    this.name = 'SynchronApiNotConfiguredError'
    this.operation = operation
  }
}

export class SynchronUnavailableError extends Error {
  constructor(message = 'Synchron Permits is unavailable right now.') {
    super(message)
    this.name = 'SynchronUnavailableError'
  }
}

export interface SynchronPaymentsAdapter {
  readonly mode: 'live' | 'mock'
  createRoutePurchase(req: RoutePurchaseRequest): Promise<{ synchronPurchaseToken: string | null }>
  requestRouteCheckout(req: RoutePurchaseRequest): Promise<CheckoutSession>
  getRoutePurchaseStatus(purchaseReference: string, billing: BillingContext): Promise<PurchaseStatusReport>
  getRoutePurchaseItems(purchaseReference: string, billing: BillingContext): Promise<PurchaseItemReport[]>
  getCustomerPaymentStatus(billing: BillingContext): Promise<CustomerPaymentStatus>
  requestCardSetup(billing: BillingContext, returnUrl: string): Promise<CardSetupSession>
  /** Synchron-hosted "choose card + CVV" confirmation for one permit order (client decision D4). */
  confirmCardUse(billing: BillingContext, cardId: string, returnUrl: string): Promise<CardSetupSession>
  getCardSetupStatus(setupReference: string, billing: BillingContext): Promise<CardSetupStatus>
  submitPermitOrder(req: PermitOrderSubmission): Promise<PermitOrderReceipt>
  reconcilePurchaseStatus(purchaseReference: string, billing: BillingContext): Promise<PurchaseStatusReport>
}
