import {
  Alert,
  Badge,
  Box,
  Button,
  Checkbox,
  Group,
  List,
  Loader,
  Modal,
  Paper,
  RingProgress,
  Stack,
  Tabs,
  Text,
  ThemeIcon,
  Title,
} from "@mantine/core";
import { isAxiosError } from "axios";
import {
  AlertTriangle,
  ArrowLeft,
  CalendarClock,
  CheckCircle2,
  Clock,
  Container as ContainerIcon,
  Eye,
  FileText,
  LayoutGrid,
  Navigation,
  Package,
  PackageCheck,
  Route as RouteIcon,
  Send,
  Train,
  Weight,
  Workflow as WorkflowIcon,
} from "lucide-react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Link, useParams } from "react-router-dom";

import { KpiStrip, PageContainer } from "@/components/page";
import {
  autoFillPlacements,
  mergePlacementsWithSaved,
  placementsFromScheduleWagons,
  validateLocalPlacements,
} from "@/components/trainScheduling/containerPlacement.util";
import { ContainerPlacementGrid } from "@/components/trainScheduling/ContainerPlacementGrid";
import { FleetAvailabilitySummary } from "@/components/trainScheduling/FleetAvailabilitySummary";
import { IntercityRideAlongPanel } from "@/components/trainScheduling/IntercityRideAlongPanel";
import { YardWorkPanel } from "@/components/trainScheduling/YardWorkPanel";
// import { ImportLoadingConfirmationPanel } from "@/components/trainScheduling/ImportLoadingConfirmationPanel";
import { RescheduleTrainDialog } from "@/components/trainScheduling/RescheduleTrainDialog";
import BookingWindowSettingsModal from "@/components/trainScheduling/BookingWindowSettingsModal";
// import { ScheduleBatchPanel } from "@/components/trainScheduling/ScheduleBatchPanel";
import { ScheduleBookingsStep } from "@/components/trainScheduling/ScheduleBookingsStep";
import { ScheduleWorkspacePanel } from "@/components/trainScheduling/ScheduleWorkspacePanel";
import { FreightTypeBadge } from "@/components/trainScheduling/ScheduleStatusBadge";
import {
  RouteCorridor,
  SegmentOccupancyStrip,
  StatusPill,
  scheduleBrand,
} from "@/components/trainScheduling/scheduleVisuals";
import {
  PreviewSummary,
  ScheduleWarningsAlert,
} from "@/components/trainScheduling/ScheduleWarningsAlert";
import { TrainCompositionDiagram } from "@/components/trainScheduling/TrainCompositionDiagram";
import { TrainConsistView } from "@/components/trainScheduling/compositionEditor";
import { WagonPlanGrid } from "@/components/trainScheduling/WagonPlanGrid";
import { WorkflowRail, WorkflowStep } from "@/components/trainScheduling/WorkflowStep";
import { openPdfBlob } from "@/components/warehouses/pdf";
import { useMutation, useQuery } from "@tanstack/react-query";
import { api } from "@/services/api";
import { trainSchedulingService } from "@/services/trainScheduling.service";
import { useToast } from "@/hooks/use-toast";
import type {
  ContainerPlacement,
  FreightType,
  TrainSchedulePreviewResponse,
} from "@/types/trainScheduling";

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;
    const violations = data?.violations;
    if (Array.isArray(violations)) return violations.join(", ");
  }
  return fallback;
};

