import { Fragment, useState, type MouseEvent } from 'react';
import { ActionIcon, Badge, Button, Checkbox, Group, Table, Text, Tooltip } from '@mantine/core';
import { ArrowRightLeft, ChevronDown, ChevronRight, ClipboardList, Coins, Download, Eye, FileText, History, MapPin } from 'lucide-react';

import { useToast } from '@/hooks/use-toast';
import { warehouseService } from '@/services/warehouse.service';
import {
  getNextInventoryAction,
  type InventoryAction,
  type WarehouseInventoryItem,
} from '@/types/warehouse';
import { InventoryStatusBadge } from './badges';
import { TruckBreakdownRow } from './TruckBreakdownRow';
import { extractDownloadErrorMessage, formatDate, formatNumber, humanizeEnum } from './options';
import { openPdfBlob } from './pdf';

interface WarehouseInventoryTableProps {
  items: WarehouseInventoryItem[];
  busyId?: string | null;
  onAdvance: (item: WarehouseInventoryItem, action: InventoryAction) => void;
  onMove: (item: WarehouseInventoryItem) => void;
  onHistory: (item: WarehouseInventoryItem) => void;
  onView?: (item: WarehouseInventoryItem) => void;
  onInspect?: (item: WarehouseInventoryItem) => void;
  onFeePreview?: (item: WarehouseInventoryItem) => void;
  onReleaseDocument?: (item: WarehouseInventoryItem) => void;
  onHandoverDocument?: (item: WarehouseInventoryItem) => void;
  onDownloadBundle?: (item: WarehouseInventoryItem) => void;
  onLastMile?: (item: WarehouseInventoryItem) => void;
  selectedIds?: Set<string>;
  onToggleSelect?: (id: string) => void;
  onToggleSelectAll?: () => void;
  allSelected?: boolean;
  someSelected?: boolean;
}

const itemKind = (item: WarehouseInventoryItem) => {
  if (item.containerId) return { label: 'Container', color: 'blue' };
  if (item.cargoId) return { label: 'Cargo', color: 'grape' };
  if (item.goodsId) return { label: 'Goods', color: 'orange' };
  return { label: '-', color: 'gray' };
};

const actionColor: Record<InventoryAction, string> = {
  store: 'blue',
  'ready-for-loading': 'cyan',
  load: 'teal',
  dispatch: 'edr-green',
  'ready-for-pickup': 'orange',
  release: 'yellow',
  deliver: 'green',
};

// After the first truck registers, the modal decides per truck whether it is
// arriving or leaving — the item-level label covers both for multi-truck.
const releaseActionLabel = (item: WarehouseInventoryItem) =>
  item.releaseOrderReference ? 'Truck Arrival / Leaving' : 'Truck Arrival';

const noteLineValue = (notes: string | null | undefined, label: string) => {
  const match = notes?.match(new RegExp(`^${label}:\\s*(.+)$`, 'im'));
  return match?.[1]?.trim() ?? '';
};

const handoverDocumentReference = (item: WarehouseInventoryItem) =>
  item.handoverDocumentReference ?? noteLineValue(item.notes, 'Handover Reference');

function GrnDocumentButton({ item }: { item: WarehouseInventoryItem }) {
  const { toast } = useToast();
  const [loading, setLoading] = useState(false);

  const openDocument = async (event: MouseEvent<HTMLButtonElement>) => {
    event.stopPropagation();
    if (!item.grnNumber) {
      toast({ variant: 'destructive', title: 'GRN document unavailable', description: 'This item has no GRN number yet.' });
      return;
    }
    setLoading(true);
    const pdfWindow = window.open('', '_blank');
    try {
      const response = await warehouseService.downloadGrnDocument(item.id);
      const opened = openPdfBlob(response.data, `grn-${item.grnNumber}.pdf`, pdfWindow);
      toast({ title: opened ? 'GRN document opened' : 'GRN document downloaded' });
    } catch (error) {
      pdfWindow?.close();
      toast({ variant: 'destructive', title: 'GRN document failed', description: await extractDownloadErrorMessage(error) });
    } finally {
      setLoading(false);
    }
  };

  return (
    <Button
      size="compact-xs"
      variant="subtle"
      color="teal"
      leftSection={<FileText size={12} />}
      disabled={!item.grnNumber}
      loading={loading}
      onClick={openDocument}
    >
      {item.grnNumber ?? 'No GRN'}
    </Button>
  );
}

