import { useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Badge,
  Button,
  Checkbox,
  Group,
  Loader,
  Modal,
  NumberInput,
  Select,
  Stack,
  Table,
  Tabs,
  Text,
  Textarea,
  TextInput,
} from '@mantine/core';
import { Info, PackageSearch, Truck } from 'lucide-react';

import { useToast } from '@/hooks/use-toast';
import {
  useBulkReceive,
  useEligibleBookings,
  useLoadPassedExport,
  useReceiveInventory,
  useWarehouseYards,
  useWarehouseZones,
  useWarehouses,
} from '@/hooks/useWarehouses';
import type { BulkReceiveResult, LoadPassedExportResult, ReceiveInventoryPayload } from '@/types/warehouse';
import { BookingSelect } from './BookingSelect';
import { extractErrorMessage, formatNumber } from './options';

interface ReceiveInventoryModalProps {
  opened: boolean;
  onClose: () => void;
  /** When supplied the modal locks to a single booking (legacy single-receive). */
  bookingId?: string;
  bookingLabel?: string;
  onReceived?: () => void;
}

interface Location {
  warehouseId: string;
  yardId: string;
  zoneId: string;
}

/** Cascading Warehouse → Yard → Zone selectors (ACTIVE only). */
function LocationSelects({
  value,
  onChange,
}: {
  value: Location;
  onChange: (next: Location) => void;
}) {
  const warehousesQuery = useWarehouses({ status: 'ACTIVE' });
  const yardsQuery = useWarehouseYards(value.warehouseId || undefined);
  const zonesQuery = useWarehouseZones(value.yardId || undefined);

  const warehouseOptions = useMemo(
    () => (warehousesQuery.data ?? []).map((w) => ({ value: w.id, label: `${w.name} (${w.code})` })),
    [warehousesQuery.data],
  );
  const yardOptions = useMemo(
    () =>
      (yardsQuery.data ?? [])
        .filter((y) => y.status === 'ACTIVE')
        .map((y) => ({ value: y.id, label: `${y.name} (${y.code})` })),
    [yardsQuery.data],
  );
  const zoneOptions = useMemo(
    () =>
      (zonesQuery.data ?? [])
        .filter((z) => z.status === 'ACTIVE')
        .map((z) => ({ value: z.id, label: `${z.name} (${z.code})` })),
    [zonesQuery.data],
  );

  return (
    <Group grow align="flex-end">
      <Select
        label="Warehouse"
        placeholder={warehousesQuery.isLoading ? 'Loading…' : 'Select warehouse'}
        required
        searchable
        data={warehouseOptions}
        value={value.warehouseId || null}
        onChange={(v) => onChange({ warehouseId: v ?? '', yardId: '', zoneId: '' })}
      />
      <Select
        label="Yard"
        placeholder={!value.warehouseId ? 'Select warehouse first' : 'Select yard'}
        required
        searchable
        disabled={!value.warehouseId}
        data={yardOptions}
        value={value.yardId || null}
        onChange={(v) => onChange({ ...value, yardId: v ?? '', zoneId: '' })}
      />
      <Select
        label="Zone"
        placeholder={!value.yardId ? 'Select yard first' : 'Select zone'}
        required
        searchable
        disabled={!value.yardId}
        data={zoneOptions}
        value={value.zoneId || null}
        onChange={(v) => onChange({ ...value, zoneId: v ?? '' })}
      />
    </Group>
  );
}

