import { Box, Center, Group, Loader, Modal, Stack, Text } from "@mantine/core";
import { useQuery } from "@tanstack/react-query";
import {
  AlertTriangle,
  CheckCircle2,
  Clock,
  Flag,
  MapPin,
  PackageX,
  RefreshCw,
  Train,
} from "lucide-react";

import { api } from "@/services/api";
import { Freight } from "@edr/types";

import {
  checkpointKindLabel,
  corridorProgress,
  isArrived,
  isDispatched,
  shipmentStatusLabel,
} from "./trackingStages";

const GREEN = "#0EA371";
const GREEN_DARK = "#0A6F4D";
const ACCENT = "#F2A516";
const INK = "#10202F";
const MUTED = "#6B7C8E";

interface ShipmentTrackingModalProps {
  opened: boolean;
  onClose: () => void;
  bookingId: string;
  bookingReference: string;
  originLabel?: string;
  destinationLabel?: string;
}

export function ShipmentTrackingModal({
  opened,
  onClose,
  bookingId,
  bookingReference,
  originLabel,
  destinationLabel,
}: ShipmentTrackingModalProps) {
  const { data, isLoading, isError, refetch, isFetching } = useQuery({
    ...api.bookings.tracking.queryOptions({ input: { id: bookingId } }),
    enabled: opened && Boolean(bookingId),
    refetchInterval: opened ? 30_000 : false,
  });

  const hasSchedule = data?.hasSchedule ?? false;

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      centered
      size={900}
      radius={20}
      padding={0}
      withCloseButton={false}
      overlayProps={{ backgroundOpacity: 0.5, blur: 4 }}
      styles={{ content: { overflow: "hidden" } }}
    >
      <Header
        bookingReference={data?.bookingReference ?? bookingReference}
        trainNumber={data?.trainNumber ?? null}
        status={data?.scheduleStatus ?? null}
        currentSequenceNo={data?.currentSequenceNo ?? -1}
        onClose={onClose}
        onRefresh={() => refetch()}
        refreshing={isFetching}
      />

      <Box px={28} py={24}>
        {isLoading ? (
          <Center mih={280}>
            <Stack align="center" gap="sm">
              <Loader color="edr-green" />
              <Text fz="sm" c={MUTED}>
                Locating your train…
              </Text>
            </Stack>
          </Center>
        ) : isError ? (
          <ErrorState onRetry={() => refetch()} />
        ) : !hasSchedule ? (
          <NotDispatchedState
            origin={originLabel ?? "Origin"}
            destination={destinationLabel ?? "Destination"}
          />
        ) : data ? (
          <Stack gap={26}>
            <SummaryBar data={data} />
            <Corridor data={data} />
            <CheckpointFeed data={data} />
          </Stack>
        ) : null}
      </Box>
    </Modal>
  );
}

// ── Header ────────────────────────────────────────────────────────────────────

function Header({
  bookingReference,
  trainNumber,
  status,
  currentSequenceNo,
  onClose,
  onRefresh,
  refreshing,
}: {
  bookingReference: string;
  trainNumber: string | null;
  status: Freight.TrainScheduleStatus | null;
  currentSequenceNo: number;
  onClose: () => void;
  onRefresh: () => void;
  refreshing: boolean;
}) {
  return (
    <Box
      px={28}
      py={22}
      style={{
        background:
          "linear-gradient(120deg, #0C1A2B 0%, #123047 60%, #0A6F4D 140%)",
      }}
    >
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Group gap={14} align="center" wrap="nowrap">
          <Box
            style={{
              width: 48,
              height: 48,
              borderRadius: 13,
              flexShrink: 0,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              backgroundColor: "rgba(255,255,255,0.12)",
              color: "#fff",
            }}
          >
            <Train size={24} />
          </Box>
          <Box>
            <Text
              fz="11px"
              fw={700}
              tt="uppercase"
              c="#9FE9CC"
              style={{ letterSpacing: 0.7 }}
            >
              Live shipment tracking
            </Text>
            <Text fz="20px" fw={800} c="#fff" lh={1.2}>
              {bookingReference}
            </Text>
            {trainNumber && (
              <Text fz="12px" c="#A9BBCB">
                Train {trainNumber}
              </Text>
            )}
          </Box>
        </Group>

        <Group gap={10} align="center" wrap="nowrap">
          <HeaderStatusPill status={status} currentSequenceNo={currentSequenceNo} />
          <IconButton title="Refresh" onClick={onRefresh} spinning={refreshing}>
            <RefreshCw size={16} />
          </IconButton>
          <IconButton title="Close" onClick={onClose}>
            <span style={{ fontSize: 18, lineHeight: 1, fontWeight: 600 }}>×</span>
          </IconButton>
        </Group>
      </Group>
    </Box>
  );
}

