import { useMemo } from "react";
import { ArrowRight, Package } from "lucide-react";
import {
  Accordion,
  Badge,
  Button,
  Checkbox,
  Group,
  Loader,
  Paper,
  Stack,
  Text,
} from "@mantine/core";

import { BookingPriorityBadge } from "@/components/bookings/BookingPriorityBadge";
import type { EligibleContainerBooking, FreightType } from "@/types/trainScheduling";
import { groupBookingsByThreeHourWindow } from "@/utils/groupBookingsByThreeHourWindow";

function EligibleBookingRow({
  booking,
  freightType,
  selected,
  onToggle,
}: {
  booking: EligibleContainerBooking;
  freightType?: FreightType;
  selected: boolean;
  onToggle: () => void;
}) {
  const resolvedFreightType = booking.freightType ?? freightType;
  const isBulk = resolvedFreightType === "BULK";

  return (
    <Group
      align="flex-start"
      wrap="nowrap"
      p="sm"
      style={{
        border: `1px solid ${
          selected ? "var(--mantine-color-edr-green-3)" : "var(--mantine-color-gray-2)"
        }`,
        borderRadius: 12,
        background: selected ? "var(--mantine-color-edr-green-0)" : "white",
        transition: "border-color 120ms ease, background 120ms ease",
      }}
    >
      <Checkbox checked={selected} onChange={onToggle} mt={4} color="edr-green" />
      <Stack gap={4} style={{ flex: 1 }}>
        <Group gap="xs" wrap="wrap">
          <Package size={14} />
          <Text fw={600} size="sm">
            {booking.reference}
          </Text>
          {resolvedFreightType ? (
            <Badge variant="outline" size="xs">
              {resolvedFreightType}
            </Badge>
          ) : null}
          {booking.schedulingStatus ? (
            <Badge variant="light" size="xs">
              {booking.schedulingStatus}
            </Badge>
          ) : null}
        </Group>
        <Text size="xs" c="dimmed">
          {booking.customer}
        </Text>
        <Group gap={6}>
          <Text size="xs">{booking.origin}</Text>
          <ArrowRight size={12} />
          <Text size="xs">{booking.destination}</Text>
        </Group>
        <Group gap="sm">
          <BookingPriorityBadge score={booking.priorityScore ?? 0} />
          <Text size="xs" c="dimmed">
            {isBulk
              ? `${booking.weightTons}T`
              : `${booking.quantity} × ${booking.containerType}`}
          </Text>
          {booking.preferredDepartureDate ? (
            <Text size="xs" c="dimmed">
              {new Date(booking.preferredDepartureDate).toLocaleString("en-GB", {
                timeZone: "UTC",
                day: "2-digit",
                month: "short",
                hour: "2-digit",
                minute: "2-digit",
              })}{" "}
              UTC
            </Text>
          ) : null}
        </Group>
      </Stack>
    </Group>
  );
}

export function EligibleBookingsPanel({
  items,
  isLoading,
  selectedIds,
  onSelectionChange,
  assignedIds = [],
  freightType,
}: {
  items: EligibleContainerBooking[];
  isLoading?: boolean;
  selectedIds: string[];
  onSelectionChange: (ids: string[]) => void;
  assignedIds?: string[];
  freightType?: FreightType;
}) {
  const assignedSet = useMemo(() => new Set(assignedIds), [assignedIds]);

  const availableItems = useMemo(
    () => items.filter((b) => !assignedSet.has(b.id)),
    [items, assignedSet],
  );

  const buckets = useMemo(
    () => groupBookingsByThreeHourWindow(availableItems),
    [availableItems],
  );

  const selectableIds = useMemo(() => {
    return [...assignedIds, ...availableItems.map((b) => b.id)];
  }, [availableItems, assignedIds]);

  const toggle = (id: string) => {
    if (selectedIds.includes(id)) {
      onSelectionChange(selectedIds.filter((x) => x !== id));
    } else {
      onSelectionChange([...selectedIds, id]);
    }
  };

  const toggleBucket = (bucketIds: string[], select: boolean) => {
    if (select) {
      const merged = new Set([...selectedIds, ...bucketIds]);
      onSelectionChange([...merged]);
    } else {
      onSelectionChange(selectedIds.filter((id) => !bucketIds.includes(id)));
    }
  };

  if (isLoading) {
    return (
      <Group justify="center" py="md">
        <Loader size="sm" />
        <Text size="sm" c="dimmed">
          Loading eligible bookings…
        </Text>
      </Group>
    );
  }

  if (!items.length && !assignedIds.length) {
    return (
      <Paper p="lg" radius="lg" withBorder bg="gray.0">
        <Text size="sm" c="dimmed" ta="center">
          No eligible bookings for this corridor
        </Text>
      </Paper>
    );
  }

  return (
    <Stack gap="md">
      <Group justify="space-between" wrap="wrap">
        <Text size="sm" fw={500}>
          Eligible bookings ({availableItems.length})
        </Text>
        <Group gap="sm">
          <Button
            variant="light"
            size="compact-sm"
            onClick={() => onSelectionChange(selectableIds)}
          >
            Select all
          </Button>
          <Button variant="subtle" size="compact-sm" onClick={() => onSelectionChange(assignedIds)}>
            Clear
          </Button>
        </Group>
      </Group>

      {buckets.length > 0 ? (
        <Accordion defaultValue={buckets[0]?.key} variant="separated" radius="lg">
          {buckets.map((bucket) => {
            const bucketIds = bucket.bookings.map((b) => b.id);
            const selectedInBucket = bucketIds.filter((id) => selectedIds.includes(id));
            const allSelected = bucketIds.length > 0 && selectedInBucket.length === bucketIds.length;

            return (
              <Accordion.Item key={bucket.key} value={bucket.key}>
                <Accordion.Control>
                  <Group justify="space-between" wrap="nowrap" pr="md">
                    <Stack gap={2}>
                      <Text fw={600} size="sm">
                        {bucket.label}
                      </Text>
                      <Text size="xs" c="dimmed">
                        {bucket.bookings.length} booking
                        {bucket.bookings.length === 1 ? "" : "s"} · priority sorted
                      </Text>
                    </Stack>
                    <Group gap="xs" onClick={(e) => e.stopPropagation()}>
                      <Badge variant="light" color="edr-green">
                        {selectedInBucket.length} selected
                      </Badge>
                      <Button
                        variant="subtle"
                        size="compact-xs"
                        onClick={(e) => {
                          e.stopPropagation();
                          toggleBucket(bucketIds, !allSelected);
                        }}
                      >
                        {allSelected ? "Deselect bucket" : "Select bucket"}
                      </Button>
                    </Group>
                  </Group>
                </Accordion.Control>
                <Accordion.Panel>
                  <Stack gap="sm">
                    {bucket.bookings.map((booking) => (
                      <EligibleBookingRow
                        key={booking.id}
                        booking={booking}
                        freightType={freightType}
                        selected={selectedIds.includes(booking.id)}
                        onToggle={() => toggle(booking.id)}
                      />
                    ))}
                  </Stack>
                </Accordion.Panel>
              </Accordion.Item>
            );
          })}
        </Accordion>
      ) : (
        <Text size="sm" c="dimmed">
          No additional eligible bookings in this corridor.
        </Text>
      )}
    </Stack>
  );
}
