export const WAREHOUSE_TYPES = ['OPEN_WAREHOUSE', 'CLOSED_WAREHOUSE'] as const;
export type WarehouseType = (typeof WAREHOUSE_TYPES)[number];

export const WAREHOUSE_STATUSES = ['ACTIVE', 'INACTIVE'] as const;
export type WarehouseStatus = (typeof WAREHOUSE_STATUSES)[number];

export const WAREHOUSE_YARD_TYPES = [
  'CONTAINER_YARD',
  'BULK_YARD',
  'GENERAL_CARGO_YARD',
  'HAZARDOUS_YARD',
  'COLD_STORAGE_YARD',
] as const;
export type WarehouseYardType = (typeof WAREHOUSE_YARD_TYPES)[number];

export const WAREHOUSE_ZONE_TYPES = [
  'CONTAINER_ZONE',
  'BULK_ZONE',
  'GENERAL_CARGO_ZONE',
  'HAZARDOUS_ZONE',
  'COLD_STORAGE_ZONE',
] as const;
export type WarehouseZoneType = (typeof WAREHOUSE_ZONE_TYPES)[number];

export const INVENTORY_STATUSES = [
  'UNLOADED',
  'RECEIVED',
  'STORED',
  'RESERVED',
  'READY_FOR_LOADING',
  'LOADED',
  'DISPATCHED',
  // Import branch
  'READY_FOR_PICKUP',
  'DELIVERED',
] as const;
export type InventoryStatus = (typeof INVENTORY_STATUSES)[number];

export type InventoryAction =
  | 'store'
  | 'reserve'
  | 'ready-for-loading'
  | 'load'
  | 'dispatch'
  // Import branch
  | 'ready-for-pickup'
  | 'release'
  | 'deliver';

/**
 * Default next lifecycle action keyed by current status. The RECEIVED and
 * READY_FOR_PICKUP rows are direction/release dependent — use
 * {@link getNextInventoryAction} which resolves those at runtime.
 */
export const INVENTORY_NEXT_ACTION: Record<InventoryStatus, InventoryAction | null> = {
  UNLOADED: 'store',
  RECEIVED: 'store',
  STORED: 'reserve',
  RESERVED: 'ready-for-loading',
  READY_FOR_LOADING: 'load',
  LOADED: 'dispatch',
  DISPATCHED: null,
  READY_FOR_PICKUP: 'release',
  DELIVERED: null,
};

/**
 * Resolve the next action for an inventory item, accounting for trade
 * direction, the inspection gate, and whether a release order was issued.
 * Returns null when no advance button should be shown (e.g. awaiting inspection).
 */
export function getNextInventoryAction(item: WarehouseInventoryItem): InventoryAction | null {
  const inspected = item.inspectionStatus === 'PASSED';
  const isImport = item.booking?.tradeDirection === 'IMPORT';

  switch (item.status) {
    case 'UNLOADED':
    case 'RECEIVED':
      // Import goods skip storage; they need inspection before pickup.
      if (isImport) return inspected ? 'ready-for-pickup' : null;
      return 'store';
    case 'RESERVED':
      // Export loading is gated on a passed inspection.
      return inspected ? 'ready-for-loading' : null;
    case 'READY_FOR_PICKUP':
      // Issue the DO / release order first, then hand over the goods.
      return item.releaseDate ? 'deliver' : 'release';
    default:
      return INVENTORY_NEXT_ACTION[item.status];
  }
}

export interface WarehouseZone {
  id: string;
  yardId: string;
  name: string;
  code: string;
  type: WarehouseZoneType;
  capacityWeight: number | null;
  capacityContainers: number | null;
  maxWeight: number | null;
  maxVolume: number | null;
  currentWeight: number;
  currentContainers: number;
  currentVolume: number;
  status: WarehouseStatus;
  isActive: boolean;
}

export interface WarehouseYard {
  id: string;
  warehouseId: string;
  name: string;
  code: string;
  type: WarehouseYardType;
  capacityWeight: number | null;
  capacityContainers: number | null;
  maxWeight: number | null;
  maxVolume: number | null;
  currentWeight: number;
  currentContainers: number;
  currentVolume: number;
  status: WarehouseStatus;
  isActive: boolean;
  zones?: WarehouseZone[];
}