export default function TrainScheduleV2DetailPage() {
  const { scheduleId } = useParams<{ scheduleId: string }>();
  const { toast } = useToast();
  const [activeStep, setActiveStep] = useState(0);
  const [selectedBookingIds, setSelectedBookingIds] = useState<string[]>([]);
  const [forceAssign, setForceAssign] = useState(false);
  const [previewResult, setPreviewResult] = useState<TrainSchedulePreviewResponse | null>(null);
  const [containerPlacements, setContainerPlacements] = useState<ContainerPlacement[]>([]);
  const [maintenanceOpen, setMaintenanceOpen] = useState(false);
  const [windowSettingsOpen, setWindowSettingsOpen] = useState(false);
  const [gatepassSecuredAt, setGatepassSecuredAt] = useState("");
  const [gatepassReference, setGatepassReference] = useState("");
  const [gatepassFileUrl, setGatepassFileUrl] = useState("");
  const [gatepassNotes, setGatepassNotes] = useState("");
  const [dispatchConfirmOpen, setDispatchConfirmOpen] = useState(false);
  const autoPreviewedRef = useRef(false);

  const detailQuery = useQuery(
    api.trainScheduling.scheduleDetail.queryOptions({
      input: { id: scheduleId ?? "" },
      enabled: Boolean(scheduleId),
    }),
  );
  const schedule = detailQuery.data;
  const freightType: FreightType | undefined = schedule?.freightType as FreightType | undefined;
  const isDjiboutiPort = (value?: string | null) =>
    ["DJIBOUTI", "DORALEH", "DMP", "DCT", "NAGAD"].some((token) =>
      (value ?? "").toUpperCase().includes(token),
    );
  const gatepassApplies = Boolean(
    schedule &&
      ((schedule.direction === "IMPORT" &&
        isDjiboutiPort(`${schedule.originStation?.code ?? ""} ${schedule.originStation?.label ?? ""}`)) ||
        (schedule.direction === "EXPORT" &&
          isDjiboutiPort(`${schedule.destinationStation?.code ?? ""} ${schedule.destinationStation?.label ?? ""}`))),
  );
  const gatepassQuery = useQuery({
    queryKey: ["train-scheduling", "gatepass", scheduleId],
    queryFn: () => trainSchedulingService.getImportDjiboutiOperation(scheduleId as string),
    enabled: Boolean(scheduleId && gatepassApplies),
  });
  const gatepassSecured = gatepassQuery.data?.gatepassStatus === "SECURED";
  const secureGatepass = useMutation({
    mutationFn: () =>
      trainSchedulingService.grantImportDjiboutiGatepass(scheduleId as string, {
        securedAt: gatepassSecuredAt ? new Date(gatepassSecuredAt).toISOString() : undefined,
        reference: gatepassReference.trim() || undefined,
        fileUrl: gatepassFileUrl.trim() || undefined,
        notes: gatepassNotes.trim() || undefined,
      }),
    onSuccess: () => {
      toast({ title: "Gate pass secured" });
      void gatepassQuery.refetch();
    },
    onError: (error) => {
      toast({
        title: "Gate pass failed",
        description: parseError(error, "Could not secure gate pass"),
        variant: "destructive",
      });
    },
  });

  // Superseded by the Workspace tab Load/Unload toggle — see commented
  // "Import loading confirmation" card below.
  // const importLoadingQuery = useQuery(
  //   api.trainScheduling.importLoadingBookings.queryOptions({
  //     input: { id: scheduleId ?? "" },
  //     enabled: Boolean(scheduleId && schedule?.direction === "IMPORT"),
  //   }),
  // );

  const eligibleFilters = useMemo(
    () =>
      schedule
        ? {
            originStationId: schedule.originStation?.id,
            destinationStationId: schedule.destinationStation?.id,
            // Only this schedule's own bookings are eligible — same rule as the auto batch.
            trainScheduleId: scheduleId,
          }
        : undefined,
    [schedule, scheduleId],
  );

  const eligibleFreightType =
    freightType === "CONTAINER" || freightType === "BULK" ? freightType : undefined;

  const eligibleQuery = useQuery(
    api.trainScheduling.eligibleBookings.queryOptions({
      input: { filters: eligibleFilters, freightType: eligibleFreightType },
      enabled: Boolean(schedule),
    }),
  );
  const preview = useMutation(api.trainScheduling.preview.mutationOptions());
  const assign = useMutation(api.trainScheduling.assignBookings.mutationOptions());
  const unassign = useMutation(api.trainScheduling.unassignBooking.mutationOptions());
  const finalize = useMutation(api.trainScheduling.finalizeSchedule.mutationOptions());
  const dispatch = useMutation(api.trainScheduling.dispatchSchedule.mutationOptions());
  const downloadMarshalling = useMutation({
    mutationFn: ({ id, direction }: { id: string; direction?: string | null }) =>
      direction === "EXPORT"
        ? trainSchedulingService.downloadExportLoadListDocument(id)
        : trainSchedulingService.downloadImportDjiboutiLoadListDocument(id),
  });

  useEffect(() => {
    const operation = gatepassQuery.data;
    if (!operation) return;
    const secured = operation.gatepassSecuredAt ?? operation.gatepassGrantedAt;
    setGatepassSecuredAt(secured ? new Date(secured).toISOString().slice(0, 16) : "");
    setGatepassReference(operation.documents?.GATE_PASS?.reference ?? "");
    setGatepassFileUrl(operation.documents?.GATE_PASS?.fileUrl ?? "");
    setGatepassNotes(operation.documents?.GATE_PASS?.notes ?? operation.notes ?? "");
  }, [gatepassQuery.data]);

  const assignedIds = useMemo(
    () => (schedule?.bookings ?? []).map((b) => b.id),
    [schedule?.bookings],
  );

  const allSelectedIds = useMemo(() => {
    const merged = new Set([...assignedIds, ...selectedBookingIds]);
    return [...merged];
  }, [assignedIds, selectedBookingIds]);

  const containerUnits = previewResult?.containerUnits ?? [];
  const containerSlots = previewResult?.containerSlotSequenceNos ?? [];
  // Container-number placement step removed — the customer enters container
  // numbers when booking, so scheduling skips straight from the wagon plan to
  // finalize. Steps: select bookings → review wagons → finalize.
  const hasContainerStep = false;

  const displayWagonPlan = useMemo(() => {
    const savedWagons = schedule?.trainSet?.wagons ?? [];
    // Map each slot to its reserved physical wagon number (from the wagon table) so the
    // plan shows real wagon ids (e.g. WGN-DEMO-001) instead of generic "Wagon #1".
    const physicalBySeq = new Map(
      savedWagons.map((w) => [w.sequenceNo, w.physicalWagonNumber ?? null]),
    );
    if (previewResult?.wagonPlan?.length) {
      return previewResult.wagonPlan.map((slot) => ({
        ...slot,
        physicalWagonNumber: physicalBySeq.get(slot.sequenceNo) ?? null,
      }));
    }
    if (savedWagons.length) return savedWagons;
    return [];
  }, [previewResult?.wagonPlan, schedule?.trainSet?.wagons]);

  // EXPORT schedules render the consist back-to-front (the train turns around
  // for the return run) — DISPLAY ONLY: stored sequenceNos, allocations,
  // documents, and the adjust-consist / placement flows keep the as-built order.
  const isExportDisplay = schedule?.direction === "EXPORT";
  const displayWagonPlanOriented = useMemo(
    () => (isExportDisplay ? [...displayWagonPlan].reverse() : displayWagonPlan),
    [displayWagonPlan, isExportDisplay],
  );

  const runPreview = useCallback(
    async (options?: { silent?: boolean; advanceStep?: boolean }) => {
      if (!schedule || !scheduleId) return null;
      if (!allSelectedIds.length) {
        if (!options?.silent) {
          toast({ title: "Select at least one booking", variant: "destructive" });
        }
        return null;
      }
      const originStationId = schedule.originStation?.id;
      const destinationStationId = schedule.destinationStation?.id;
      if (!originStationId || !destinationStationId) {
        if (!options?.silent) {
          toast({ title: "Schedule missing origin or destination", variant: "destructive" });
        }
        return null;
      }
      try {
        const result = await preview.mutateAsync({
          freightType,
          payload: {
            bookingIds: allSelectedIds,
            scheduleDate: schedule.scheduledDepartureDate,
            originStationId,
            destinationStationId,
            targetScheduleId: scheduleId,
          },
        });
        setPreviewResult(result);
        if (result.containerUnits?.length && result.containerSlotSequenceNos?.length) {
          const autoFilled = autoFillPlacements(
            result.containerUnits,
            result.containerSlotSequenceNos,
          );
          const saved = schedule.trainSet?.wagons
            ? placementsFromScheduleWagons(schedule.trainSet.wagons)
            : [];
          setContainerPlacements(
            saved.length ? mergePlacementsWithSaved(autoFilled, saved) : autoFilled,
          );
        } else {
          setContainerPlacements([]);
        }
        if (!options?.silent) {
          if (!result.valid) {
            toast({ title: "Preview has violations", variant: "destructive" });
          } else if (options?.advanceStep !== false) {
            setActiveStep(1);
          }
        }
        return result;
      } catch (err) {
        if (!options?.silent) {
          toast({
            title: "Preview failed",
            description: parseError(err, "Could not preview"),
            variant: "destructive",
          });
        }
        return null;
      }
    },
    [allSelectedIds, freightType, preview, schedule, scheduleId, toast],
  );

  useEffect(() => {
    if (!schedule || !scheduleId || autoPreviewedRef.current) return;
    if (!assignedIds.length) return;
    autoPreviewedRef.current = true;
    void runPreview({ silent: true, advanceStep: false });
  }, [assignedIds.length, runPreview, schedule, scheduleId]);

  const savedPlacementsFromSchedule = useMemo(
    () =>
      schedule?.trainSet?.wagons
        ? placementsFromScheduleWagons(schedule.trainSet.wagons)
        : [],
    [schedule?.trainSet?.wagons],
  );

  useEffect(() => {
    if (!containerUnits.length || !containerSlots.length) return;

    setContainerPlacements((current) => {
      if (current.length && current.some((p) => p.containerNumber?.trim())) {
        return current;
      }
      const autoFilled = autoFillPlacements(containerUnits, containerSlots);
      if (savedPlacementsFromSchedule.length) {
        return mergePlacementsWithSaved(autoFilled, savedPlacementsFromSchedule);
      }
      if (current.length) return current;
      return autoFilled;
    });
  }, [containerUnits, containerSlots, savedPlacementsFromSchedule]);

  if (detailQuery.isLoading) {
    return (
      <PageContainer>
        <Group justify="center" py="xl">
          <Loader size="sm" />
        </Group>
      </PageContainer>
    );
  }

  if (!schedule || !scheduleId) {
    return (
      <PageContainer>
        <Text c="dimmed" py="xl">
          Schedule not found
        </Text>
      </PageContainer>
    );
  }

  // All locomotives pulling the train (≥2), falling back to the legacy single loco.
  const locomotives =
    schedule.trainSet?.locomotives && schedule.trainSet.locomotives.length > 0
      ? schedule.trainSet.locomotives
      : schedule.trainSet?.locomotive
        ? [schedule.trainSet.locomotive]
        : [];

  const canEditBookings = ["DRAFT", "SCHEDULED"].includes(schedule.status);
  const canFinalize = schedule.status === "DRAFT" && (schedule.bookings?.length ?? 0) > 0;
  const canDispatch = schedule.status === "SCHEDULED";

  // Dispatch readiness: bookings with no wagon, and wagon-loaded bookings whose
  // cargo staff never marked loaded. Both are warnings, not blockers — staff can
  // still dispatch after confirming.
  const dispatchBookings = schedule.bookings ?? [];
  const unassignedCount = dispatchBookings.filter((b) => !b.wagonAssigned).length;
  const unloadedCount = dispatchBookings.filter(
    (b) => b.wagonAssigned && (b.loadingStatus ?? "UNLOADED") !== "LOADED",
  ).length;
  // Intercity ride-alongs load through the journey flow (Load at their origin
  // yard), not the workspace toggle — dispatching before that leaves paid cargo
  // stranded on the platform while its train departs.
  const intercityNotLoadedCount = dispatchBookings.filter(
    (b) =>
      b.tradeDirection === "DOMESTIC" &&
      !b.loadedAt &&
      !["IN_TRANSIT", "COMPLETED"].includes(b.status ?? ""),
  ).length;
  // No loading hard-block: bookings may board mid-corridor, so loading happens
  // per yard from the track page's log-pass flow. Everything below is advisory.
  const hasDispatchWarnings =
    unassignedCount > 0 || unloadedCount > 0 || intercityNotLoadedCount > 0;

  const finalizeStep = hasContainerStep ? 3 : 2;
  const canModifyBookings = canEditBookings && !["DISPATCHED", "ARRIVED"].includes(schedule.status);
  const canPrintMarshalling =
    (schedule.direction === "IMPORT" || schedule.direction === "EXPORT") &&
    ["DISPATCHED", "ARRIVED"].includes(schedule.status);

  const openMarshallingDocument = async (options?: {
    title?: string;
    successDescription?: string;
    errorTitle?: string;
  }) => {
    const pdfWindow = window.open("", "_blank");
    try {
      const blob = await downloadMarshalling.mutateAsync({
        id: scheduleId,
        direction: schedule.direction,
      });
      const prefix = schedule.direction === "EXPORT" ? "export-marshalling" : "import-marshalling";
      const filename = `${prefix}-${schedule.trainNumber ?? scheduleId}.pdf`;
      const opened = openPdfBlob(blob, filename, pdfWindow);
      toast({
        title: options?.title ?? "Marshalling document ready",
        description:
          options?.successDescription ??
          (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: options?.errorTitle ?? "Could not open marshalling document",
        description: parseError(error, "Make sure the train has wagon allocations, then try again."),
        variant: "destructive",
      });
    }
  };

  const runDispatch = async () => {
    setDispatchConfirmOpen(false);
    try {
      await dispatch.mutateAsync(scheduleId);
      await openMarshallingDocument({
        title: "Train dispatched",
        successDescription: "Marshalling document generated for the dispatched train.",
        errorTitle: "Train dispatched, but document could not open",
      });
    } catch (err) {
      toast({
        title: "Dispatch failed",
        description: parseError(err, "Could not dispatch"),
        variant: "destructive",
      });
    }
  };

  const handleAssign = async () => {
    if (!allSelectedIds.length) return;

    if (hasContainerStep) {
      const issues = validateLocalPlacements(containerUnits, containerPlacements);
      if (issues.length) {
        toast({
          title: "Complete container assignments",
          description: issues.join(", "),
          variant: "destructive",
        });
        return;
      }
    }

    try {
      const result = await assign.mutateAsync({
        id: scheduleId,
        freightType,
        payload: {
          bookingIds: allSelectedIds,
          forceAssign,
          containerPlacements: hasContainerStep ? containerPlacements : undefined,
        },
      });
      toast({ title: "Bookings assigned — wagons auto-pinned" });
      const refreshed = await detailQuery.refetch();
      const saved = refreshed.data?.trainSet?.wagons
        ? placementsFromScheduleWagons(refreshed.data.trainSet.wagons)
        : [];
      if (saved.length) {
        setContainerPlacements(saved);
      }
      autoPreviewedRef.current = false;
      setActiveStep(finalizeStep);
      if (result.deferredBookings?.length) {
        toast({
          title: "Partial assignment",
          description: `${result.deferredBookings.length} booking(s) deferred to next train`,
        });
      }
    } catch (err) {
      toast({
        title: "Assign failed",
        description: parseError(err, "Could not assign"),
        variant: "destructive",
      });
    }
  };

  const handleUnassign = async (bookingId: string) => {
    try {
      await unassign.mutateAsync({ id: scheduleId, bookingId });
      toast({ title: "Booking unassigned" });
      setSelectedBookingIds((ids) => ids.filter((id) => id !== bookingId));
      setPreviewResult(null);
      autoPreviewedRef.current = false;
    } catch (err) {
      toast({
        title: "Unassign failed",
        description: parseError(err, "Could not unassign"),
        variant: "destructive",
      });
    }
  };

  const containerComplete =
    hasContainerStep &&
    containerUnits.length > 0 &&
    validateLocalPlacements(containerUnits, containerPlacements).length === 0;
  const finalizeComplete = ["SCHEDULED", "DISPATCHED", "ARRIVED"].includes(
    schedule.status,
  );

  const stepsMeta = [
    {
      key: "bookings",
      icon: Package,
      title: "Bookings",
      subtitle: "Select cargo & preview the plan",
      complete: Boolean(previewResult) || assignedIds.length > 0,
    },
    {
      key: "wagon",
      icon: LayoutGrid,
      title: "Wagon plan",
      subtitle: "Review generated allocations",
      complete: displayWagonPlan.length > 0,
    },
    ...(hasContainerStep
      ? [
          {
            key: "container",
            icon: ContainerIcon,
            title: "Containers",
            subtitle: "Map units to wagon slots",
            complete: containerComplete,
          },
        ]
      : []),
    {
      key: "finalize",
      icon: CheckCircle2,
      title: "Finalize",
      subtitle: "Lock the plan & dispatch",
      complete: finalizeComplete,
    },
  ];
  const completedCount = stepsMeta.filter((s) => s.complete).length;
  const progressPct = Math.round((completedCount / stepsMeta.length) * 100);
  const toggleStep = (i: number) => setActiveStep((cur) => (cur === i ? -1 : i));

  const renderStepRightSlot = (key: string) => {
    if (key === "bookings") {
      if (previewResult) {
        return (
          <Badge
            variant="light"
            color={previewResult.valid ? "edr-green" : "red"}
            radius="sm"
          >
            {previewResult.valid ? "Plan valid" : "Has issues"}
          </Badge>
        );
      }
      return allSelectedIds.length ? (
        <Badge variant="light" color="edr-green" radius="sm">
          {allSelectedIds.length} selected
        </Badge>
      ) : null;
    }
    if (key === "wagon" && displayWagonPlan.length) {
      return (
        <Group gap="xs">
          {schedule.reverseWagonOrder ? (
            <Badge variant="light" color="orange" radius="sm">
              Reversed order
            </Badge>
          ) : null}
          <Badge variant="light" color="edr-green" radius="sm">
            {displayWagonPlan.length} wagons
          </Badge>
        </Group>
      );
    }
    if (key === "container" && containerUnits.length) {
      return (
        <Badge
          variant="light"
          color={containerComplete ? "edr-green" : "yellow"}
          radius="sm"
        >
          {containerUnits.length} units
        </Badge>
      );
    }
    if (key === "finalize") {
      return <StatusPill status={schedule.status} />;
    }
    return null;
  };

  const renderStepBody = (key: string) => {
    if (key === "bookings") {
      return (
        <Stack gap="md">
          <ScheduleBookingsStep
            assignedBookings={(schedule.bookings ?? []).map((b) => ({
              id: b.id,
              reference: b.reference ?? b.id.slice(0, 8),
              weightTons: b.weightTons,
            }))}
            eligibleItems={eligibleQuery.data?.items ?? []}
            eligibleLoading={eligibleQuery.isLoading}
            selectedIds={allSelectedIds}
            onSelectionChange={(ids) => {
              const assigned = new Set(assignedIds);
              setSelectedBookingIds(ids.filter((id) => !assigned.has(id)));
            }}
            assignedIds={assignedIds}
            freightType={freightType}
            canRemove={canModifyBookings}
            onRemove={handleUnassign}
          />

          {canEditBookings ? (
            <Group
              align="center"
              justify="space-between"
              wrap="wrap"
              gap="md"
              p="sm"
              style={{
                borderRadius: 12,
                background: "var(--mantine-color-gray-0)",
                border: "1px solid var(--mantine-color-gray-2)",
              }}
            >
              <Checkbox
                label="Force assign (bypass hold / overweight warnings)"
                checked={forceAssign}
                onChange={(e) => setForceAssign(e.currentTarget.checked)}
                size="sm"
              />
              <Button
                color="edr-green"
                radius="md"
                leftSection={<Eye size={16} />}
                loading={preview.isPending}
                onClick={() => void runPreview()}
              >
                Preview plan
              </Button>
            </Group>
          ) : null}

          {previewResult ? (
            <Stack gap="sm">
              <ScheduleWarningsAlert
                violations={previewResult.violations}
                warnings={previewResult.warnings}
              />
              <FleetAvailabilitySummary
                fleetAvailability={previewResult.fleetAvailability}
                deferredBookings={previewResult.deferredBookings}
              />
              <PreviewSummary summary={previewResult.summary} />
            </Stack>
          ) : null}
        </Stack>
      );
    }

    if (key === "wagon") {
      return (
        <Stack gap="md">
          {!displayWagonPlan.length && !previewResult ? (
            <Paper p="md" radius="lg" withBorder bg="gray.0">
              <Text size="sm" c="dimmed">
                Run a preview from the Bookings step to generate the wagon plan.
              </Text>
            </Paper>
          ) : null}
          <FleetAvailabilitySummary
            fleetAvailability={previewResult?.fleetAvailability}
            deferredBookings={previewResult?.deferredBookings}
          />
          {isExportDisplay && displayWagonPlanOriented.length ? (
            <Text size="xs" c="dimmed">
              Shown rear-first (export direction) — positions keep their original numbers.
            </Text>
          ) : null}
          <WagonPlanGrid wagonPlan={displayWagonPlanOriented} freightType={freightType} />
          {canEditBookings && (previewResult || displayWagonPlan.length) ? (
            <Group>
              {!hasContainerStep ? (
                <Button
                  color="edr-green"
                  radius="md"
                  loading={assign.isPending}
                  onClick={handleAssign}
                >
                  {assignedIds.length ? "Save assignments" : "Assign bookings"}
                </Button>
              ) : (
                <Button
                  color="edr-green"
                  radius="md"
                  rightSection={<ContainerIcon size={16} />}
                  onClick={() => setActiveStep(2)}
                >
                  Continue to containers
                </Button>
              )}
              <Button variant="default" radius="md" onClick={() => void runPreview()}>
                Refresh preview
              </Button>
            </Group>
          ) : null}
        </Stack>
      );
    }

    if (key === "container") {
      return (
        <Stack gap="md">
          {!containerUnits.length ? (
            <Paper p="md" radius="lg" withBorder bg="gray.0">
              <Text size="sm" c="dimmed">
                Run preview from the Bookings step to load container units for numbering.
              </Text>
            </Paper>
          ) : (
            <ContainerPlacementGrid
              units={containerUnits}
              containerSlots={containerSlots}
              placements={containerPlacements}
              onChange={setContainerPlacements}
            />
          )}
          {canEditBookings ? (
            <Group>
              <Button
                color="edr-green"
                radius="md"
                loading={assign.isPending}
                onClick={handleAssign}
              >
                {assignedIds.length ? "Save assignments" : "Assign bookings"}
              </Button>
              <Button
                variant="default"
                radius="md"
                onClick={() => setActiveStep(finalizeStep)}
              >
                Skip to finalize
              </Button>
            </Group>
          ) : null}
        </Stack>
      );
    }

    // finalize — the train is known here, so draw the full composition the
    // same way the batch board's composition tab does (interactive consist).
    return (
      <Stack gap="md">
        {schedule.trainSet ? (
          <TrainConsistView
            scheduleDetail={schedule}
            scheduleId={scheduleId ?? ""}
            maxWagons={schedule.maxWagons ?? 53}
          />
        ) : (
          <TrainCompositionDiagram
            locomotive={null}
            locomotives={locomotives}
            wagons={[]}
            freightType={freightType}
            trainNumber={schedule.trainNumber ?? schedule.train?.code ?? null}
            totalLengthMeters={null}
          />
        )}
        <Paper
          p="lg"
          radius="lg"
          withBorder
          style={{
            background: scheduleBrand.softSurface,
            borderColor: scheduleBrand.mutedBorder,
          }}
        >
          <Group gap="md" align="flex-start" wrap="nowrap">
            <ThemeIcon size={44} radius="md" variant="light" color="#F2A516">
              <CheckCircle2 size={22} />
            </ThemeIcon>
            <Stack gap={2}>
              <Text fw={600}>Ready to depart</Text>
              <Text size="sm" c="dimmed">
                Finalizing locks the plan and moves the schedule to{" "}
                <Text span fw={600} c="edr-green.7">
                  SCHEDULED
                </Text>
                . Dispatch then begins rail movement and notifies the yard.
              </Text>
            </Stack>
          </Group>
        </Paper>
        <Group>
          {canFinalize ? (
            <Button
              color="edr-green"
              size="md"
              radius="md"
              leftSection={<CheckCircle2 size={18} />}
              loading={finalize.isPending}
              onClick={async () => {
                try {
                  await finalize.mutateAsync(scheduleId);
                  toast({ title: "Schedule finalized" });
                } catch (err) {
                  toast({
                    title: "Finalize failed",
                    description: parseError(err, "Could not finalize"),
                    variant: "destructive",
                  });
                }
              }}
            >
              Finalize schedule
            </Button>
          ) : null}
          {canDispatch ? (
            <Button
              color="edr-green"
              size="md"
              radius="md"
              leftSection={<Send size={18} />}
              loading={dispatch.isPending}
              onClick={() => setDispatchConfirmOpen(true)}
            >
              Dispatch train
            </Button>
          ) : null}
          {!canFinalize && !canDispatch ? (
            <Text size="sm" c="dimmed">
              No actions available for this schedule status.
            </Text>
          ) : null}
        </Group>
      </Stack>
    );
  };

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

      <Paper
        radius="xl"
        p="xl"
        style={{ position: "relative", overflow: "hidden" }}
      >
        <Stack gap="lg" style={{ position: "relative" }}>
          <Group justify="space-between" align="flex-start" wrap="wrap">
            <Group gap="md" align="flex-start" wrap="nowrap">
              <ThemeIcon size={56} radius="lg" variant="light" color="#F2A516">
                <Train size={28} />
              </ThemeIcon>
              <Stack gap={6}>
                <Group gap="sm" align="center" wrap="wrap">
                  {schedule.reference ? (
                    <Badge
                      variant="filled"
                      color="edr-green"
                      radius="sm"
                      style={{ fontWeight: 700, fontFamily: "monospace" }}
                    >
                      {schedule.reference}
                    </Badge>
                  ) : null}
                  <Title order={2} fw={700} style={{ color: "#0f172a" }}>
                    {schedule.route?.name ?? "Train schedule"}
                  </Title>
                  {schedule.trainNumber ? (
                    <Badge variant="light" color="#F2A516" radius="sm" style={{ fontWeight: 600 }}>
                      {schedule.trainNumber}
                    </Badge>
                  ) : null}
                  {schedule.train ? (
                    <Text size="xs" c="dimmed" ff="monospace">
                      Train {schedule.train.code}
                    </Text>
                  ) : null}
                </Group>
                {(schedule.stops?.length ?? 0) >= 3 ||
                (schedule.bookings ?? []).some(
                  (b) => b.tradeDirection === "DOMESTIC",
                ) ? (
                  <SegmentOccupancyStrip
                    stops={schedule.stops ?? []}
                    bookings={schedule.bookings ?? []}
                    maxWagons={schedule.maxWagons}
                    maxGrossTons={schedule.maxGrossWeightTons}
                  />
                ) : (
                  <Box maw={340}>
                    <RouteCorridor
                      origin={
                        schedule.originStation?.label ?? schedule.originStation?.code
                      }
                      destination={
                        schedule.destinationStation?.label ??
                        schedule.destinationStation?.code
                      }
                    />
                  </Box>
                )}
                <Group gap="sm" align="center">
                  <FreightTypeBadge freightType={schedule.freightType} />
                  <StatusPill status={schedule.status} />
                </Group>
              </Stack>
            </Group>
            <Group gap="sm">
              {canPrintMarshalling ? (
                <Button
                  variant="light"
                  color="edr-green"
                  radius="lg"
                  size="sm"
                  leftSection={<FileText size={16} />}
                  loading={downloadMarshalling.isPending}
                  onClick={() => void openMarshallingDocument()}
                >
                  Marshalling PDF
                </Button>
              ) : null}
              {["DISPATCHED", "ARRIVED"].includes(schedule.status) ? (
                <Button
                  component={Link}
                  to={`/dashboard/operations/train-scheduling-v2/${scheduleId}/track`}
                  color="edr-green"
                  radius="lg"
                  size="sm"
                  leftSection={<Navigation size={16} />}
                >
                  Track train
                </Button>
              ) : null}
              {schedule.windowPhase === "PRE_WINDOW" ? (
                <Button
                  variant="light"
                  color="edr-green"
                  radius="lg"
                  size="sm"
                  leftSection={<Clock size={16} />}
                  onClick={() => setWindowSettingsOpen(true)}
                >
                  Window settings
                </Button>
              ) : null}
              {["DRAFT", "SCHEDULED"].includes(schedule.status) ? (
                <Button
                  variant="default"
                  radius="lg"
                  size="sm"
                  onClick={() => setMaintenanceOpen(true)}
                >
                  Reschedule train
                </Button>
              ) : null}
              {gatepassApplies ? (
                gatepassSecured ? (
                  <Button
                    variant="light"
                    color="edr-green"
                    radius="lg"
                    size="sm"
                    leftSection={<CheckCircle2 size={16} />}
                    disabled
                  >
                    Gate pass secured
                  </Button>
                ) : (
                  <Button
                    color="edr-green"
                    radius="lg"
                    size="sm"
                    leftSection={<FileText size={16} />}
                    loading={secureGatepass.isPending}
                    onClick={() => secureGatepass.mutate()}
                  >
                    Secure gate pass
                  </Button>
                )
              ) : null}
            </Group>
          </Group>

          {previewResult ? (
            <Badge
              size="lg"
              radius="sm"
              variant="light"
              color={previewResult.valid ? "edr-green" : "red"}
              leftSection={
                <Box
                  w={8}
                  h={8}
                  style={{
                    borderRadius: 999,
                    background: previewResult.valid
                      ? "var(--mantine-color-edr-green-6)"
                      : "var(--mantine-color-red-6)",
                  }}
                />
              }
            >
              Preview {previewResult.valid ? "valid" : "has issues"}
            </Badge>
          ) : null}
        </Stack>
      </Paper>

      <KpiStrip
        items={[
          ...(schedule.train
            ? [
                {
                  label: "Train",
                  value: schedule.train.code,
                  hint: schedule.train.trainName ?? "Built train (Train Builder)",
                  icon: Train,
                },
              ]
            : []),
          {
            label: locomotives.length > 1 ? "Locomotives" : "Locomotive",
            value: locomotives.length
              ? locomotives.map((l) => l.code).join(" + ")
              : "—",
            hint: locomotives.length
              ? `${locomotives.length} locomotive${locomotives.length > 1 ? "s" : ""}`
              : "No locomotives assigned",
            icon: Train,
          },
          {
            label: "Bookings",
            value: schedule.bookings?.length ?? 0,
            hint: (() => {
              const intercity = (schedule.bookings ?? []).filter(
                (b) => b.tradeDirection === "DOMESTIC",
              ).length;
              return intercity > 0
                ? `${intercity} intercity ride-along${intercity === 1 ? "" : "s"}`
                : undefined;
            })(),
            icon: Package,
          },
          {
            label: "Wagons / load",
            // Gross: cargo load + the tare of every wagon in the consist — the
            // weight the locomotive actually hauls.
            value: `${schedule.trainSet?.wagonCount ?? displayWagonPlan.length} · ${
              Math.round(
                ((schedule.trainSet?.totalWeightTons ?? 0) +
                  (schedule.trainSet?.wagons ?? []).reduce(
                    (sum, w) => sum + (Number(w.tareWeightTons) || 0),
                    0,
                  )) *
                  100,
              ) / 100
            }T`,
            hint: "gross · wagon tare + cargo",
            icon: Weight,
          },
          {
            label: "Departure",
            value: new Date(schedule.scheduledDepartureDate).toLocaleDateString("en", {
              month: "short",
              day: "2-digit",
            }),
            hint: new Date(schedule.scheduledDepartureDate).toLocaleTimeString("en", {
              hour: "2-digit",
              minute: "2-digit",
            }),
            icon: CalendarClock,
          },
        ]}
      />

      {/* Import loading confirmation — superseded by the per-booking Load/Unload
          toggle in the Workspace tab (works for all directions). Kept commented
          in case the import-only confirmation flow is needed again.
      {schedule?.direction === "IMPORT" ? (
        <Paper radius="xl" p="lg" withBorder>
          <Stack gap="md">
            <Text fw={600}>Import loading confirmation</Text>
            <Text size="sm" c="dimmed">
              Paid import bookings with a wagon allocated on this schedule. Marking loaded/unloaded
              is tracking only — it does not block dispatch.
            </Text>
            <ImportLoadingConfirmationPanel
              scheduleId={scheduleId as string}
              items={importLoadingQuery.data?.items ?? []}
              isLoading={importLoadingQuery.isLoading}
            />
          </Stack>
        </Paper>
      ) : null}
      */}

      <Tabs defaultValue="workflow" radius="md" color="edr-green" keepMounted={false}>
        <Tabs.List mb="md">
          <Tabs.Tab value="workflow" leftSection={<WorkflowIcon size={16} />}>
            Workflow
          </Tabs.Tab>
          <Tabs.Tab value="workspace" leftSection={<PackageCheck size={16} />}>
            Workspace
          </Tabs.Tab>
        </Tabs.List>

        <Tabs.Panel value="workflow">
          <Stack gap="lg">
      <Paper radius="xl" p="lg">
        <Stack gap="lg">
          {/* Workflow header with ring progress */}
          <Group justify="space-between" align="center" wrap="nowrap">
            <Group gap="md" align="center" wrap="nowrap">
              <ThemeIcon size={44} radius="md" variant="light" color="edr-green">
                <RouteIcon size={22} />
              </ThemeIcon>
              <Stack gap={2}>
                <Title order={4} fw={700}>
                  Scheduling workflow
                </Title>
                <Text size="sm" c="dimmed">
                  {completedCount} of {stepsMeta.length} steps complete · expand any
                  step to edit
                </Text>
              </Stack>
            </Group>
            <RingProgress
              size={64}
              thickness={6}
              roundCaps
              sections={[{ value: progressPct, color: "edr-green" }]}
              label={
                <Text ta="center" size="xs" fw={700} c="edr-green.7">
                  {progressPct}%
                </Text>
              }
            />
          </Group>

          <WorkflowRail>
            {stepsMeta.map((step, index) => (
              <WorkflowStep
                key={step.key}
                index={index}
                icon={step.icon}
                title={step.title}
                subtitle={step.subtitle}
                state={
                  activeStep === index
                    ? "active"
                    : step.complete
                      ? "complete"
                      : "upcoming"
                }
                open={activeStep === index}
                onToggle={() => toggleStep(index)}
                rightSlot={renderStepRightSlot(step.key)}
              >
                {renderStepBody(step.key)}
              </WorkflowStep>
            ))}
          </WorkflowRail>
        </Stack>
      </Paper>

            {/* <ScheduleBatchPanel schedule={schedule} /> */}
          </Stack>
        </Tabs.Panel>

        <Tabs.Panel value="workspace">
          <ScheduleWorkspacePanel
            schedule={schedule}
            onChanged={() => {
              autoPreviewedRef.current = false;
              void detailQuery.refetch();
            }}
          />
          {scheduleId ? <YardWorkPanel scheduleId={scheduleId} /> : null}
          {scheduleId ? (
            <IntercityRideAlongPanel
              scheduleId={scheduleId}
              direction={schedule.direction}
            />
          ) : null}
        </Tabs.Panel>
      </Tabs>

      {scheduleId ? (
        <RescheduleTrainDialog
          scheduleId={scheduleId}
          currentBookingIds={(schedule.bookings ?? []).map((b) => b.id)}
          opened={maintenanceOpen}
          onClose={() => setMaintenanceOpen(false)}
          onComplete={() => void detailQuery.refetch()}
        />
      ) : null}

      <BookingWindowSettingsModal
        scheduleId={scheduleId ?? null}
        opened={windowSettingsOpen}
        onClose={() => setWindowSettingsOpen(false)}
        onSaved={() => void detailQuery.refetch()}
      />

      <Modal
        opened={dispatchConfirmOpen}
        onClose={() => setDispatchConfirmOpen(false)}
        centered
        radius="lg"
        title={
          <Group gap={8}>
            <Send size={18} />
            <Text fw={700}>Dispatch this train?</Text>
          </Group>
        }
      >
        <Stack gap="md">
          <Text size="sm" c="dimmed">
            Dispatch locks the composition and begins rail movement. This cannot be
            undone.
          </Text>

          {hasDispatchWarnings ? (
            <Alert
              color="orange"
              variant="light"
              radius="md"
              icon={<AlertTriangle size={18} />}
              title="Some bookings are not fully ready"
            >
              <List size="sm" spacing={4}>
                {unassignedCount > 0 ? (
                  <List.Item>
                    <Text span fw={700}>
                      {unassignedCount}
                    </Text>{" "}
                    booking{unassignedCount === 1 ? "" : "s"} not assigned to a wagon
                  </List.Item>
                ) : null}
                {unloadedCount > 0 ? (
                  <List.Item>
                    <Text span fw={700}>
                      {unloadedCount}
                    </Text>{" "}
                    wagon-assigned booking{unloadedCount === 1 ? "" : "s"} not loaded
                    yet — mid-route boarders load from the track page when the train
                    reaches their yard
                  </List.Item>
                ) : null}
                {intercityNotLoadedCount > 0 ? (
                  <List.Item>
                    <Text span fw={700}>
                      {intercityNotLoadedCount}
                    </Text>{" "}
                    intercity ride-along{intercityNotLoadedCount === 1 ? "" : "s"} not
                    loaded yet — load them from the Workspace tab (Yard work) before
                    the train leaves their origin yard
                  </List.Item>
                ) : null}
              </List>
              <Text size="xs" c="dimmed" mt={6}>
                You can still dispatch — confirm to proceed.
              </Text>
            </Alert>
          ) : (
            <Alert
              color="edr-green"
              variant="light"
              radius="md"
              icon={<CheckCircle2 size={18} />}
            >
              All bookings are assigned to a wagon and marked loaded.
            </Alert>
          )}

          <Group justify="flex-end" gap="sm">
            <Button
              variant="default"
              onClick={() => setDispatchConfirmOpen(false)}
            >
              Cancel
            </Button>
            <Button
              color="edr-green"
              leftSection={<Send size={16} />}
              loading={dispatch.isPending}
              onClick={() => void runDispatch()}
            >
              {hasDispatchWarnings ? "Dispatch anyway" : "Dispatch train"}
            </Button>
          </Group>
        </Stack>
      </Modal>
    </PageContainer>
  );
}