function IconButton({
  children,
  onClick,
  title,
  spinning,
}: {
  children: React.ReactNode;
  onClick: () => void;
  title: string;
  spinning?: boolean;
}) {
  return (
    <button
      type="button"
      title={title}
      aria-label={title}
      onClick={onClick}
      style={{
        width: 34,
        height: 34,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        borderRadius: 9,
        border: "1px solid rgba(255,255,255,0.18)",
        backgroundColor: "rgba(255,255,255,0.08)",
        color: "#fff",
        cursor: "pointer",
        animation: spinning ? "edr-spin 0.9s linear infinite" : undefined,
      }}
    >
      {children}
    </button>
  );
}

function HeaderStatusPill({
  status,
  currentSequenceNo,
}: {
  status: Freight.TrainScheduleStatus | null;
  currentSequenceNo: number;
}) {
  const arrived = isArrived(status);
  const moving = isDispatched(status);
  const bg = arrived
    ? "rgba(14,163,113,0.22)"
    : moving
      ? "rgba(242,165,22,0.20)"
      : "rgba(255,255,255,0.12)";
  const dot = arrived ? "#5BE3B0" : moving ? ACCENT : "#CBD5E1";
  return (
    <Group
      gap={7}
      align="center"
      wrap="nowrap"
      px={12}
      py={7}
      style={{ borderRadius: 999, backgroundColor: bg }}
    >
      <Box
        style={{
          width: 7,
          height: 7,
          borderRadius: "50%",
          backgroundColor: dot,
          animation: moving ? "edr-pulse 1.4s ease-in-out infinite" : undefined,
        }}
      />
      <Text fz="12px" fw={700} c="#fff">
        {shipmentStatusLabel(status, currentSequenceNo)}
      </Text>
    </Group>
  );
}

// ── Summary bar (ETA / departure / arrival) ────────────────────────────────────

function SummaryBar({ data }: { data: Freight.IBookingTracking }) {
  const arrived = isArrived(data.scheduleStatus);
  const items: Array<{ label: string; value: string; accent?: boolean }> = [
    {
      label: "Departed",
      value: fmtTime(data.actualDepartureAt ?? data.scheduledDepartureAt),
    },
    {
      label: arrived ? "Arrived" : "Est. arrival",
      value: fmtTime(data.actualArrivalAt ?? data.scheduledArrivalAt),
      accent: !arrived,
    },
    {
      label: "Stations",
      value: `${Math.max(0, data.currentSequenceNo + (data.currentSequenceNo >= 0 ? 1 : 0))} / ${data.stations.length}`,
    },
  ];
  return (
    <Group
      gap={0}
      wrap="nowrap"
      style={{
        borderRadius: 14,
        border: "1px solid #E6ECF2",
        overflow: "hidden",
      }}
    >
      {items.map((it, i) => (
        <Box
          key={it.label}
          style={{
            flex: 1,
            padding: "14px 16px",
            borderLeft: i > 0 ? "1px solid #EEF2F6" : undefined,
            background: it.accent ? "#FEFBF3" : "#FBFCFD",
          }}
        >
          <Text
            fz="10.5px"
            fw={700}
            tt="uppercase"
            c={it.accent ? "#B07D14" : MUTED}
            style={{ letterSpacing: 0.5 }}
          >
            {it.label}
          </Text>
          <Text fz="15px" fw={800} c={INK} mt={2}>
            {it.value}
          </Text>
        </Box>
      ))}
    </Group>
  );
}

