import {
  Alert,
  Badge,
  Button,
  Divider,
  Group,
  Loader,
  Modal,
  Stack,
  Table,
  Text,
  ThemeIcon,
  Tooltip,
} from "@mantine/core";
import { DateTimePicker } from "@mantine/dates";
import { useMutation, useQuery } from "@tanstack/react-query";
import {
  CheckCircle2,
  Flag,
  MapPin,
  PackageCheck,
  TrainFront,
} from "lucide-react";
import { useEffect, useState } from "react";
import { Freight } from "@edr/types";

import { BookingStatusBadge } from "@/components/bookings/BookingStatusBadge";
import { useToast } from "@/hooks/use-toast";
import { api } from "@/services/api";
import type { TrackStation, YardWorkBookingRow } from "@/types/trainScheduling";

const parseError = (error: unknown, fallback: string) => {
  const message = (error as { response?: { data?: { message?: string | string[] } } })
    ?.response?.data?.message;
  if (Array.isArray(message)) return message.join("; ");
  return message || (error as Error)?.message || fallback;
};

const fmtDate = (iso: string) => {
  const d = new Date(iso);
  return Number.isNaN(d.getTime()) ? iso : d.toLocaleString();
};

const DIRECTION_COLORS: Record<string, string> = {
  IMPORT: "blue",
  EXPORT: "teal",
  DOMESTIC: "violet",
};

/** DOMESTIC displays as "Intercity" — shared with the rest of the platform. */
const DIRECTION_LABELS: Record<string, string> = Freight.TRADE_DIRECTION_LABELS;

function DirectionChip({ direction }: { direction: string }) {
  return (
    <Badge size="sm" variant="light" color={DIRECTION_COLORS[direction] ?? "gray"}>
      {DIRECTION_LABELS[direction] ?? direction}
    </Badge>
  );
}

function SectionLabel({
  icon,
  title,
  count,
}: {
  icon: React.ReactNode;
  title: string;
  count: number;
}) {
  return (
    <Group gap={8} align="center">
      <ThemeIcon size={26} radius="md" variant="light" color="edr-green">
        {icon}
      </ThemeIcon>
      <Text fw={700} size="sm">
        {title}
      </Text>
      <Badge size="sm" variant="light" color="gray" radius="sm">
        {count}
      </Badge>
    </Group>
  );
}

/**
 * Yard-work modal for the track page's "Log pass" step.
 *
 * A train runs A→B→C→D and bookings board/alight at any stop, so logging the
 * pass at a yard is the moment its yard work happens: bookings destined here
 * flip to ARRIVED (import/export) or COMPLETED (intercity) automatically the
 * instant the pass is logged, and bookings boarding here become loadable —
 * the server only accepts a load while the train's latest checkpoint is this
 * yard. The modal therefore drives the sequence: log the pass first, then
 * load anything that boards here (including cargo the operator forgot — it
 * stays loadable until the next pass is logged).
 */
