import type { LucideIcon } from "lucide-react";
import {
  Ban,
  Check,
  MessageSquareWarning,
  Play,
  ShieldCheck,
  XCircle,
} from "lucide-react";

import type { AuthUser } from "@/auth/types";
import {
  FREIGHT_PERMS,
  hasPermission,
  isFreightApprovalAdmin,
} from "@/lib/permissions";
import type { BookingDetail, BookingStatus } from "@/types/booking";

export type BookingActionId =
  | "accept"
  | "requestChanges"
  | "reject"
  | "viewContract"
  | "signContractStaff"
  | "reviewClearance"
  | "allocateBooking"
  | "startTransit"
  | "complete"
  | "operationAccept"
  | "operationRequestChanges"
  | "cancel";

export type BookingActionInputKind =
  | "note"
  | "reason"
  | "file"
  | "days"
  | "amount";

export interface BookingActionDef {
  id: BookingActionId;
  label: string;
  shortLabel: string;
  description: string;
  confirmTitle: string;
  confirmDescription: string;
  variant: "default" | "destructive" | "outline";
  icon: LucideIcon;
  input?: BookingActionInputKind;
  inputLabel?: string;
  inputPlaceholder?: string;
  primary?: boolean;
}

export type BookingActionContext = Pick<
  BookingDetail,
  | "status"
  | "paymentCurrency"
  | "reference"
  | "schedulingStatus"
  | "customsClearingEnabled"
>;

const ALLOCATABLE_SCHEDULING_STATUSES = new Set([
  "NOT_SCHEDULED",
  "HOLDING",
  "ELIGIBLE",
  undefined,
  null,
  "",
]);

export function canAllocateBooking(
  booking: Pick<BookingDetail, "status" | "schedulingStatus">,
) {
  return (
    booking.status === "PAID" &&
    ALLOCATABLE_SCHEDULING_STATUSES.has(booking.schedulingStatus ?? undefined)
  );
}

const SUBMITTED_ACTIONS: BookingActionDef[] = [
  {
    id: "accept",
    label: "Accept for approval",
    shortLabel: "Accept",
    description: "Start the formal approval chain",
    confirmTitle: "Accept submission?",
    confirmDescription:
      "Set how long the contract stays valid, then the booking moves to pending approval and approval steps are created from the rule engine.",
    variant: "default",
    icon: ShieldCheck,
    primary: true,
    input: "days",
    inputLabel: "Contract validity (days)",
    inputPlaceholder: "e.g. 30",
  },
  {
    id: "requestChanges",
    label: "Request changes",
    shortLabel: "Changes",
    description: "Ask the customer to update and resubmit",
    confirmTitle: "Request changes from customer?",
    confirmDescription:
      "The customer will see your note and can edit the booking before resubmitting.",
    variant: "outline",
    icon: MessageSquareWarning,
    input: "note",
    inputLabel: "Message to customer",
    inputPlaceholder: "Describe what needs to be corrected or added…",
  },
  {
    id: "reject",
    label: "Reject booking",
    shortLabel: "Reject",
    description: "Reject this submission",
    confirmTitle: "Reject booking?",
    confirmDescription:
      "The booking will be marked rejected and removed from active queues.",
    variant: "destructive",
    icon: Ban,
    input: "reason",
    inputLabel: "Rejection reason",
    inputPlaceholder: "Reason for rejection…",
  },
];

// Marketing/operations review of a drawdown order's operation request.
const OPERATION_REVIEW_ACTIONS: BookingActionDef[] = [
  {
    id: "operationAccept",
    label: "Accept operation",
    shortLabel: "Accept",
    description: "Accept the operation request and release it for dispatch",
    confirmTitle: "Accept operation request?",
    confirmDescription:
      "Train orders enter the batch pool; road orders move to truck dispatch.",
    variant: "default",
    icon: Check,
    primary: true,
  },
  {
    id: "operationRequestChanges",
    label: "Request changes",
    shortLabel: "Changes",
    description: "Ask the customer to adjust the operation request",
    confirmTitle: "Request changes to the operation?",
    confirmDescription:
      "The customer will see your note and can adjust and resubmit the order.",
    variant: "outline",
    icon: MessageSquareWarning,
    input: "note",
    inputLabel: "Message to customer",
    inputPlaceholder: "Describe what needs to change…",
  },
];

const CANCEL_ACTION: BookingActionDef = {
  id: "cancel",
  label: "Cancel booking",
  shortLabel: "Cancel",
  description: "Cancel this booking",
  confirmTitle: "Cancel booking?",
  confirmDescription:
    "The booking will be marked cancelled. Provide a reason for the audit trail.",
  variant: "destructive",
  icon: Ban,
  input: "reason",
  inputLabel: "Cancellation reason",
  inputPlaceholder: "Reason for cancellation…",
};

