import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { ExternalLink, MoreHorizontal, Receipt } from "lucide-react";
import { Button, Menu, ActionIcon, Group, Text } from "@mantine/core";

import { BookingConfirmDialog } from "./BookingConfirmDialog";
import { OperationRescheduleModal } from "./OperationRescheduleModal";
import { useBookingActionDialog } from "./useBookingActionDialog";
import { useAuth } from "@/auth/useAuth";
import { FREIGHT_PERMS, hasPermission as hasFreightPermission } from "@/lib/permissions";
import {
  isAllocateAction,
  isClearanceNavAction,
  isContractNavAction,
  isRescheduleAction,
  listRowHasActions,
  type BookingActionContext,
} from "@/features/bookings/booking-actions.config";
import type { BookingListRow } from "@/types/booking";

interface BookingActionsMenuProps {
  row: BookingListRow;
  /** Compact table cell vs. larger detail toolbar */
  variant?: "table" | "toolbar";
  className?: string;
  /** Suppresses table row navigation after menu/dialog close (click-through). */
  onSuppressRowClick?: () => void;
  onAllocateBooking?: () => void;
}

export function BookingActionsMenu({
  row,
  variant = "table",
  onSuppressRowClick,
  onAllocateBooking,
}: BookingActionsMenuProps) {
  const navigate = useNavigate();
  const { user } = useAuth();
  const context: BookingActionContext = {
    status: row.status,
    paymentCurrency: row.paymentCurrency,
    reference: row.reference,
    schedulingStatus: row.schedulingStatus,
    customsClearingEnabled: row.customsClearingEnabled,
    consolidationPartnerId: row.consolidationPartnerId,
  };

  const flow = useBookingActionDialog(row.id, context);
  const { actions, pendingAction, mutations } = flow;
  // Day / train reschedule has its own modal (date + export train picker).
  const [rescheduleOpen, setRescheduleOpen] = useState(false);

  const goToContract = () =>
    navigate(`/dashboard/booking-requests/${row.id}/contract`);

  const goToClearanceTab = () =>
    navigate(`/dashboard/booking-requests/${row.id}?tab=clearance`);

  const goToAdditionalCharges = () =>
    navigate(`/dashboard/booking-requests/${row.id}?tab=additional-charges`);

  const canSeeAdditionalCharges = hasFreightPermission(
    user,
    FREIGHT_PERMS.additionalCharges.view,
  );

  const handleAction = (action: (typeof actions)[number]) => {
    onSuppressRowClick?.();
    if (isContractNavAction(action.id)) {
      goToContract();
    } else if (isClearanceNavAction(action.id)) {
      goToClearanceTab();
    } else if (isAllocateAction(action.id)) {
      onAllocateBooking?.();
    } else if (isRescheduleAction(action.id)) {
      setRescheduleOpen(true);
    } else {
      flow.openAction(action);
    }
  };

  const hasMenu = listRowHasActions(row, user);

  // Row click already opens the detail page — no chevron affordance needed.
  if (!hasMenu && variant === "table") {
    return null;
  }

  // Toolbar: lay every action out as a button row.
  if (variant === "toolbar" && actions.length > 0) {
    return (
      <>
        <Group gap="sm" w="100%">
          {actions.map((action) => {
            const Icon = action.icon;
            const destructive = action.variant === "destructive";
            return (
              <Button
                key={action.id}
                size="sm"
                variant={action.primary && !destructive ? "filled" : "default"}
                color={destructive ? "red" : action.primary ? "edr-green" : "gray"}
                leftSection={<Icon size={16} />}
                disabled={mutations.isPending}
                onClick={() => handleAction(action)}
              >
                {action.label}
              </Button>
            );
          })}
        </Group>
        <ActionDialog
          flow={flow}
          pendingAction={pendingAction}
          onSuppressRowClick={onSuppressRowClick}
          consolidationPartnerId={row.consolidationPartnerId}
          consolidationPartnerReference={row.consolidationPartnerReference}
        />
        <OperationRescheduleModal
          bookingId={row.id}
          opened={rescheduleOpen}
          onClose={() => {
            onSuppressRowClick?.();
            setRescheduleOpen(false);
          }}
        />
      </>
    );
  }

  return (
    <Group
      gap={4}
      justify="flex-end"
      wrap="nowrap"
      data-stop-row-click
      onClick={(e) => e.stopPropagation()}
      onKeyDown={(e) => e.stopPropagation()}
    >
      <Menu position="bottom-end" width={220} withinPortal>
        <Menu.Target>
          <ActionIcon
            variant={variant === "table" ? "subtle" : "default"}
            color="gray"
            loading={mutations.isPending}
            aria-label="Booking actions"
          >
            <MoreHorizontal size={16} />
          </ActionIcon>
        </Menu.Target>
        <Menu.Dropdown>
          <Menu.Label>
            <Text size="xs" ff="monospace" c="dimmed">
              {row.reference}
            </Text>
          </Menu.Label>
          {actions.map((action) => {
            const Icon = action.icon;
            return (
              <Menu.Item
                key={action.id}
                color={action.variant === "destructive" ? "red" : undefined}
                leftSection={<Icon size={15} />}
                onClick={() => handleAction(action)}
              >
                {action.label}
              </Menu.Item>
            );
          })}
          {actions.length > 0 && <Menu.Divider />}
          {canSeeAdditionalCharges && (
            <Menu.Item
              leftSection={<Receipt size={15} />}
              onClick={() => {
                onSuppressRowClick?.();
                goToAdditionalCharges();
              }}
            >
              Additional charges
            </Menu.Item>
          )}
          <Menu.Item
            leftSection={<ExternalLink size={15} />}
            onClick={() => {
              onSuppressRowClick?.();
              navigate(`/dashboard/booking-requests/${row.id}`);
            }}
          >
            Open full details
          </Menu.Item>
        </Menu.Dropdown>
      </Menu>

      <ActionDialog
          flow={flow}
          pendingAction={pendingAction}
          onSuppressRowClick={onSuppressRowClick}
          consolidationPartnerId={row.consolidationPartnerId}
          consolidationPartnerReference={row.consolidationPartnerReference}
        />
      <OperationRescheduleModal
        bookingId={row.id}
        opened={rescheduleOpen}
        onClose={() => {
          onSuppressRowClick?.();
          setRescheduleOpen(false);
        }}
      />
    </Group>
  );
}