export const FACILITY_TYPES = [
  'PORT',
  'DRY_PORT',
  'TERMINAL',
  'RAIL_YARD',
  'WAREHOUSE_COMPLEX',
] as const;
export type FacilityType = (typeof FACILITY_TYPES)[number];

export interface Facility {
  id: string;
  code: string;
  name: string;
  facilityType: FacilityType;
  facilityStatus?: string;
  locationName?: string | null;
  city?: string | null;
  country?: string | null;
  isActive?: boolean;
}

export interface Warehouse {
  id: string;
  name: string;
  code: string;
  type: WarehouseType;
  stationId: string | null;
  facilityId: string | null;
  facility?: Facility | null;
  locationName: string | null;
  capacityWeight: number | null;
  capacityContainers: number | null;
  maxWeight: number | null;
  maxVolume: number | null;
  currentWeight: number;
  currentContainers: number;
  currentVolume: number;
  status: WarehouseStatus;
  isActive: boolean;
  yards?: WarehouseYard[];
  createdAt?: string;
  updatedAt?: string;
}

export interface WarehouseInventoryItem {
  id: string;
  warehouseId: string;
  yardId: string;
  zoneId: string;
  bookingId: string | null;
  cargoId: string | null;
  containerId: string | null;
  goodsId: string | null;
  quantity: number;
  weight: number;
  volume: number | null;
  status: InventoryStatus;
  inspectionStatus: string | null;
  arrivedAt: string | null;
  storedAt: string | null;
  reservedAt: string | null;
  inspectedAt: string | null;
  readyForLoadingAt: string | null;
  loadedAt: string | null;
  dispatchedAt: string | null;
  // Import branch
  readyForPickupAt: string | null;
  releaseDate: string | null;
  releaseOrderReference: string | null;
  deliveredAt: string | null;
  notes: string | null;
  warehouse?: Warehouse | null;
  yard?: WarehouseYard | null;
  zone?: WarehouseZone | null;
  booking?: InventoryBookingRef | null;
}

/** Slim booking shape returned alongside inventory for the loading queue. */
export interface InventoryBookingRef {
  id: string;
  reference?: string | null;
  status?: string | null;
  paymentStatus?: string | null;
  tradeDirection?: string | null;
  // Present when the customer requested last-mile (door) delivery — gates the Last Mile action.
  lastMileDeliveryAddress?: string | null;
}

export interface InventoryMovement {
  id: string;
  inventoryId: string;
  fromWarehouseId: string;
  fromYardId: string;
  fromZoneId: string;
  toWarehouseId: string;
  toYardId: string;
  toZoneId: string;
  remarks: string | null;
  movedBy: string | null;
  movedAt: string;
}

export const ACTIVITY_TYPES = [
  'INVENTORY_RECEIVED',
  'INVENTORY_STORED',
  'INVENTORY_MOVED',
  'INVENTORY_RESERVED',
  'READY_FOR_LOADING',
  'INVENTORY_LOADED',
  'INVENTORY_DISPATCHED',
] as const;
export type ActivityType = (typeof ACTIVITY_TYPES)[number];

export interface WarehouseActivityLog {
  id: string;
  inventoryId: string | null;
  warehouseId: string | null;
  activityType: ActivityType;
  description: string | null;
  performedBy: string | null;
  createdAt: string;
}

export interface WarehouseDashboard {
  totalWarehouses: number;
  totalInventory: number;
  receivedToday: number;
  awaitingInspection: number;
  inspected: number;
  stored: number;
  reserved: number;
  readyForLoading: number;
  loaded: number;
  dispatched: number;
  readyForPickup: number;
  delivered: number;
}

// ── Loading (Batch 3) ────────────────────────────────────────────────────────

export interface WarehouseLoading {
  id: string;
  warehouseInventoryId: string;
  bookingId: string | null;
  wagonId: string;
  wagonNumber?: string | null;
  loadedAt: string;
  loadedBy: string | null;
  loadedWeight: number | null;
  notes: string | null;
  inventory?: WarehouseInventoryItem | null;
}

export interface LoadInventoryPayload {
  wagonId: string;
  loadedWeight?: number;
  loadedBy?: string;
  notes?: string;
}

/** Read-only wagon view exposed by the scheduling facade. */
export interface LoadableWagon {
  id: string;
  wagonNumber: string;
  status: string;
  trainId: string | null;
}

