import { OrderValidationError } from './errors.js'

export type ProductKind = 'physical' | 'digital' | 'voucher'

export type OrderStatus =
  | 'pending'
  | 'charging'
  | 'paid'
  | 'fulfilled'
  | 'completed'
  | 'failed'
  | 'cancelled'
  | 'unfulfillable'
  | 'refunded'
  | 'partially_refunded'

export const ORDER_STATUSES: readonly OrderStatus[] = [
  'pending',
  'charging',
  'paid',
  'fulfilled',
  'completed',
  'failed',
  'cancelled',
  'unfulfillable',
  'refunded',
  'partially_refunded',
] as const

export function isOrderStatus(value: string): value is OrderStatus {
  return (ORDER_STATUSES as readonly string[]).includes(value)
}

export type PriceMode = 'inclusive' | 'exclusive'

export type BuyerRef = { userId: string } | { guestEmail: string }

/** commerce-catalog has no Actor yet — plan shape for W3 reads/authz. */
export type Actor = { userId?: string; vendorId?: string; isAdmin?: boolean }

export type StepRecord = Record<string, unknown>

export interface OrderLine {
  id: string
  orderId: string
  variantId: string
  kind: ProductKind
  qty: number
  unitPrice: bigint
  lineTotal: bigint
  vendorId: string | null
}

export interface VendorSplit {
  id: string
  orderId: string
  vendorId: string | null
  amount: bigint
  funder: 'platform' | 'vendor'
}

export interface Order {
  id: string
  buyerRef: BuyerRef
  status: OrderStatus
  currency: string
  priceMode: PriceMode
  subtotal: bigint
  tax: bigint
  discount: bigint
  total: bigint
  lines: OrderLine[]
  splits: VendorSplit[]
  fulfillmentState: { steps: Record<string, StepRecord> }
}

export interface NewOrderLine {
  variantId: string
  kind: ProductKind
  qty: number
  unitPrice: bigint
  lineTotal: bigint
  currency: string
  vendorId?: string | null
}

export interface NewVendorSplit {
  vendorId: string | null
  amount: bigint
  funder: 'platform' | 'vendor'
}

export interface NewOrder {
  idempotencyKey: string
  buyerRef: BuyerRef
  currency: string
  priceMode: PriceMode
  subtotal: bigint
  tax: bigint
  discount: bigint
  total: bigint
  lines: NewOrderLine[]
  splits: NewVendorSplit[]
}

export const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i

export function assertUuid(value: string, field: string): void {
  if (!UUID_RE.test(value)) {
    throw new OrderValidationError(field)
  }
}

export function assertPositiveInt(qty: number, field = 'qty'): void {
  if (!Number.isInteger(qty) || qty <= 0) {
    throw new OrderValidationError(field)
  }
}

export type Page<T> = { items: T[]; nextCursor: string | null }

export type OrderListFilter = {
  status?: OrderStatus
  cursor?: string
  limit?: number
}

export const ORDER_LIST_DEFAULT_LIMIT = 20
export const ORDER_LIST_MAX_LIMIT = 100