function ActionDialog({
  flow,
  pendingAction,
  onSuppressRowClick,
  consolidationPartnerId,
  consolidationPartnerReference,
}: {
  flow: ReturnType<typeof useBookingActionDialog>;
  pendingAction: ReturnType<typeof useBookingActionDialog>["pendingAction"];
  onSuppressRowClick?: () => void;
  consolidationPartnerId?: string | null;
  consolidationPartnerReference?: string | null;
}) {
  return (
    <BookingConfirmDialog
      open={flow.dialogOpen}
      onOpenChange={(open) => {
        if (!open) onSuppressRowClick?.();
        flow.setDialogOpen(open);
      }}
      action={pendingAction}
      reference={flow.mergedContext.reference}
      inputValue={flow.inputValue}
      onInputChange={flow.setInputValue}
      selectedFile={flow.selectedFile}
      onFileChange={flow.setSelectedFile}
      onConfirm={() => {
        onSuppressRowClick?.();
        flow.runAction();
      }}
      isPending={flow.mutations.isPending || flow.detailLoading}
      confirmDisabled={flow.confirmDisabled}
      // Only the four pairable decisions land on both halves; the rest stay
      // per booking, so the warning must not appear for them.
      pairedWithReference={
        consolidationPartnerId &&
        pendingAction &&
        ["accept", "cancel", "operationAccept", "requestChanges"].includes(
          pendingAction.id,
        )
          ? (consolidationPartnerReference ?? "its wagon partner")
          : null
      }
    />
  );
}