// Opens the booking detail straight on the Clearance tab so Marketing can
// review the customer's clearance documents (non-customs bookings only).
const REVIEW_CLEARANCE_ACTION: BookingActionDef = {
  id: "reviewClearance",
  label: "Review clearance",
  shortLabel: "Clearance",
  description: "Approve or query the customer's clearance documents",
  confirmTitle: "",
  confirmDescription: "",
  variant: "default",
  icon: ShieldCheck,
  primary: true,
};

function withCancel(actions: BookingActionDef[]): BookingActionDef[] {
  return [...actions, CANCEL_ACTION];
}

const ACTION_PERMISSION: Partial<Record<BookingActionId, string>> = {
  accept: FREIGHT_PERMS.bookings.staffAccept,
  requestChanges: FREIGHT_PERMS.bookings.requestChanges,
  reject: FREIGHT_PERMS.bookings.reject,
  viewContract: FREIGHT_PERMS.bookings.view,
  signContractStaff: FREIGHT_PERMS.bookings.signStaff,
  reviewClearance: FREIGHT_PERMS.bookings.reviewDocuments,
  startTransit: FREIGHT_PERMS.bookings.operations,
  complete: FREIGHT_PERMS.bookings.operations,
  operationAccept: FREIGHT_PERMS.bookings.operations,
  operationRequestChanges: FREIGHT_PERMS.bookings.operations,
  allocateBooking: FREIGHT_PERMS.trainScheduling.update,
  cancel: FREIGHT_PERMS.bookings.cancel,
};

function filterActionsByUser(
  actions: BookingActionDef[],
  user: AuthUser | null | undefined,
): BookingActionDef[] {
  if (!user) return [];
  return actions.filter((action) => {
    const perm = ACTION_PERMISSION[action.id];
    return perm ? hasPermission(user, perm) : true;
  });
}

/** Actions available for the current booking status (detail or list). */
export function getBookingActions(
  ctx: BookingActionContext,
  user?: AuthUser | null,
): BookingActionDef[] {
  const { status } = ctx;

  let actions: BookingActionDef[];

  switch (status) {
    case "SUBMITTED":
      actions = withCancel(SUBMITTED_ACTIONS);
      break;
    case "PENDING_APPROVAL":
    case "APPROVED_PENDING_SIGNATURE":
    case "APPROVED":
      actions = [CANCEL_ACTION];
      break;
    case "CONTRACT_READY":
    case "SIGNED_CUSTOMER":
    case "FULLY_EXECUTED":
      // Contract view/sign/executed buttons intentionally removed from the
      // booking-request page.
      actions = [];
      break;
    case "AWAITING_DOCUMENTS":
    case "DOCUMENTS_UNDER_REVIEW":
      // Marketing reviews non-customs clearance here; customs bookings are
      // handled in the Global Logistics clearance queue, not the booking list.
      actions = ctx.customsClearingEnabled
        ? [CANCEL_ACTION]
        : withCancel([REVIEW_CLEARANCE_ACTION]);
      break;
    case "OPERATION_REQUEST_PENDING":
      actions = withCancel(OPERATION_REVIEW_ACTIONS);
      break;
    case "PAID":
      // Allocate is handled by the Operations "Ready to allocate" queue, not the
      // per-booking action menu. Start transit was removed entirely. No per-row
      // action remains in the PAID state.
      actions = [];
      break;
    case "IN_TRANSIT":
      actions = [
        {
          id: "complete",
          label: "Complete booking",
          shortLabel: "Complete",
          description: "Mark journey finished",
          confirmTitle: "Complete booking?",
          confirmDescription:
            "Marks the booking as completed. No further staff transitions apply.",
          variant: "default",
          icon: Play,
          primary: true,
        },
      ];
      break;
    case "CHANGES_REQUESTED":
      actions = [CANCEL_ACTION];
      break;
    case "PENDING_CONSOLIDATION":
      // View-only while waiting for a consolidation partner; cancel still allowed.
      actions = [CANCEL_ACTION];
      break;
    default:
      actions = [];
  }

  if (user === undefined) return actions;
  return filterActionsByUser(actions, user);
}

/** Opens contract page without confirmation dialog. */
export function isContractNavAction(id: BookingActionId): boolean {
  return id === "viewContract" || id === "signContractStaff";
}

/** Opens allocation wizard without confirmation dialog. */
export function isAllocateAction(id: BookingActionId): boolean {
  return id === "allocateBooking";
}

/** Opens the booking detail on the Clearance tab without a confirm dialog. */
export function isClearanceNavAction(id: BookingActionId): boolean {
  return id === "reviewClearance";
}

export function listRowHasActions(
  row: {
    status: BookingStatus;
    paymentCurrency: string;
    customsClearingEnabled?: boolean;
  },
  user?: AuthUser | null,
): boolean {
  const actions = getBookingActions(
    {
      status: row.status,
      paymentCurrency: row.paymentCurrency,
      reference: "",
      schedulingStatus: row.status,
      customsClearingEnabled: row.customsClearingEnabled,
    },
    user,
  );
  return actions.length > 0;
}
