import { Link, useParams } from "react-router-dom";
import { isAxiosError } from "axios";
import { useState } from "react";
import {
  ArrowLeft,
  CalendarClock,
  CheckCircle2,
  Flag,
  MapPin,
  Navigation,
  PackageCheck,
  Train,
} from "lucide-react";
import {
  Alert,
  Badge,
  Box,
  Button,
  Group,
  Loader,
  Paper,
  RingProgress,
  Stack,
  Text,
  ThemeIcon,
  Timeline,
  Title,
} from "@mantine/core";

import { PageContainer } from "@/components/page";
import { LogPassYardWorkModal } from "@/components/trainScheduling/LogPassYardWorkModal";
import { RouteCorridorTrack } from "@/components/trainScheduling/RouteCorridorTrack";
import type { TrackStation } from "@/types/trainScheduling";
import {
  RouteCorridor,
  StatusPill,
  scheduleBrand,
} from "@/components/trainScheduling/scheduleVisuals";
import { freightBrand } from "@/theme/freight-brand";
import { useMutation, useQuery } from "@tanstack/react-query";
import { api } from "@/services/api";
import { useToast } from "@/hooks/use-toast";

const parseError = (error: unknown, fallback: string) => {
  if (isAxiosError(error)) {
    const data = error.response?.data as Record<string, unknown> | undefined;
    const message = data?.message;
    if (Array.isArray(message)) return message.join(", ");
    if (typeof message === "string") return message;
  }
  return fallback;
};

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

/**
 * A single fact in the hero's glass meta strip — icon chip + uppercase label +
 * value, laid on the translucent panel over the gradient.
 */
function HeroStat({
  icon,
  label,
  value,
}: {
  icon: React.ReactNode;
  label: string;
  value: string;
}) {
  return (
    <Group gap={10} wrap="nowrap" style={{ minWidth: 0 }}>
      <Box
        style={{
          width: 34,
          height: 34,
          borderRadius: 10,
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          background: "rgba(255,255,255,0.16)",
          border: "1px solid rgba(255,255,255,0.24)",
          color: "white",
          flexShrink: 0,
        }}
      >
        {icon}
      </Box>
      <Stack gap={1} style={{ minWidth: 0 }}>
        <Text
          size="10px"
          fw={700}
          tt="uppercase"
          style={{ letterSpacing: 0.6, color: "rgba(255,255,255,0.72)" }}
        >
          {label}
        </Text>
        <Text size="sm" fw={700} c="white" truncate>
          {value}
        </Text>
      </Stack>
    </Group>
  );
}

/** Section header — icon chip + title + one-line hint. Shared by the cards. */
function SectionHead({
  icon,
  title,
  hint,
}: {
  icon: React.ReactNode;
  title: string;
  hint: string;
}) {
  return (
    <Group gap="sm" align="center" wrap="nowrap">
      <ThemeIcon size={36} radius="md" variant="light" color="edr-green">
        {icon}
      </ThemeIcon>
      <Stack gap={0} style={{ minWidth: 0 }}>
        <Text fw={800} size="sm">
          {title}
        </Text>
        <Text size="xs" c="dimmed">
          {hint}
        </Text>
      </Stack>
    </Group>
  );
}

const CARD_STYLE = {
  borderColor: scheduleBrand.mutedBorder,
  boxShadow: scheduleBrand.shadowSm,
} as const;