// ── Corridor: stations + train marker ──────────────────────────────────────────

function Corridor({ data }: { data: Freight.IBookingTracking }) {
  const arrived = isArrived(data.scheduleStatus);
  const moving = isDispatched(data.scheduleStatus);
  const stations = data.stations;
  const current = data.currentSequenceNo;
  const progress = corridorProgress(stations.length, current, arrived);

  // Map sequenceNo → latest checkpoint at that station for captions.
  const checkpointBySeq = new Map<number, Freight.ITrackingCheckpoint>();
  for (const c of data.checkpoints) checkpointBySeq.set(c.sequenceNo, c);

  return (
    <Box>
      <Group gap={8} align="center" mb={16}>
        <MapPin size={15} color={GREEN_DARK} />
        <Text fz="14px" fw={800} c={INK}>
          Where is your train
        </Text>
        <Text fz="12.5px" c={MUTED}>
          · {progress}% of the route
        </Text>
      </Group>

      {/* Horizontal rail */}
      <Box style={{ position: "relative", paddingTop: 44, paddingBottom: 4 }}>
        {/* base rail */}
        <Box
          style={{
            position: "absolute",
            top: 54,
            left: 16,
            right: 16,
            height: 5,
            borderRadius: 999,
            background: "#EAF0F5",
          }}
        />
        {/* filled rail */}
        <Box
          style={{
            position: "absolute",
            top: 54,
            left: 16,
            width: `calc((100% - 32px) * ${progress / 100})`,
            height: 5,
            borderRadius: 999,
            background: `linear-gradient(90deg, ${GREEN_DARK}, ${GREEN})`,
            transition: "width 600ms ease",
          }}
        />

        {/* train marker riding the filled rail */}
        <Box
          style={{
            position: "absolute",
            top: 18,
            left: `calc(16px + (100% - 32px) * ${progress / 100})`,
            transform: "translateX(-50%)",
            transition: "left 600ms ease",
            zIndex: 3,
          }}
        >
          <Box
            style={{
              width: 38,
              height: 38,
              borderRadius: 11,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              background: arrived
                ? `linear-gradient(135deg, ${GREEN}, ${GREEN_DARK})`
                : `linear-gradient(135deg, ${ACCENT}, #D98A06)`,
              color: "#fff",
              boxShadow: "0 6px 16px rgba(16,24,40,0.20)",
              border: "3px solid #fff",
              animation: moving ? "edr-bob 1.8s ease-in-out infinite" : undefined,
            }}
          >
            {arrived ? <CheckCircle2 size={18} /> : <Train size={18} />}
          </Box>
        </Box>

        {/* station nodes */}
        <Box
          style={{
            position: "relative",
            display: "flex",
            justifyContent: "space-between",
            zIndex: 2,
          }}
        >
          {stations.map((s, i) => {
            const reached = arrived || (current >= 0 && i <= current);
            const isCurrent = !arrived && i === current;
            const isLast = i === stations.length - 1;
            const cp = checkpointBySeq.get(s.sequenceNo);
            return (
              <StationNode
                key={`${s.yardId}-${i}`}
                label={s.label}
                reached={reached}
                isCurrent={isCurrent}
                isEndpoint={i === 0 || isLast}
                arrivedHere={isLast && arrived}
                time={cp ? fmtTime(cp.occurredAt) : null}
                align={i === 0 ? "left" : isLast ? "right" : "center"}
              />
            );
          })}
        </Box>
      </Box>
    </Box>
  );
}