export function LogPassYardWorkModal({
  opened,
  onClose,
  scheduleId,
  station,
  isFinal,
  alreadyLogged,
}: {
  opened: boolean;
  onClose: () => void;
  scheduleId: string;
  station: TrackStation | null;
  isFinal: boolean;
  /** True when opened for the current station (pass already logged). */
  alreadyLogged: boolean;
}) {
  const { toast } = useToast();
  const [justLogged, setJustLogged] = useState(false);
  // When the train was here — defaults to now, past allowed (recorded after the fact).
  const [passAt, setPassAt] = useState<Date | null>(null);
  useEffect(() => {
    setJustLogged(false);
    setPassAt(new Date());
  }, [station?.sequenceNo, opened]);
  const logged = alreadyLogged || justLogged;

  const yardWorkQuery = useQuery(
    api.trainScheduling.yardWork.queryOptions({
      input: { scheduleId },
      enabled: opened && Boolean(scheduleId),
    }),
  );
  const recordCheckpoint = useMutation(
    api.trainScheduling.recordCheckpoint.mutationOptions(),
  );
  const load = useMutation(api.trainScheduling.loadScheduleBooking.mutationOptions());

  const yard = yardWorkQuery.data?.yards.find((y) => y.yardId === station?.yardId);
  const boarders: YardWorkBookingRow[] = yard?.toLoad ?? [];
  const arrivals: YardWorkBookingRow[] = yard?.toUnload ?? [];
  const pendingBoarders = boarders.filter((r) => !r.loadedAt);

  const doLogPass = () => {
    if (!station) return;
    recordCheckpoint.mutate(
      {
        id: scheduleId,
        payload: {
          sequenceNo: station.sequenceNo,
          ...(passAt ? { occurredAt: passAt.toISOString() } : {}),
        },
      },
      {
        onSuccess: () => {
          setJustLogged(true);
          toast({
            title: isFinal
              ? "Train arrived — remaining bookings marked arrived, assets freed"
              : `Pass logged at ${station.label}`,
            description: isFinal
              ? undefined
              : arrivals.some((r) => r.canUnload)
                ? "Bookings arriving here have been marked arrived."
                : undefined,
          });
          void yardWorkQuery.refetch();
        },
        onError: (err) =>
          toast({
            title: "Could not log checkpoint",
            description: parseError(err, "Please try again"),
            variant: "destructive",
          }),
      },
    );
  };

  const doLoad = (row: YardWorkBookingRow) => {
    load.mutate(
      { scheduleId, bookingId: row.id },
      {
        onSuccess: () => {
          toast({
            title: `${row.reference ?? "Booking"} loaded`,
            description: `Cargo boarded the train at ${station?.label ?? "this yard"}.`,
          });
          void yardWorkQuery.refetch();
        },
        onError: (err) =>
          toast({
            title: "Could not load booking",
            description: parseError(err, "Please try again"),
            variant: "destructive",
          }),
      },
    );
  };

  const hasWork = boarders.length > 0 || arrivals.length > 0;

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      size="xl"
      radius="lg"
      title={
        <Group gap={8}>
          {isFinal ? <Flag size={18} /> : <MapPin size={18} />}
          <Text fw={700}>
            {isFinal ? "Arrival" : "Yard work"} — {station?.label ?? ""}
          </Text>
          {logged ? (
            <Badge size="sm" variant="light" color="edr-green" radius="sm">
              {isFinal ? "Arrived" : "Pass logged"}
            </Badge>
          ) : null}
        </Group>
      }
    >
      <Stack gap="md">
        {yardWorkQuery.isLoading ? (
          <Group justify="center" py="lg">
            <Loader size="sm" color="edr-green" />
          </Group>
        ) : !hasWork ? (
          <Alert color="gray" variant="light" radius="md" icon={<MapPin size={16} />}>
            No bookings board or alight at this station.
          </Alert>
        ) : (
          <>
            {/* ── Arriving here ─────────────────────────────────────────── */}
            {arrivals.length > 0 ? (
              <Stack gap="xs">
                <SectionLabel
                  icon={<Flag size={14} />}
                  title="Arriving at this yard"
                  count={arrivals.length}
                />
                {!logged ? (
                  <Text size="xs" c="dimmed">
                    Logging the pass marks the loaded bookings below as Arrived
                    (import/export) or Completed (intercity) automatically.
                  </Text>
                ) : null}
                <Table.ScrollContainer minWidth={620}>
                  <Table verticalSpacing="xs" highlightOnHover>
                    <Table.Thead>
                      <Table.Tr>
                        <Table.Th>Booking</Table.Th>
                        <Table.Th>Customer</Table.Th>
                        <Table.Th>Direction</Table.Th>
                        <Table.Th>Status</Table.Th>
                        <Table.Th>Arrived</Table.Th>
                      </Table.Tr>
                    </Table.Thead>
                    <Table.Tbody>
                      {arrivals.map((row) => (
                        <Table.Tr key={row.id}>
                          <Table.Td>
                            <Text size="sm" fw={600}>
                              {row.reference ?? row.id.slice(0, 8)}
                            </Text>
                          </Table.Td>
                          <Table.Td>
                            <Text size="sm">{row.customer}</Text>
                          </Table.Td>
                          <Table.Td>
                            <DirectionChip direction={row.tradeDirection} />
                          </Table.Td>
                          <Table.Td>
                            <BookingStatusBadge status={row.status} />
                          </Table.Td>
                          <Table.Td>
                            <Text size="xs" c="dimmed">
                              {row.arrivedAt ? fmtDate(row.arrivedAt) : "—"}
                            </Text>
                          </Table.Td>
                        </Table.Tr>
                      ))}
                    </Table.Tbody>
                  </Table>
                </Table.ScrollContainer>
              </Stack>
            ) : null}

            {arrivals.length > 0 && boarders.length > 0 ? <Divider /> : null}

            {/* ── Boarding here ─────────────────────────────────────────── */}
            {boarders.length > 0 ? (
              <Stack gap="xs">
                <SectionLabel
                  icon={<TrainFront size={14} />}
                  title="Boarding at this yard"
                  count={boarders.length}
                />
                {!logged && pendingBoarders.length > 0 ? (
                  <Text size="xs" c="dimmed">
                    Log the pass first — the train must be at {station?.label} before
                    cargo can be loaded.
                  </Text>
                ) : null}
                <Table.ScrollContainer minWidth={620}>
                  <Table verticalSpacing="xs" highlightOnHover>
                    <Table.Thead>
                      <Table.Tr>
                        <Table.Th>Booking</Table.Th>
                        <Table.Th>Customer</Table.Th>
                        <Table.Th>Direction</Table.Th>
                        <Table.Th>Status</Table.Th>
                        <Table.Th>Loaded</Table.Th>
                        <Table.Th />
                      </Table.Tr>
                    </Table.Thead>
                    <Table.Tbody>
                      {boarders.map((row) => (
                        <Table.Tr key={row.id}>
                          <Table.Td>
                            <Group gap={6} wrap="nowrap">
                              <Text size="sm" fw={600}>
                                {row.reference ?? row.id.slice(0, 8)}
                              </Text>
                              {row.isGovernment ? (
                                <Badge size="xs" variant="light" color="grape">
                                  GOV
                                </Badge>
                              ) : null}
                            </Group>
                          </Table.Td>
                          <Table.Td>
                            <Text size="sm">{row.customer}</Text>
                          </Table.Td>
                          <Table.Td>
                            <DirectionChip direction={row.tradeDirection} />
                          </Table.Td>
                          <Table.Td>
                            <BookingStatusBadge status={row.status} />
                          </Table.Td>
                          <Table.Td>
                            {row.loadedAt ? (
                              <Group gap={4} wrap="nowrap">
                                <CheckCircle2
                                  size={13}
                                  color="var(--mantine-color-edr-green-7)"
                                />
                                <Text size="xs" c="dimmed">
                                  {fmtDate(row.loadedAt)}
                                </Text>
                              </Group>
                            ) : (
                              <Text size="xs" c="dimmed">
                                Not loaded
                              </Text>
                            )}
                          </Table.Td>
                          <Table.Td>
                            {!row.loadedAt ? (
                              <Tooltip
                                label={
                                  !logged
                                    ? "Log the pass first — the train must be at this yard"
                                    : !row.canLoad
                                      ? "Booking is not ready to load (payment pending)"
                                      : "Confirm cargo loaded onto the train"
                                }
                              >
                                <Button
                                  size="compact-xs"
                                  variant="light"
                                  leftSection={<PackageCheck size={13} />}
                                  disabled={!logged || !row.canLoad}
                                  loading={
                                    load.isPending && load.variables?.bookingId === row.id
                                  }
                                  onClick={() => doLoad(row)}
                                >
                                  Load
                                </Button>
                              </Tooltip>
                            ) : null}
                          </Table.Td>
                        </Table.Tr>
                      ))}
                    </Table.Tbody>
                  </Table>
                </Table.ScrollContainer>
              </Stack>
            ) : null}
          </>
        )}

        {!logged ? (
          <DateTimePicker
            label={isFinal ? "Arrival time" : "Time at station"}
            description="Defaults to now — pick an earlier time if you are recording after the fact."
            value={passAt}
            onChange={(v) => setPassAt(v ? new Date(v) : null)}
            maxDate={new Date()}
            valueFormat="DD MMM YYYY HH:mm"
            clearable={false}
            radius="md"
            maw={320}
          />
        ) : null}

        <Group justify="space-between" mt="xs">
          <Text size="xs" c="dimmed">
            {logged && pendingBoarders.length > 0
              ? `${pendingBoarders.length} booking${pendingBoarders.length === 1 ? "" : "s"} still to load before the next station.`
              : ""}
          </Text>
          <Group gap="sm">
            <Button variant="default" onClick={onClose}>
              Close
            </Button>
            {!logged ? (
              <Button
                color={isFinal ? "teal" : "edr-green"}
                leftSection={isFinal ? <Flag size={15} /> : <MapPin size={15} />}
                loading={recordCheckpoint.isPending}
                onClick={doLogPass}
              >
                {isFinal
                  ? `Mark arrived at ${station?.label ?? "destination"}`
                  : `Log pass at ${station?.label ?? "station"}`}
              </Button>
            ) : null}
          </Group>
        </Group>
      </Stack>
    </Modal>
  );
}