/** Read-only schedule + wagon + departure status for a booking. */
export interface BookingScheduleView {
  schedule: {
    id: string;
    status: string;
    scheduledDepartureDate: string | null;
    scheduledArrivalDate: string | null;
    originStationId: string | null;
    destinationStationId: string | null;
  } | null;
  wagon: {
    wagonId: string | null;
    wagonNumber: string | null;
    sequenceNo: number | null;
    allocatedWeightTons: number | null;
  } | null;
  departureStatus: string | null;
}

export interface MoveInventoryPayload {
  warehouseId: string;
  yardId: string;
  zoneId: string;
  remarks?: string;
}

export interface ReserveInventoryPayload {
  bookingId: string;
  inventoryId: string;
}

/** Import branch: DO / release order sent to the customer. */
export interface ReleaseOrderPayload {
  reference?: string;
  releaseDate?: string;
}

/** Import branch: proof of delivery captured on customer pickup. */
export interface DeliverInventoryPayload {
  receiverName: string;
  deliveredAt?: string;
  remarks?: string;
}

/** Receive (Import/Export) bulk flow. */
export interface EligibleBooking {
  id: string;
  reference: string;
  customerId: string | null;
  customer: string | null;
  direction: string;
  origin: string | null;
  destination: string | null;
  freightType: string | null;
  cargo: string | null;
  weight: string | null;
  paymentStatus: string;
  status: string;
}

export interface BulkReceivePayload {
  direction: 'IMPORT' | 'EXPORT';
  warehouseId: string;
  yardId: string;
  zoneId: string;
  bookingIds: string[];
}

export interface BulkReceiveResult {
  receivedCount: number;
  skippedCount: number;
  results: { bookingId: string; status: string; inventoryId?: string; reason?: string }[];
}

export interface LoadPassedExportResult {
  loadedCount: number;
  skippedCount: number;
  results: { inventoryId: string; status: string; reason?: string }[];
}

export interface BulkInspectPayload {
  inventoryIds: string[];
  inspectionType?: string;
  remarks?: string;
}

export interface BulkInspectResult {
  inspectedCount: number;
  skippedCount: number;
  results: { inventoryId: string; status: string; reason?: string }[];
}

export interface ReadyToLoadRow {
  id: string;
  bookingId: string | null;
  bookingReference: string | null;
  customerId: string | null;
  customerName: string | null;
  containerNumber: string | null;
  cargoType: string | null;
  weight: number | null;
  origin: string | null;
  destination: string | null;
  inspectionStatus: string | null;
  status: string;
}

export interface BulkDispatchResult {
  dispatchedCount: number;
  skippedCount: number;
  results: { inventoryId: string; status: string; reason?: string }[];
}

export interface ImportTrain {
  scheduleId: string;
  trainNumber: string | null;
  route: string | null;
  origin: string | null;
  destination: string | null;
  arrivalTime: string | null;
  totalBookings: number;
  totalContainers: number;
  totalCargoes: number;
  status: string;
}

export interface AutoUnloadArrivedResult {
  unloadedCount: number;
  skippedCount: number;
  failedCount: number;
  results: { bookingId: string; inventoryId?: string; status: string; reason?: string }[];
}

export interface ImportUnloadedItem {
  id: string;
  bookingId: string | null;
  bookingReference: string | null;
  customerId: string | null;
  customerName: string | null;
  arrivalTime: string | null;
  containerNumber: string | null;
  cargoType: string | null;
  weight: number | null;
  trainSchedule: string | null;
  inspectionStatus: string | null;
  pickupOption: string;
  lastMileRequested: boolean;
  currentStatus: string;
}

export interface ImportTrainItem {
  bookingId: string;
  bookingReference: string | null;
  customerId: string | null;
  customerName: string | null;
  containerNumber: string | null;
  cargoType: string | null;
  weight: number | null;
  arrivalTime: string | null;
  currentStatus: string | null;
  lastMileRequested: boolean;
  pickupOption: string;
}

export interface InventoryInquiryResult {
  id: string;
  bookingId: string;
  bookingNumber: string | null;
  customerName: string | null;
  containerNumber: string | null;
  cargoType: string | null;
  cargoDescription: string | null;
  goodsId: string | null;
  warehouse: { id: string; name: string; code: string } | null;
  yard: { id: string; name: string; code: string } | null;
  zone: { id: string; name: string; code: string } | null;
  status: InventoryStatus;
  quantity: number;
  weight: number;
  arrivedAt: string | null;
  readyForLoadingAt: string | null;
}