function StationNode({
  label,
  reached,
  isCurrent,
  isEndpoint,
  arrivedHere,
  time,
  align,
}: {
  label: string;
  reached: boolean;
  isCurrent: boolean;
  isEndpoint: boolean;
  arrivedHere: boolean;
  time: string | null;
  align: "left" | "center" | "right";
}) {
  const color = arrivedHere ? GREEN : isCurrent ? ACCENT : reached ? GREEN : "#CBD5E1";
  return (
    <Box
      style={{
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        flex: isEndpoint ? "0 0 auto" : 1,
        minWidth: 0,
        maxWidth: 120,
      }}
    >
      <Box
        style={{
          width: isCurrent ? 18 : 14,
          height: isCurrent ? 18 : 14,
          borderRadius: "50%",
          background: "#fff",
          border: `3px solid ${color}`,
          boxShadow: isCurrent ? `0 0 0 4px ${ACCENT}22` : undefined,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
        }}
      >
        <Box
          style={{
            width: isCurrent ? 7 : 5,
            height: isCurrent ? 7 : 5,
            borderRadius: "50%",
            background: color,
          }}
        />
      </Box>
      <Text
        fz="11.5px"
        fw={reached ? 700 : 600}
        c={reached ? INK : "#9AA8B5"}
        mt={8}
        ta={align}
        truncate
        style={{ maxWidth: 110 }}
        title={label}
      >
        {label}
      </Text>
      {time && (
        <Text fz="10px" c={MUTED} mt={1}>
          {time}
        </Text>
      )}
    </Box>
  );
}

// ── Checkpoint feed ────────────────────────────────────────────────────────────

function CheckpointFeed({ data }: { data: Freight.IBookingTracking }) {
  // Newest first.
  const ordered = [...data.checkpoints].sort(
    (a, b) =>
      new Date(b.occurredAt).getTime() - new Date(a.occurredAt).getTime(),
  );

  return (
    <Box
      p={20}
      style={{
        borderRadius: 16,
        border: "1px solid #E6ECF2",
        background: "#FBFCFD",
      }}
    >
      <Group gap={8} align="center" mb={ordered.length ? 16 : 0}>
        <Clock size={15} color={GREEN_DARK} />
        <Text fz="14px" fw={800} c={INK}>
          Journey log
        </Text>
      </Group>

      {ordered.length === 0 ? (
        <Text fz="13px" c={MUTED}>
          No checkpoints logged yet. Updates appear here as the train passes each
          station along the corridor.
        </Text>
      ) : (
        <Box>
          {ordered.map((cp, i) => {
            const isLatest = i === 0;
            const last = i === ordered.length - 1;
            const Icon =
              cp.kind === Freight.TrainCheckpointKind.Arrived
                ? CheckCircle2
                : cp.kind === Freight.TrainCheckpointKind.Departed
                  ? Flag
                  : Train;
            return (
              <Group key={cp.id} gap={14} wrap="nowrap" align="flex-start">
                <Box
                  style={{
                    display: "flex",
                    flexDirection: "column",
                    alignItems: "center",
                    alignSelf: "stretch",
                  }}
                >
                  <Box
                    style={{
                      width: 30,
                      height: 30,
                      borderRadius: 9,
                      display: "flex",
                      alignItems: "center",
                      justifyContent: "center",
                      background: isLatest ? "#ECF6F1" : "#F1F4F7",
                      color: isLatest ? GREEN_DARK : "#64748B",
                      flexShrink: 0,
                    }}
                  >
                    <Icon size={15} />
                  </Box>
                  {!last && (
                    <Box
                      style={{
                        flex: 1,
                        width: 2,
                        marginTop: 4,
                        marginBottom: 4,
                        background: "#E1E7EE",
                      }}
                    />
                  )}
                </Box>

                <Box pb={last ? 0 : 16} style={{ flex: 1, minWidth: 0 }}>
                  <Group gap={8} align="center" wrap="wrap">
                    <Text fz="13.5px" fw={700} c={INK}>
                      {cp.label ?? "Checkpoint"}
                    </Text>
                    <Box
                      component="span"
                      style={{
                        borderRadius: 999,
                        padding: "2px 9px",
                        fontSize: 10.5,
                        fontWeight: 700,
                        background: isLatest ? "#ECF6F1" : "#F1F4F7",
                        color: isLatest ? GREEN_DARK : "#475569",
                      }}
                    >
                      {checkpointKindLabel(cp.kind)}
                    </Box>
                    {isLatest && (
                      <Box
                        component="span"
                        style={{
                          borderRadius: 999,
                          padding: "2px 9px",
                          fontSize: 10.5,
                          fontWeight: 700,
                          background: "#FEF6E6",
                          color: "#B07D14",
                        }}
                      >
                        Latest
                      </Box>
                    )}
                  </Group>
                  {cp.note && (
                    <Text fz="12.5px" c={MUTED} mt={2}>
                      {cp.note}
                    </Text>
                  )}
                  <Text fz="11.5px" c="#9AA8B5" mt={3}>
                    {fmtTime(cp.occurredAt)}
                  </Text>
                </Box>
              </Group>
            );
          })}
        </Box>
      )}
    </Box>
  );
}