export default function TrainScheduleTrackPage() {
  const { scheduleId } = useParams<{ scheduleId: string }>();
  const { toast } = useToast();
  const trackQuery = useQuery(
    api.trainScheduling.trainTrack.queryOptions({
      input: { id: scheduleId ?? "" },
      enabled: Boolean(scheduleId),
    }),
  );
  const recordCheckpoint = useMutation(
    api.trainScheduling.recordCheckpoint.mutationOptions(),
  );
  // Yard work drives the log-pass modal: which bookings board/alight per stop.
  const yardWorkQuery = useQuery(
    api.trainScheduling.yardWork.queryOptions({
      input: { scheduleId: scheduleId ?? "" },
      enabled: Boolean(scheduleId) && trackQuery.data?.status === "DISPATCHED",
    }),
  );
  const [yardModal, setYardModal] = useState<{
    station: TrackStation;
    isFinal: boolean;
    alreadyLogged: boolean;
  } | null>(null);

  if (trackQuery.isLoading) {
    return (
      <PageContainer>
        <Group justify="center" py="xl">
          <Loader size="sm" color="edr-green" />
        </Group>
      </PageContainer>
    );
  }

  const track = trackQuery.data;
  if (!track || !scheduleId) {
    return (
      <PageContainer>
        <Text c="dimmed" py="xl">
          Tracking data not found.
        </Text>
      </PageContainer>
    );
  }

  const canLog = track.status === "DISPATCHED";
  const totalStations = track.stations.length;
  const reached = Math.min(track.currentSequenceNo + 1, totalStations);
  const progressPct =
    totalStations > 1 ? (track.currentSequenceNo / (totalStations - 1)) * 100 : 0;
  const clampedPct = Math.min(100, Math.max(0, progressPct));
  const currentStation =
    track.stations[Math.max(0, track.currentSequenceNo)]?.label ?? "—";
  const inTransit = track.status === "DISPATCHED";
  const arrived = track.status === "ARRIVED";

  // Yard work at a station: boarders not yet loaded, and loaded bookings that
  // alight there. When either exists, logging the pass goes through the modal
  // so the operator sees (and can act on) both lists; empty yards log directly.
  const yardWorkFor = (station: TrackStation | undefined) =>
    yardWorkQuery.data?.yards.find((y) => y.yardId === station?.yardId);
  const stationHasWork = (station: TrackStation | undefined) => {
    const yard = yardWorkFor(station);
    return Boolean(
      yard &&
        (yard.toLoad.some((r) => !r.loadedAt) || yard.toUnload.some((r) => r.canUnload)),
    );
  };

  const handleLog = (sequenceNo: number) => {
    const station = track.stations.find((s) => s.sequenceNo === sequenceNo);
    const isFinal = sequenceNo === track.stations[totalStations - 1]?.sequenceNo;
    if (station && stationHasWork(station)) {
      setYardModal({ station, isFinal, alreadyLogged: false });
      return;
    }
    recordCheckpoint.mutate(
      { id: scheduleId, payload: { sequenceNo } },
      {
        onSuccess: () => {
          toast({
            title: isFinal
              ? "Train arrived — assets freed, moved to destination yard"
              : "Checkpoint logged",
          });
        },
        onError: (err) =>
          toast({
            title: "Could not log checkpoint",
            description: parseError(err, "Please try again"),
            variant: "destructive",
          }),
      },
    );
  };

  // "Forgot to load" catch: while the train sits at the current station, any
  // boarder there that is still unloaded can be loaded until the next pass.
  const currentStationObj = track.stations.find(
    (s) => s.sequenceNo === track.currentSequenceNo,
  );
  const currentYard = canLog ? yardWorkFor(currentStationObj) : undefined;
  const forgottenBoarders =
    currentYard?.toLoad.filter((r) => !r.loadedAt) ?? [];

  return (
    <PageContainer>
      <Button
        component={Link}
        to={`/dashboard/operations/train-scheduling-v2/${scheduleId}`}
        variant="subtle"
        color="gray"
        size="compact-sm"
        leftSection={<ArrowLeft size={16} />}
        w="fit-content"
      >
        Back to schedule
      </Button>

      {/* ── Hero: gradient wash, route + a bold progress ring woven together ── */}
      <Paper
        radius="lg"
        p={0}
        style={{ overflow: "hidden", boxShadow: scheduleBrand.shadow }}
      >
        <Box
          style={{
            background: scheduleBrand.heroGradient,
            padding: "26px 28px",
            position: "relative",
          }}
        >
          {/* soft decorative glow, purely artistic */}
          <Box
            style={{
              position: "absolute",
              top: -80,
              right: -60,
              width: 260,
              height: 260,
              borderRadius: "50%",
              background: "rgba(255,255,255,0.10)",
              pointerEvents: "none",
            }}
          />

          <Group
            justify="space-between"
            align="flex-start"
            wrap="wrap"
            gap="xl"
            style={{ position: "relative" }}
          >
            {/* left — identity + route */}
            <Stack gap={14} style={{ minWidth: 260, flex: 1 }}>
              <Group gap="md" align="center" wrap="nowrap">
                <Box
                  style={{
                    width: 52,
                    height: 52,
                    borderRadius: 14,
                    display: "flex",
                    alignItems: "center",
                    justifyContent: "center",
                    background: "rgba(255,255,255,0.16)",
                    border: "1px solid rgba(255,255,255,0.26)",
                    color: "white",
                    flexShrink: 0,
                  }}
                >
                  <Navigation size={26} />
                </Box>
                <Stack gap={6} style={{ minWidth: 0 }}>
                  <Group gap="sm" align="center" wrap="wrap">
                    <Title order={3} fw={800} c="white">
                      Train tracking
                    </Title>
                    {track.trainNumber ? (
                      <Badge
                        variant="white"
                        color="dark"
                        radius="sm"
                        styles={{ root: { color: freightBrand.primaryDark } }}
                      >
                        {track.trainNumber}
                      </Badge>
                    ) : null}
                    {track.direction ? (
                      <Badge
                        variant="outline"
                        radius="sm"
                        styles={{
                          root: {
                            color: "white",
                            borderColor: "rgba(255,255,255,0.5)",
                          },
                        }}
                      >
                        {track.direction}
                      </Badge>
                    ) : null}
                  </Group>
                  <Box maw={380}>
                    <RouteCorridor
                      origin={track.origin}
                      destination={track.destination}
                      variant="compact"
                      onDark
                    />
                  </Box>
                </Stack>
              </Group>

              <Group gap="sm">
                <StatusPill status={track.status} size="md" />
                <Box
                  px={12}
                  py={5}
                  style={{
                    borderRadius: 999,
                    background: "rgba(255,255,255,0.16)",
                    border: "1px solid rgba(255,255,255,0.24)",
                  }}
                >
                  <Text size="xs" fw={700} c="white" style={{ letterSpacing: 0.2 }}>
                    {arrived
                      ? "Journey complete"
                      : inTransit
                        ? `En route · ${currentStation}`
                        : "Awaiting dispatch"}
                  </Text>
                </Box>
              </Group>
            </Stack>

            {/* right — progress ring, the artistic focal point */}
            <RingProgress
              size={132}
              thickness={11}
              roundCaps
              sections={[{ value: clampedPct, color: "white" }]}
              rootColor="rgba(255,255,255,0.22)"
              label={
                <Stack gap={0} align="center">
                  <Text fw={800} fz={26} lh={1} c="white">
                    {Math.round(clampedPct)}%
                  </Text>
                  <Text
                    size="10px"
                    fw={700}
                    tt="uppercase"
                    style={{ letterSpacing: 0.6, color: "rgba(255,255,255,0.8)" }}
                  >
                    {reached}/{totalStations} stops
                  </Text>
                </Stack>
              }
            />
          </Group>
        </Box>

        {/* glass meta strip below the wash */}
        <Group
          justify="space-between"
          wrap="wrap"
          gap="lg"
          px={28}
          py="md"
          style={{
            background: freightBrand.primaryDark,
            borderTop: "1px solid rgba(255,255,255,0.12)",
          }}
        >
          <HeroStat icon={<MapPin size={16} />} label="Current" value={currentStation} />
          <HeroStat
            icon={<CalendarClock size={16} />}
            label="Departed"
            value={formatDateTime(track.actualDepartureAt)}
          />
          <HeroStat
            icon={<Flag size={16} />}
            label="Arrived"
            value={formatDateTime(track.actualArrivalAt)}
          />
          <HeroStat
            icon={<Train size={16} />}
            label="Stations"
            value={`${reached} of ${totalStations}`}
          />
        </Group>
      </Paper>

      {/* ── Route corridor ── */}
      <Paper radius="lg" p="lg" withBorder style={CARD_STYLE}>
        <Stack gap="md">
          <SectionHead
            icon={<Navigation size={17} />}
            title="Route corridor"
            hint={
              canLog
                ? "Log the train passing each station; the final station marks arrival."
                : arrived
                  ? "This train has arrived at its destination."
                  : "Tracking becomes available once the train is dispatched."
            }
          />
          <RouteCorridorTrack
            stations={track.stations}
            currentSequenceNo={track.currentSequenceNo}
            checkpoints={track.checkpoints}
            canLog={canLog}
            loggingSeq={
              recordCheckpoint.isPending
                ? recordCheckpoint.variables?.payload.sequenceNo
                : null
            }
            onLogCheckpoint={handleLog}
          />

          {/* Cargo the operator forgot: boarders at the CURRENT station stay
              loadable until the next pass is logged. */}
          {currentStationObj && forgottenBoarders.length > 0 ? (
            <Alert
              color="yellow"
              variant="light"
              radius="md"
              icon={<PackageCheck size={16} />}
              title={`${forgottenBoarders.length} booking${
                forgottenBoarders.length === 1 ? "" : "s"
              } at ${currentStationObj.label} not loaded yet`}
            >
              <Group justify="space-between" align="center" wrap="wrap" gap="sm">
                <Text size="sm">
                  The train is at {currentStationObj.label} — cargo boarding here can
                  still be loaded before the next station is logged.
                </Text>
                <Button
                  size="compact-sm"
                  variant="light"
                  color="yellow"
                  onClick={() =>
                    setYardModal({
                      station: currentStationObj,
                      isFinal:
                        currentStationObj.sequenceNo ===
                        track.stations[totalStations - 1]?.sequenceNo,
                      alreadyLogged: true,
                    })
                  }
                >
                  Open yard work
                </Button>
              </Group>
            </Alert>
          ) : null}
        </Stack>
      </Paper>

      {/* ── Checkpoint log ── */}
      <Paper radius="lg" p="lg" withBorder style={CARD_STYLE}>
        <Group justify="space-between" wrap="nowrap" mb="md">
          <SectionHead
            icon={<CheckCircle2 size={17} />}
            title="Checkpoint log"
            hint={`${track.checkpoints.length} event${
              track.checkpoints.length === 1 ? "" : "s"
            } recorded`}
          />
        </Group>

        {track.checkpoints.length === 0 ? (
          <Stack
            align="center"
            gap="xs"
            py={40}
            style={{
              borderRadius: 14,
              border: `1px dashed ${scheduleBrand.mutedBorder}`,
              background: scheduleBrand.softSurface,
            }}
          >
            <ThemeIcon size={48} radius="xl" variant="light" color="edr-green">
              <MapPin size={22} />
            </ThemeIcon>
            <Text size="sm" fw={700} c="gray.7">
              No checkpoints yet
            </Text>
            <Text size="xs" c="dimmed" ta="center" maw={320}>
              Each station the train passes will be logged here with its
              timestamp.
            </Text>
          </Stack>
        ) : (
          <Timeline
            active={track.checkpoints.length}
            bulletSize={24}
            lineWidth={2}
            color="edr-green"
          >
            {track.checkpoints.map((cp) => (
              <Timeline.Item
                key={cp.id}
                bullet={
                  cp.kind === "ARRIVED" ? (
                    <CheckCircle2 size={13} />
                  ) : (
                    <MapPin size={12} />
                  )
                }
                title={
                  <Group gap="sm">
                    <Text fw={700} size="sm">
                      {cp.label ?? `Station ${cp.sequenceNo}`}
                    </Text>
                    <Badge
                      size="xs"
                      radius="sm"
                      variant="light"
                      color={
                        cp.kind === "ARRIVED"
                          ? "teal"
                          : cp.kind === "DEPARTED"
                            ? "blue"
                            : "edr-green"
                      }
                    >
                      {cp.kind}
                    </Badge>
                  </Group>
                }
              >
                <Text size="xs" c="dimmed">
                  {formatDateTime(cp.occurredAt)}
                </Text>
                {cp.note ? (
                  <Text size="xs" mt={2}>
                    {cp.note}
                  </Text>
                ) : null}
              </Timeline.Item>
            ))}
          </Timeline>
        )}
      </Paper>

      <LogPassYardWorkModal
        opened={yardModal !== null}
        onClose={() => setYardModal(null)}
        scheduleId={scheduleId}
        station={yardModal?.station ?? null}
        isFinal={yardModal?.isFinal ?? false}
        alreadyLogged={yardModal?.alreadyLogged ?? false}
      />
    </PageContainer>
  );
}