export function WarehouseInventoryTable({
  items,
  busyId,
  onAdvance,
  onMove,
  onHistory,
  onView,
  onInspect,
  onFeePreview,
  onReleaseDocument,
  onHandoverDocument,
  onDownloadBundle,
  onLastMile,
  selectedIds,
  onToggleSelect,
  onToggleSelectAll,
  allSelected,
  someSelected,
}: WarehouseInventoryTableProps) {
  const selectable = Boolean(onToggleSelect);
  // Bookings whose truck breakdown is open. Expanded rows fetch on demand, so a
  // closed table costs nothing extra.
  const [expanded, setExpanded] = useState<Set<string>>(new Set());
  const toggleExpanded = (bookingId: string) =>
    setExpanded((prev) => {
      const next = new Set(prev);
      if (next.has(bookingId)) next.delete(bookingId);
      else next.add(bookingId);
      return next;
    });

  if (items.length === 0) {
    return (
      <Text size="sm" c="dimmed" ta="center" py="xl">
        No inventory items found.
      </Text>
    );
  }

  return (
    <Table.ScrollContainer minWidth={1150}>
      <Table highlightOnHover verticalSpacing="sm" striped>
        <Table.Thead>
          <Table.Tr>
            {selectable && (
              <Table.Th w={40}>
                <Checkbox
                  aria-label="Select all"
                  checked={allSelected}
                  indeterminate={someSelected}
                  onChange={onToggleSelectAll}
                />
              </Table.Th>
            )}
            {/* Expander for the per-truck breakdown. */}
            <Table.Th w={32} />
            <Table.Th>Booking</Table.Th>
            <Table.Th>GRN</Table.Th>
            <Table.Th>Facility</Table.Th>
            <Table.Th>Warehouse</Table.Th>
            <Table.Th>Yard</Table.Th>
            <Table.Th>Zone</Table.Th>
            <Table.Th>Item</Table.Th>
            <Table.Th>Qty</Table.Th>
            <Table.Th>Weight</Table.Th>
            <Table.Th>Status</Table.Th>
            <Table.Th>Arrived</Table.Th>
            <Table.Th ta="right">Actions</Table.Th>
          </Table.Tr>
        </Table.Thead>
        <Table.Tbody>
          {items.map((item) => {
            const kind = itemKind(item);
            const busy = busyId === item.id;
            // Per-booking Load and Dispatch are retired: wagon loading happens in
            // the train flow and dispatch at the train level (which already
            // advances inventory). Only the remaining lifecycle actions render.
            const rawNextAction = getNextInventoryAction(item);
            const nextAction =
              rawNextAction === 'load' || rawNextAction === 'dispatch' ? null : rawNextAction;
            const canGenerateHandover =
              item.inspectionStatus === 'PASSED' &&
              Boolean(item.bookingId) &&
              (!item.booking?.tradeDirection || item.booking.tradeDirection === 'IMPORT');
            const handoverReference = handoverDocumentReference(item);

            // Only offer the breakdown where there is one: a plate means at
            // least one customer truck is on the booking.
            const hasCustomerTrucks = Boolean(
              item.bookingId && item.booking?.customerTruckPlateNumber?.trim(),
            );
            const isExpanded = Boolean(item.bookingId && expanded.has(item.bookingId));

            return (
              <Fragment key={item.id}>
              <Table.Tr>
                {selectable && (
                  <Table.Td>
                    <Checkbox
                      aria-label={`Select ${item.bookingReference ?? item.booking?.reference ?? item.bookingId ?? item.id}`}
                      checked={selectedIds?.has(item.id) ?? false}
                      onChange={() => onToggleSelect?.(item.id)}
                    />
                  </Table.Td>
                )}
                <Table.Td>
                  {hasCustomerTrucks ? (
                    <Tooltip
                      label={isExpanded ? 'Hide trucks' : 'Show which containers ride which truck'}
                      withArrow
                    >
                      <ActionIcon
                        variant="subtle"
                        size="sm"
                        aria-label={isExpanded ? 'Hide trucks' : 'Show trucks'}
                        onClick={() => toggleExpanded(item.bookingId as string)}
                      >
                        {isExpanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                      </ActionIcon>
                    </Tooltip>
                  ) : null}
                </Table.Td>
                <Table.Td>
                  {item.bookingReference || item.booking?.reference || item.bookingId ? (
                    <Tooltip label={item.bookingId ?? ''} withArrow disabled={!item.bookingId}>
                      <Text size="sm" fw={600}>
                        {item.bookingReference ?? item.booking?.reference ?? `${item.bookingId?.slice(0, 8)}...`}
                      </Text>
                    </Tooltip>
                  ) : (
                    <Text size="sm" c="dimmed">
                      -
                    </Text>
                  )}
                </Table.Td>
                <Table.Td>
                  <GrnDocumentButton item={item} />
                </Table.Td>
                <Table.Td>{item.warehouse?.facility?.name ?? '-'}</Table.Td>
                <Table.Td>{item.warehouse?.code ?? '-'}</Table.Td>
                <Table.Td>{item.yard?.code ?? '-'}</Table.Td>
                <Table.Td>{item.zone?.code ?? '-'}</Table.Td>
                <Table.Td>
                  <Badge color={kind.color} variant="light" size="sm" radius="md">
                    {kind.label}
                  </Badge>
                </Table.Td>
                <Table.Td>{formatNumber(item.quantity)}</Table.Td>
                <Table.Td>{formatNumber(item.weight)}</Table.Td>
                <Table.Td>
                  <InventoryStatusBadge status={item.status} />
                </Table.Td>
                <Table.Td>
                  <Text size="xs">{formatDate(item.arrivedAt)}</Text>
                </Table.Td>
                <Table.Td>
                  <Group gap="xs" justify="flex-end" wrap="nowrap">
                    {onView && (
                      <Tooltip label="View details" withArrow>
                        <ActionIcon variant="subtle" color="gray" onClick={() => onView(item)}>
                          <Eye size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    {nextAction && (
                      <Button
                        size="compact-xs"
                        variant="light"
                        color={actionColor[nextAction]}
                        loading={busy}
                        onClick={() => onAdvance(item, nextAction)}
                      >
                        {nextAction === 'release' ? releaseActionLabel(item) : humanizeEnum(nextAction.replace(/-/g, '_'))}
                      </Button>
                    )}
                    {/* After the first exit the primary action flips to Deliver, but a
                        multi-truck booking still weighs its remaining trucks in and out. */}
                    {item.status === 'READY_FOR_PICKUP' && item.releaseDate && nextAction !== 'release' && (
                      <Button
                        size="compact-xs"
                        variant="light"
                        color="yellow"
                        loading={busy}
                        onClick={() => onAdvance(item, 'release')}
                      >
                        Truck Arrival / Leaving
                      </Button>
                    )}
                    {item.status === 'READY_FOR_PICKUP' && (
                      <Button
                        size="compact-xs"
                        variant="light"
                        color="blue"
                        loading={busy}
                        onClick={() => onAdvance(item, 'store')}
                      >
                        Store
                      </Button>
                    )}
                    {item.status !== 'DISPATCHED' && (
                      <Tooltip label="Move" withArrow>
                        <ActionIcon variant="subtle" color="gray" onClick={() => onMove(item)}>
                          <ArrowRightLeft size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    {onInspect && (
                      <Tooltip label="Inspection / Report" withArrow>
                        <ActionIcon variant="subtle" color="orange" onClick={() => onInspect(item)}>
                          <ClipboardList size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    {onFeePreview && (
                      <Tooltip label="Storage / Demurrage preview" withArrow>
                        <ActionIcon variant="subtle" color="teal" onClick={() => onFeePreview(item)}>
                          <Coins size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    {onReleaseDocument && item.releaseDate && (
                      <Tooltip label="View release exit paper" withArrow>
                        <ActionIcon variant="subtle" color="orange" onClick={() => onReleaseDocument(item)}>
                          <FileText size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    {onHandoverDocument && canGenerateHandover && (
                      <Tooltip
                        label={handoverReference ? `View handover document ${handoverReference}` : 'Generate customer handover document'}
                        withArrow
                      >
                        <ActionIcon variant="subtle" color="teal" onClick={() => onHandoverDocument(item)}>
                          <FileText size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    {onDownloadBundle && item.grnNumber && (
                      <Tooltip label="Download document bundle (GRN + gate clearance + handover)" withArrow>
                        <ActionIcon variant="subtle" color="grape" onClick={() => onDownloadBundle(item)}>
                          <Download size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    {onLastMile && item.booking?.lastMileDeliveryAddress && (
                      <Tooltip label="Last mile delivery" withArrow>
                        <ActionIcon variant="subtle" color="blue" onClick={() => onLastMile(item)}>
                          <MapPin size={16} />
                        </ActionIcon>
                      </Tooltip>
                    )}
                    <Tooltip label="History" withArrow>
                      <ActionIcon variant="subtle" color="gray" onClick={() => onHistory(item)}>
                        <History size={16} />
                      </ActionIcon>
                    </Tooltip>
                  </Group>
                </Table.Td>
              </Table.Tr>
              {isExpanded && item.bookingId ? (
                <TruckBreakdownRow
                  bookingId={item.bookingId}
                  // Expander + every data column + actions, plus the checkbox
                  // when the table is selectable.
                  colSpan={selectable ? 14 : 13}
                />
              ) : null}
              </Fragment>
            );
          })}
        </Table.Tbody>
      </Table>
    </Table.ScrollContainer>
  );
}
