/**
 * OpStatus — operational lifecycle of a single booking_transport_item
 * or booking_activity_item row. Independent from `assignment_status`
 * and the parent booking's status.
 *
 * Model (client decision 2026-10-10):
 *   - A row with NO supplier is UNPLANNED; assigning a supplier auto-sets
 *     it to PLANNED; removing the supplier reverts it to UNPLANNED. This
 *     auto-flip applies ONLY while the row is in one of those two base
 *     states (see OP_STATUS_BASE). HOLD / PICKED_UP / NO_SHOW / CANCELLED
 *     are set manually and are "sticky" (supplier changes don't override).
 *   - PICKED_UP is the "done" state (activities read it as "Completed").
 *   - Terminal states (PICKED_UP, NO_SHOW, CANCELLED) don't move forward.
 *     An Admin may still override ANY status → any status to correct a
 *     mistaken update by the team (see `canTransition(..., allowAny)`).
 *
 * (Removed on 2026-10-10: DISPATCHED and DROPPED. Added: UNPLANNED, HOLD.)
 */
export enum OpStatus {
  UNPLANNED = 'UNPLANNED', // no supplier assigned
  PLANNED = 'PLANNED', // supplier assigned
  HOLD = 'HOLD', // manually parked
  PICKED_UP = 'PICKED_UP', // done (activity reads as "Completed")
  NO_SHOW = 'NO_SHOW',
  CANCELLED = 'CANCELLED',
}

/** Base states that the supplier auto-flip is allowed to move between. */
export const OP_STATUS_BASE: readonly OpStatus[] = [OpStatus.UNPLANNED, OpStatus.PLANNED];

/** Terminal/done states — no further forward transitions (Admin can still override). */
export const OP_STATUS_TERMINAL: readonly OpStatus[] = [
  OpStatus.PICKED_UP,
  OpStatus.NO_SHOW,
  OpStatus.CANCELLED,
];

/** The supplier-driven base status for a row. */
export function autoBaseStatus(hasSupplier: boolean): OpStatus {
  return hasSupplier ? OpStatus.PLANNED : OpStatus.UNPLANNED;
}

/**
 * Allowed forward transitions from each state for NON-admin users.
 * UNPLANNED ⇄ PLANNED is normally supplier-driven (auto), but we also
 * allow manual moves into HOLD and the terminal states from any live row.
 */
export const OP_STATUS_TRANSITIONS: Record<OpStatus, OpStatus[]> = {
  [OpStatus.UNPLANNED]: [OpStatus.PLANNED, OpStatus.HOLD, OpStatus.NO_SHOW, OpStatus.CANCELLED],
  [OpStatus.PLANNED]: [OpStatus.HOLD, OpStatus.PICKED_UP, OpStatus.NO_SHOW, OpStatus.CANCELLED],
  [OpStatus.HOLD]: [OpStatus.PLANNED, OpStatus.PICKED_UP, OpStatus.NO_SHOW, OpStatus.CANCELLED],
  [OpStatus.PICKED_UP]: [OpStatus.CANCELLED],
  [OpStatus.NO_SHOW]: [],
  [OpStatus.CANCELLED]: [],
};

/**
 * @param allowAny Admins pass true to override any status → any status
 *                 (fixing a mistaken update by the team).
 */
export function canTransition(
  from: OpStatus | null | undefined,
  to: OpStatus,
  allowAny = false,
): boolean {
  const src = from || OpStatus.UNPLANNED;
  if (src === to) return false;
  if (allowAny) return true;
  return (OP_STATUS_TRANSITIONS[src] || []).includes(to);
}