// ── Empty / error states ───────────────────────────────────────────────────────

function NotDispatchedState({
  origin,
  destination,
}: {
  origin: string;
  destination: string;
}) {
  return (
    <Stack align="center" gap={6} py={40} ta="center">
      <Box
        style={{
          width: 64,
          height: 64,
          borderRadius: 16,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          background: "#FEF6E6",
          color: ACCENT,
        }}
      >
        <PackageX size={30} />
      </Box>
      <Text fz="18px" fw={800} c={INK} mt={4}>
        Not on the rails yet
      </Text>
      <Text fz="13.5px" c={MUTED} maw={440}>
        Your shipment from <b>{origin}</b> to <b>{destination}</b> hasn't been
        assigned to a train. Live tracking begins the moment it's dispatched and
        starts moving along the corridor.
      </Text>
    </Stack>
  );
}

function ErrorState({ onRetry }: { onRetry: () => void }) {
  return (
    <Stack align="center" gap={8} py={40} ta="center">
      <Box
        style={{
          width: 60,
          height: 60,
          borderRadius: 16,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          background: "#FBEAE7",
          color: "#C0392B",
        }}
      >
        <AlertTriangle size={28} />
      </Box>
      <Text fz="16px" fw={800} c={INK}>
        Couldn't load tracking
      </Text>
      <Text fz="13px" c={MUTED}>
        Something went wrong fetching your shipment status.
      </Text>
      <button
        type="button"
        onClick={onRetry}
        style={{
          marginTop: 6,
          display: "inline-flex",
          alignItems: "center",
          gap: 7,
          padding: "9px 16px",
          borderRadius: 10,
          border: "1px solid #E6ECF2",
          background: "#fff",
          color: INK,
          fontWeight: 700,
          fontSize: 13,
          cursor: "pointer",
        }}
      >
        <RefreshCw size={15} /> Try again
      </button>
    </Stack>
  );
}

// ── helpers ────────────────────────────────────────────────────────────────────

function fmtTime(iso?: string | null): string {
  if (!iso) return "—";
  const d = new Date(iso);
  if (Number.isNaN(d.getTime())) return "—";
  return d.toLocaleString(undefined, {
    month: "short",
    day: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

// keyframes (injected once)
if (
  typeof document !== "undefined" &&
  !document.getElementById("edr-tracking-kf")
) {
  const style = document.createElement("style");
  style.id = "edr-tracking-kf";
  style.textContent = `
@keyframes edr-spin { to { transform: rotate(360deg); } }
@keyframes edr-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
@keyframes edr-bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
`;
  document.head.appendChild(style);
}