/** One tab: eligible PAID bookings for a direction, with bulk receive (+ export load). */
function EligibleTab({
  direction,
  location,
  enabled,
  onChanged,
}: {
  direction: 'IMPORT' | 'EXPORT';
  location: Location;
  enabled: boolean;
  onChanged?: () => void;
}) {
  const { toast } = useToast();
  const { data: rows = [], isLoading } = useEligibleBookings(direction, enabled);
  const bulkReceive = useBulkReceive();
  const loadPassed = useLoadPassedExport();
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const locationReady = Boolean(location.warehouseId && location.yardId && location.zoneId);
  const allSelected = rows.length > 0 && selected.size === rows.length;
  const someSelected = selected.size > 0 && !allSelected;

  const toggleAll = () =>
    setSelected(allSelected ? new Set() : new Set(rows.map((r) => r.id)));
  const toggleOne = (id: string) =>
    setSelected((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });

  const receive = async (bookingIds: string[]) => {
    if (!locationReady) {
      toast({ variant: 'destructive', title: 'Select warehouse, yard and zone first' });
      return;
    }
    if (bookingIds.length === 0) {
      toast({ variant: 'destructive', title: 'Select at least one booking' });
      return;
    }
    try {
      const res = (await bulkReceive.mutateAsync({ direction, ...location, bookingIds })) as {
        data: BulkReceiveResult;
      };
      const r = res.data;
      toast({
        title: `${r.receivedCount} received`,
        description: r.skippedCount ? `${r.skippedCount} skipped` : undefined,
      });
      setSelected(new Set());
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Receive failed', description: extractErrorMessage(error) });
    }
  };

  const loadPassedExport = async () => {
    try {
      const res = (await loadPassed.mutateAsync(undefined)) as { data: LoadPassedExportResult };
      const r = res.data;
      toast({
        title: `${r.loadedCount} loaded`,
        description: r.skippedCount ? `${r.skippedCount} skipped — inspection not passed` : undefined,
      });
      onChanged?.();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Load failed', description: extractErrorMessage(error) });
    }
  };

  return (
    <Stack gap="sm" mt="sm">
      <Group justify="space-between">
        <Text size="sm" c="dimmed">
          Selected: <b>{selected.size}</b> / {rows.length} eligible
        </Text>
        <Group gap="xs">
          {direction === 'EXPORT' && (
            <Button
              size="compact-sm"
              variant="light"
              color="teal"
              leftSection={<Truck size={14} />}
              loading={loadPassed.isPending}
              onClick={loadPassedExport}
            >
              Load Passed Export Items
            </Button>
          )}
          <Button
            size="compact-sm"
            variant="default"
            disabled={!locationReady || rows.length === 0}
            loading={bulkReceive.isPending}
            onClick={() => receive(rows.map((r) => r.id))}
          >
            Receive All Eligible
          </Button>
          <Button
            size="compact-sm"
            disabled={!locationReady || selected.size === 0}
            loading={bulkReceive.isPending}
            onClick={() => receive([...selected])}
          >
            Receive Selected
          </Button>
        </Group>
      </Group>

      {!locationReady && (
        <Alert icon={<Info size={16} />} color="orange" variant="light">
          <Text size="sm">Select a warehouse, yard and zone above before receiving.</Text>
        </Alert>
      )}

      {isLoading ? (
        <Group justify="center" py="lg">
          <Loader size="sm" />
        </Group>
      ) : rows.length === 0 ? (
        <Text c="dimmed" ta="center" py="lg" size="sm">
          No eligible PAID {direction.toLowerCase()} bookings to receive.
        </Text>
      ) : (
        <Table.ScrollContainer minWidth={1700}>
          <Table highlightOnHover verticalSpacing="xs" striped>
            <Table.Thead>
              <Table.Tr>
                <Table.Th w={40}>
                  <Checkbox
                    aria-label="Select all"
                    checked={allSelected}
                    indeterminate={someSelected}
                    onChange={toggleAll}
                  />
                </Table.Th>
                <Table.Th>Booking Ref</Table.Th>
                <Table.Th>Booking ID</Table.Th>
                <Table.Th>Customer ID</Table.Th>
                <Table.Th>Customer Name</Table.Th>
                <Table.Th>Origin</Table.Th>
                <Table.Th>Destination</Table.Th>
                <Table.Th>Route</Table.Th>
                <Table.Th>Container #</Table.Th>
                <Table.Th>Cargo Type</Table.Th>
                <Table.Th>Weight</Table.Th>
                <Table.Th>Payment</Table.Th>
                <Table.Th>Current Status</Table.Th>
                <Table.Th>Inspection</Table.Th>
                <Table.Th ta="right">Actions</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {rows.map((r) => (
                <Table.Tr key={r.id}>
                  <Table.Td>
                    <Checkbox
                      aria-label={`Select ${r.reference}`}
                      checked={selected.has(r.id)}
                      onChange={() => toggleOne(r.id)}
                    />
                  </Table.Td>
                  <Table.Td>
                    <Text size="sm" fw={600}>
                      {r.reference}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="xs" c="dimmed">{r.id.slice(0, 8)}…</Text>
                  </Table.Td>
                  <Table.Td>
                    <Text size="xs" c="dimmed">{r.customerId ? `${r.customerId.slice(0, 8)}…` : '—'}</Text>
                  </Table.Td>
                  <Table.Td>{r.customer ?? '—'}</Table.Td>
                  <Table.Td>{r.origin ?? '—'}</Table.Td>
                  <Table.Td>{r.destination ?? '—'}</Table.Td>
                  <Table.Td>
                    {r.origin || r.destination ? `${r.origin ?? '?'} → ${r.destination ?? '?'}` : '—'}
                  </Table.Td>
                  <Table.Td>—</Table.Td>
                  <Table.Td>{r.cargo ?? '—'}</Table.Td>
                  <Table.Td>{formatNumber(Number(r.weight))}</Table.Td>
                  <Table.Td>
                    <Badge color="green" variant="light" size="sm">
                      {r.paymentStatus}
                    </Badge>
                  </Table.Td>
                  <Table.Td>
                    <Badge color="gray" variant="light" size="sm">
                      {r.status ?? '—'}
                    </Badge>
                  </Table.Td>
                  <Table.Td>—</Table.Td>
                  <Table.Td ta="right">
                    <Button
                      size="compact-xs"
                      variant="light"
                      disabled={!locationReady}
                      loading={bulkReceive.isPending}
                      onClick={() => receive([r.id])}
                    >
                      Receive
                    </Button>
                  </Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>
      )}
    </Stack>
  );
}

/** New bulk Receive: Import / Export tabs with eligible PAID bookings. */
function BulkReceiveModal({ opened, onClose, onReceived }: ReceiveInventoryModalProps) {
  const [location, setLocation] = useState<Location>({ warehouseId: '', yardId: '', zoneId: '' });
  const [tab, setTab] = useState<'IMPORT' | 'EXPORT'>('IMPORT');

  useEffect(() => {
    if (opened) setLocation({ warehouseId: '', yardId: '', zoneId: '' });
  }, [opened]);

  return (
    <Modal opened={opened} onClose={onClose} title="Receive at warehouse" centered size="80rem">
      <Stack gap="md">
        <LocationSelects value={location} onChange={setLocation} />

        <Tabs value={tab} onChange={(v) => setTab((v as 'IMPORT' | 'EXPORT') ?? 'IMPORT')}>
          <Tabs.List>
            <Tabs.Tab value="IMPORT" leftSection={<PackageSearch size={16} />}>
              Import
            </Tabs.Tab>
            <Tabs.Tab value="EXPORT" leftSection={<Truck size={16} />}>
              Export
            </Tabs.Tab>
          </Tabs.List>

          <Tabs.Panel value="IMPORT">
            <EligibleTab direction="IMPORT" location={location} enabled={opened} onChanged={onReceived} />
          </Tabs.Panel>
          <Tabs.Panel value="EXPORT">
            <Tabs defaultValue="receive-queue" mt="xs">
              <Tabs.List>
                <Tabs.Tab value="receive-queue">Receive Queue</Tabs.Tab>
                <Tabs.Tab value="ready-to-load">Ready To Load</Tabs.Tab>
                <Tabs.Tab value="loaded">Loaded</Tabs.Tab>
                <Tabs.Tab value="dispatch-queue">Dispatch Queue</Tabs.Tab>
              </Tabs.List>

              <Tabs.Panel value="receive-queue">
                <EligibleTab direction="EXPORT" location={location} enabled={opened} onChanged={onReceived} />
              </Tabs.Panel>
              <Tabs.Panel value="ready-to-load">
                <Text c="dimmed" ta="center" py="lg" size="sm">
                  Ready To Load — coming in the next batch.
                </Text>
              </Tabs.Panel>
              <Tabs.Panel value="loaded">
                <Text c="dimmed" ta="center" py="lg" size="sm">
                  Loaded — coming in the next batch.
                </Text>
              </Tabs.Panel>
              <Tabs.Panel value="dispatch-queue">
                <Text c="dimmed" ta="center" py="lg" size="sm">
                  Dispatch Queue — coming in the next batch.
                </Text>
              </Tabs.Panel>
            </Tabs>
          </Tabs.Panel>
        </Tabs>

        <Group justify="flex-end" mt="sm">
          <Button variant="default" onClick={onClose}>
            Close
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

interface SingleFormState {
  warehouseId: string;
  yardId: string;
  zoneId: string;
  quantity: number | '';
  weight: number | '';
  volume: number | '';
  notes: string;
}

/** Legacy single-booking receive — used when a specific bookingId is supplied. */
function SingleBookingReceiveModal({
  opened,
  onClose,
  bookingId,
  bookingLabel,
  onReceived,
}: ReceiveInventoryModalProps) {
  const { toast } = useToast();
  const receiveMutation = useReceiveInventory();
  const [selectedBooking, setSelectedBooking] = useState(bookingId ?? '');
  const [form, setForm] = useState<SingleFormState>({
    warehouseId: '',
    yardId: '',
    zoneId: '',
    quantity: '',
    weight: '',
    volume: '',
    notes: '',
  });

  useEffect(() => {
    if (opened) {
      setSelectedBooking(bookingId ?? '');
      setForm({ warehouseId: '', yardId: '', zoneId: '', quantity: '', weight: '', volume: '', notes: '' });
    }
  }, [opened, bookingId]);

  const location: Location = { warehouseId: form.warehouseId, yardId: form.yardId, zoneId: form.zoneId };

  const handleSubmit = async () => {
    if (!selectedBooking.trim()) {
      toast({ variant: 'destructive', title: 'Booking is required' });
      return;
    }
    if (!form.warehouseId || !form.yardId || !form.zoneId) {
      toast({ variant: 'destructive', title: 'Select warehouse, yard and zone' });
      return;
    }
    if (form.quantity === '' || form.weight === '') {
      toast({ variant: 'destructive', title: 'Quantity and weight are required' });
      return;
    }
    const payload: ReceiveInventoryPayload = {
      bookingId: selectedBooking.trim(),
      warehouseId: form.warehouseId,
      yardId: form.yardId,
      zoneId: form.zoneId,
      quantity: Number(form.quantity),
      weight: Number(form.weight),
      volume: form.volume === '' ? undefined : Number(form.volume),
      notes: form.notes.trim() || undefined,
    };
    try {
      await receiveMutation.mutateAsync(payload);
      toast({ title: 'Inventory received' });
      onReceived?.();
      onClose();
    } catch (error) {
      toast({ variant: 'destructive', title: 'Receive failed', description: extractErrorMessage(error) });
    }
  };

  return (
    <Modal opened={opened} onClose={onClose} title="Receive at warehouse" centered size="lg">
      <Stack gap="md">
        {bookingId ? (
          <TextInput label="Booking" value={bookingLabel ?? bookingId} readOnly />
        ) : (
          <BookingSelect label="Booking" value={selectedBooking} onChange={setSelectedBooking} />
        )}

        <LocationSelects value={location} onChange={(next) => setForm((f) => ({ ...f, ...next }))} />

        <Group grow>
          <NumberInput
            label="Quantity"
            required
            min={0}
            value={form.quantity}
            onChange={(value) => setForm((f) => ({ ...f, quantity: value === '' ? '' : Number(value) }))}
          />
          <NumberInput
            label="Weight (kg)"
            required
            min={0}
            value={form.weight}
            onChange={(value) => setForm((f) => ({ ...f, weight: value === '' ? '' : Number(value) }))}
          />
          <NumberInput
            label="Volume (m³)"
            placeholder="Optional"
            min={0}
            value={form.volume}
            onChange={(value) => setForm((f) => ({ ...f, volume: value === '' ? '' : Number(value) }))}
          />
        </Group>

        <Textarea
          label="Notes"
          placeholder="Optional notes"
          autosize
          minRows={2}
          value={form.notes}
          onChange={(e) => {
            const v = e.currentTarget.value;
            setForm((f) => ({ ...f, notes: v }));
          }}
        />

        <Group justify="flex-end" mt="sm">
          <Button variant="default" onClick={onClose} disabled={receiveMutation.isPending}>
            Cancel
          </Button>
          <Button onClick={handleSubmit} loading={receiveMutation.isPending}>
            Receive inventory
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

export function ReceiveInventoryModal(props: ReceiveInventoryModalProps) {
  // Locked to a booking → legacy single receive; otherwise the Import/Export bulk flow.
  return props.bookingId ? <SingleBookingReceiveModal {...props} /> : <BulkReceiveModal {...props} />;
}
