import { Link, useParams } from "react-router-dom";
import { isAxiosError } from "axios";
import { useState } from "react";
import {
  ArrowLeft,
  CalendarClock,
  CheckCircle2,
  FileText,
  Flag,
  MapPin,
  Navigation,
  PackageCheck,
  Pencil,
  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 { CheckpointTimeModal } from "@/components/trainScheduling/CheckpointTimeModal";
import { LogPassYardWorkModal } from "@/components/trainScheduling/LogPassYardWorkModal";
import { RouteCorridorTrack } from "@/components/trainScheduling/RouteCorridorTrack";
import type { TrackStation, TrainCheckpoint } 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";
import { openPdfBlob } from "@/components/warehouses/pdf";
import { trainSchedulingService } from "@/services/trainScheduling.service";

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(),
  );
  const updateCheckpoint = useMutation(
    api.trainScheduling.updateCheckpoint.mutationOptions(),
  );
  // Time-entry dialogs: logging a pass at a yard with no work (the yard-work
  // modal carries its own picker), and correcting an already-logged leg.
  const [logModal, setLogModal] = useState<{
    station: TrackStation;
    isFinal: boolean;
  } | null>(null);
  const [editModal, setEditModal] = useState<TrainCheckpoint | null>(null);
  // 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",
    }),
  );
  // Marshalling 2: the current on-board list, reprinted after station work.
  const intercityMarshalling = useMutation({
    mutationFn: () =>
      trainSchedulingService.downloadIntercityMarshallingDocument(scheduleId ?? ""),
  });
  const openIntercityMarshalling = async () => {
    const pdfWindow = window.open("", "_blank");
    try {
      const blob = await intercityMarshalling.mutateAsync();
      const opened = openPdfBlob(blob, `intercity-marshalling-${scheduleId}.pdf`, pdfWindow);
      toast({
        title: "Intercity marshalling ready",
        description: opened
          ? "The PDF opened in a browser tab for printing or saving."
          : "The browser blocked the preview tab, so the PDF was downloaded.",
      });
    } catch (error) {
      pdfWindow?.close();
      toast({
        title: "Could not open intercity marshalling document",
        description: parseError(error, "Please try again"),
        variant: "destructive",
      });
    }
  };
  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);
    if (!station) return;
    const isFinal = sequenceNo === track.stations[totalStations - 1]?.sequenceNo;
    if (stationHasWork(station)) {
      setYardModal({ station, isFinal, alreadyLogged: false });
      return;
    }
    setLogModal({ station, isFinal });
  };

  const submitLog = (values: { occurredAt: string; note: string }) => {
    if (!logModal) return;
    const { station, isFinal } = logModal;
    recordCheckpoint.mutate(
      {
        id: scheduleId,
        payload: {
          sequenceNo: station.sequenceNo,
          occurredAt: values.occurredAt,
          ...(values.note ? { note: values.note } : {}),
        },
      },
      {
        onSuccess: () => {
          setLogModal(null);
          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",
          }),
      },
    );
  };

  const submitEdit = (values: { occurredAt: string; note: string }) => {
    if (!editModal) return;
    updateCheckpoint.mutate(
      {
        id: scheduleId,
        sequenceNo: editModal.sequenceNo,
        payload: { occurredAt: values.occurredAt, note: values.note || null },
      },
      {
        onSuccess: () => {
          setEditModal(null);
          toast({ title: "Checkpoint updated" });
        },
        onError: (err) =>
          toast({
            title: "Could not update checkpoint",
            description: parseError(err, "Please try again"),
            variant: "destructive",
          }),
      },
    );
  };
  // Legs stay correctable for as long as the journey exists — while rolling
  // and after arrival.
  const canEdit = track.status === "DISPATCHED" || track.status === "ARRIVED";

  // "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>
      <Group justify="space-between" w="100%">
        <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>
        {inTransit || arrived ? (
          <Button
            variant="light"
            color="edr-green"
            radius="lg"
            size="compact-sm"
            leftSection={<FileText size={16} />}
            loading={intercityMarshalling.isPending}
            onClick={() => void openIntercityMarshalling()}
          >
            Intercity Marshalling
          </Button>
        ) : null}
      </Group>

      {/* ── 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}
            onEditCheckpoint={canEdit ? setEditModal : undefined}
          />

          {/* 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" justify="space-between" wrap="nowrap">
                    <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>
                    {canEdit ? (
                      <Button
                        size="compact-xs"
                        radius="md"
                        variant="light"
                        color="gray"
                        leftSection={<Pencil size={12} />}
                        onClick={() => setEditModal(cp)}
                      >
                        Edit
                      </Button>
                    ) : null}
                  </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>

      <CheckpointTimeModal
        opened={logModal !== null}
        onClose={() => setLogModal(null)}
        title={
          logModal?.isFinal
            ? `Mark arrived at ${logModal.station.label}`
            : `Log pass at ${logModal?.station.label ?? "station"}`
        }
        icon={logModal?.isFinal ? <Flag size={18} /> : <MapPin size={18} />}
        description={
          logModal?.isFinal
            ? "Marks the train arrived: remaining bookings arrive, assets are freed."
            : undefined
        }
        submitLabel={logModal?.isFinal ? "Mark arrived" : "Log pass"}
        submitColor={logModal?.isFinal ? "teal" : "edr-green"}
        loading={recordCheckpoint.isPending}
        onSubmit={submitLog}
      />

      <CheckpointTimeModal
        opened={editModal !== null}
        onClose={() => setEditModal(null)}
        title={`Edit ${editModal?.label ?? "checkpoint"}`}
        icon={<Pencil size={18} />}
        description="Corrects this leg's time and note only — nothing else changes."
        initialOccurredAt={editModal?.occurredAt}
        initialNote={editModal?.note}
        submitLabel="Save"
        loading={updateCheckpoint.isPending}
        onSubmit={submitEdit}
      />

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