// ── Batch 4.5: Arrival / Unload / Inspection ────────────────────────────────

export interface ArrivalQueueItem {
  bookingId: string;
  bookingReference: string;
  customer: string | null;
  cargo: string | null;
  container: string | null;
  facility: string | null;
  warehouse: string | null;
  yard: string | null;
  zone: string | null;
  inventoryId: string | null;
  currentStatus: string | null;
  arrivalDate: string | null;
  inspectionStatus: string | null;
  unloaded: boolean;
}

export interface AutoUnloadResult {
  processedCount: number;
  skippedCount: number;
  failedCount: number;
  results: { bookingId: string; inventoryId?: string; status: string; reason?: string }[];
}

export interface AutoLoadResult {
  loadedCount: number;
  skippedCount: number;
  results: { inventoryId: string; status: string; reason?: string }[];
}

export const INSPECTION_REPORT_TYPES = [
  'INSPECTION',
  'DAMAGE',
  'WEIGHT_LOSS',
  'MISSING_ITEM',
  'GENERAL',
] as const;
export type InspectionReportType = (typeof INSPECTION_REPORT_TYPES)[number];

export const INSPECTION_STATUSES = ['PASSED', 'FAILED', 'NEEDS_REVIEW'] as const;
export type InspectionResultStatus = (typeof INSPECTION_STATUSES)[number];

export interface InspectionReportPayload {
  reportType: InspectionReportType;
  inspectionStatus: InspectionResultStatus;
  hasDamage?: boolean;
  damageDescription?: string;
  hasWeightLoss?: boolean;
  expectedWeight?: number;
  actualWeight?: number;
  hasMissingItems?: boolean;
  missingItemsDescription?: string;
  remarks?: string;
}

export interface InspectionAttachment {
  id: string;
  name: string;
  url: string;
  mimeType: string;
  size: number;
}

export interface InspectionReport extends InspectionReportPayload {
  id: string;
  inventoryId: string;
  bookingId: string | null;
  weightLoss?: number | null;
  inspectedAt: string | null;
  createdAt: string;
  attachments?: InspectionAttachment[];
}

// ── Batch 5: Allocation + Fee rules / preview ───────────────────────────────

export interface AllocationRule {
  id: string;
  name: string;
  priority: number;
  freightType?: string | null;
  tradeDirection?: string | null;
  cargoTypeCode?: string | null;
  containerStatus?: string | null;
  requiresInspection?: boolean | null;
  targetFacilityCode?: string | null;
  targetYardCode: string;
  targetWarehouseCode?: string | null;
  targetZoneCode?: string | null;
  storageType?: string | null;
  isActive: boolean;
}
export type SaveAllocationRulePayload = Omit<AllocationRule, 'id'>;

export const FEE_RULE_TYPES = ['STORAGE_FEE', 'DEMURRAGE_FEE'] as const;
export type FeeRuleType = (typeof FEE_RULE_TYPES)[number];

export interface FeeRule {
  id: string;
  name: string;
  ruleType: FeeRuleType;
  priority: number;
  freightType?: string | null;
  tradeDirection?: string | null;
  cargoTypeCode?: string | null;
  containerType?: string | null;
  facilityId?: string | null;
  warehouseId?: string | null;
  yardId?: string | null;
  zoneId?: string | null;
  freeDays: number;
  ratePerDay: number;
  currency: string;
  isActive: boolean;
}
export type SaveFeeRulePayload = Omit<FeeRule, 'id'>;

export interface FeePreview {
  ruleType: FeeRuleType;
  ruleId: string | null;
  ruleName: string | null;
  freeDays: number;
  ratePerDay: number;
  currency: string;
  startDate: string | null;
  endDate: string;
  endIsOpen: boolean;
  elapsedDays: number;
  chargeableDays: number;
  amount: number;
}

export interface AllocationPreviewResult {
  warehouseId: string;
  yardId: string;
  zoneId: string;
  facilityId: string | null;
  rule: { id: string; name: string; storageType: string | null } | null;
  path: string;
}

export interface AllocationCriteria {
  freightType?: string;
  tradeDirection?: string;
  cargoTypeCode?: string;
  containerStatus?: string;
  requiresInspection?: boolean;
}

// ── Batch 6: Warehouse fee invoices ─────────────────────────────────────────

export const WAREHOUSE_INVOICE_STATUSES = [
  'DRAFT',
  'ISSUED',
  'PARTIALLY_PAID',
  'PAID',
  'CANCELLED',
] as const;
export type WarehouseInvoiceStatus = (typeof WAREHOUSE_INVOICE_STATUSES)[number];

export const WAREHOUSE_INVOICE_TYPES = ['DEMURRAGE', 'STORAGE_FEE', 'MIXED_WAREHOUSE_FEES'] as const;
export type WarehouseInvoiceType = (typeof WAREHOUSE_INVOICE_TYPES)[number];

export interface WarehouseInvoicePaymentRecord {
  amount: number;
  method?: string | null;
  reference?: string | null;
  paidAt: string;
}

export interface WarehouseFeeInvoiceItem {
  id: string;
  invoiceId: string;
  feeRuleId?: string | null;
  feeType: string;
  description: string;
  quantity: number;
  unitRate: number;
  amount: number;
  currency: string;
  chargeableDays?: number | null;
  freeDays?: number | null;
}

export interface WarehouseFeeInvoice {
  id: string;
  invoiceNumber: string;
  bookingId?: string | null;
  customerId?: string | null;
  inventoryId: string;
  facilityId?: string | null;
  warehouseId?: string | null;
  yardId?: string | null;
  zoneId?: string | null;
  invoiceType: WarehouseInvoiceType;
  status: WarehouseInvoiceStatus;
  subtotalAmount: number;
  taxAmount: number;
  totalAmount: number;
  paidAmount: number;
  balanceAmount: number;
  currency: string;
  periodStart?: string | null;
  periodEnd?: string | null;
  issuedAt?: string | null;
  dueDate?: string | null;
  paidAt?: string | null;
  cancelledAt?: string | null;
  payments?: WarehouseInvoicePaymentRecord[];
  notes?: string | null;
  items?: WarehouseFeeInvoiceItem[];
}

export interface WarehouseInvoiceFilter {
  status?: WarehouseInvoiceStatus;
  invoiceType?: WarehouseInvoiceType;
  warehouseId?: string;
  facilityId?: string;
  customerId?: string;
  bookingId?: string;
}

export interface PayInvoicePayload {
  amount: number;
  method?: string;
  reference?: string;
}

// ── Payloads ───────────────────────────────────────────────────────────────

export interface SaveWarehousePayload {
  name: string;
  code: string;
  type: WarehouseType;
  stationId?: string;
  facilityId?: string;
  locationName?: string;
  capacityWeight?: number;
  capacityContainers?: number;
  maxWeight?: number;
  maxVolume?: number;
  status?: WarehouseStatus;
}

export interface SaveYardPayload {
  name: string;
  code: string;
  type: WarehouseYardType;
  capacityWeight?: number;
  capacityContainers?: number;
  maxWeight?: number;
  maxVolume?: number;
  status?: WarehouseStatus;
}

export interface SaveZonePayload {
  name: string;
  code: string;
  type: WarehouseZoneType;
  capacityWeight?: number;
  capacityContainers?: number;
  maxWeight?: number;
  maxVolume?: number;
  status?: WarehouseStatus;
}

export interface ReceiveInventoryPayload {
  warehouseId: string;
  yardId: string;
  zoneId: string;
  bookingId: string;
  cargoId?: string;
  containerId?: string;
  goodsId?: string;
  quantity: number;
  weight: number;
  volume?: number;
  notes?: string;
}

export interface WarehouseFilter {
  search?: string;
  type?: WarehouseType;
  stationId?: string;
  status?: WarehouseStatus;
}

export interface InventoryFilter {
  warehouseId?: string;
  yardId?: string;
  zoneId?: string;
  bookingId?: string;
  cargoId?: string;
  containerId?: string;
  goodsId?: string;
  status?: InventoryStatus;
  search?: string;
}

export interface InventoryInquiryFilter {
  bookingNumber?: string;
  containerNumber?: string;
  cargoType?: string;
  goodsName?: string;
  warehouseId?: string;
  yardId?: string;
  zoneId?: string;
  status?: InventoryStatus;
}
