'use client';

import { useState, useEffect, useRef } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { Plus, Edit, Trash2, X, Search, Train, Save, GripVertical } from 'lucide-react';
import DataTable from '@/components/ui/DataTable';
import Badge from '@/components/ui/Badge';
import ActionButton from '@/components/ui/ActionButton';
import Modal from '@/components/ui/Modal';
import ConfirmDialog from '@/components/ui/ConfirmDialog';
import { routesApi } from '@/lib/api/routes';
import { stationsApi, fleetApi, routeCoachTemplatesApi } from '@/lib/api';
import { eatLocalToISO, isoToEATLocal } from '@/lib/timezone';

interface RouteStop {
  stationId: string;
  sequence: number;
  distanceKm?: number;
  distanceFromOrigin?: number;
  checkinMinutesBefore?: number;
  travelMinutesToStop?: number;
}

type Tab = 'routes' | 'coaches';

function RouteCoachesTab({ routes }: { routes: any[] }) {
  const queryClient = useQueryClient();
  const [selectedRouteId, setSelectedRouteId] = useState('');
  const [coachRows, setCoachRows] = useState<{ coachId: string; positionNumber: number }[]>([]);

  const { data: coaches } = useQuery({
    queryKey: ['coaches-all'],
    queryFn: () => fleetApi.getCoaches(),
  });

  const { data: template, isLoading: templateLoading } = useQuery({
    queryKey: ['route-coaches', selectedRouteId],
    queryFn: () => routeCoachTemplatesApi.get(selectedRouteId),
    enabled: !!selectedRouteId,
  });

  const saveMutation = useMutation({
    mutationFn: () => routeCoachTemplatesApi.set(selectedRouteId, coachRows),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['route-coaches', selectedRouteId] }),
  });

  const clearMutation = useMutation({
    mutationFn: () => routeCoachTemplatesApi.clear(selectedRouteId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['route-coaches', selectedRouteId] });
      setCoachRows([]);
    },
  });

  // Sync coachRows when template loads
  useEffect(() => {
    const rows: any[] = Array.isArray(template) ? template : (template as any)?.coaches ?? [];
    if (rows.length) setCoachRows(rows.map((r: any) => ({ coachId: r.coachId ?? r.coach?.id, positionNumber: r.positionNumber })));
  }, [template]);

  const allCoaches: any[] = (coaches as any)?.items ?? (Array.isArray(coaches) ? coaches : []);

  const addRow = () => setCoachRows([...coachRows, { coachId: '', positionNumber: coachRows.length + 1 }]);
  const removeRow = (i: number) => {
    const updated = coachRows.filter((_, idx) => idx !== i);
    setCoachRows(updated.map((r, idx) => ({ ...r, positionNumber: idx + 1 })));
  };
  const updateRow = (i: number, field: 'coachId', val: string) => {
    const updated = [...coachRows];
    updated[i] = { ...updated[i], [field]: val };
    setCoachRows(updated);
  };

  const selectedCoachIds = new Set(coachRows.map((r) => r.coachId).filter(Boolean));

  const handleCoachDragStart = (e: React.DragEvent, index: number) => {
    e.dataTransfer.setData('coach-index', index.toString());
  };
  const handleCoachDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    (e.currentTarget as HTMLElement).style.opacity = '0.5';
  };
  const handleCoachDragLeave = (e: React.DragEvent) => {
    (e.currentTarget as HTMLElement).style.opacity = '1';
  };
  const handleCoachDrop = (e: React.DragEvent, targetIndex: number) => {
    e.preventDefault();
    (e.currentTarget as HTMLElement).style.opacity = '1';
    const sourceIndex = parseInt(e.dataTransfer.getData('coach-index'));
    if (sourceIndex === targetIndex) return;
    const reordered = [...coachRows];
    const [moved] = reordered.splice(sourceIndex, 1);
    reordered.splice(targetIndex, 0, moved);
    setCoachRows(reordered.map((r, idx) => ({ ...r, positionNumber: idx + 1 })));
  };

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-4">
        <div className="flex-1">
          <label className="label">Select Route</label>
          <select className="input" value={selectedRouteId} onChange={(e) => { setSelectedRouteId(e.target.value); setCoachRows([]); }}>
            <option value="">— choose a route —</option>
            {routes.map((r: any) => <option key={r.id} value={r.id}>{r.name} ({r.code})</option>)}
          </select>
        </div>
      </div>

      {selectedRouteId && (
        <>
          {templateLoading ? (
            <p className="text-sm text-muted-foreground">Loading template…</p>
          ) : (
            <div className="space-y-2">
              {coachRows.length > 0 && (
                <p className="text-xs text-muted-foreground">Drag <GripVertical className="inline h-3 w-3" /> to reorder coaches</p>
              )}
              {coachRows.map((row, i) => (
                <div
                  key={i}
                  draggable
                  onDragStart={(e) => handleCoachDragStart(e, i)}
                  onDragOver={handleCoachDragOver}
                  onDragLeave={handleCoachDragLeave}
                  onDrop={(e) => handleCoachDrop(e, i)}
                  className="flex gap-2 items-center p-3 bg-muted/50 rounded cursor-move hover:bg-muted transition-colors"
                >
                  <GripVertical className="h-4 w-4 text-muted-foreground flex-shrink-0" />
                  <div className="w-8 text-center text-sm font-medium text-muted-foreground flex-shrink-0">
                    {row.positionNumber}
                  </div>
                  <div className="flex-1">
                    <select className="input input-sm" value={row.coachId} onChange={(e) => updateRow(i, 'coachId', e.target.value)}>
                      <option value="">Select Coach</option>
                      {allCoaches
                        .filter((c: any) => !selectedCoachIds.has(c.id) || c.id === row.coachId)
                        .map((c: any) => (
                          <option key={c.id} value={c.id}>{c.number} — {c.coachType?.name ?? c.type}</option>
                        ))}
                    </select>
                  </div>
                  <button type="button" onClick={() => removeRow(i)} className="p-1 text-destructive hover:bg-destructive/10 rounded flex-shrink-0">
                    <X className="h-4 w-4" />
                  </button>
                </div>
              ))}

              <div className="flex justify-between pt-2">
                <ActionButton type="button" variant="secondary" size="sm" icon={Plus} onClick={addRow}>Add Coach</ActionButton>
                <div className="flex gap-2">
                  {coachRows.length > 0 && (
                    <ActionButton type="button" variant="danger" size="sm" onClick={() => clearMutation.mutate()} loading={clearMutation.isPending}>
                      Clear
                    </ActionButton>
                  )}
                  <ActionButton type="button" size="sm" icon={Save} onClick={() => saveMutation.mutate()} loading={saveMutation.isPending}>
                    Save Template
                  </ActionButton>
                </div>
              </div>
            </div>
          )}
        </>
      )}
    </div>
  );
}

export default function RoutesPage() {
  const [activeTab, setActiveTab] = useState<Tab>('routes');
  const [showModal, setShowModal] = useState(false);
  const [editingRoute, setEditingRoute] = useState<any>(null);
  const [editLoading, setEditLoading] = useState(false);
  const [stops, setStops] = useState<RouteStop[]>([]);
  const [originStationId, setOriginStationId] = useState('');
  const [destinationStationId, setDestinationStationId] = useState('');
  const [destinationDistance, setDestinationDistance] = useState<number | undefined>(undefined);
  const [originCheckinMinutes, setOriginCheckinMinutes] = useState<number | undefined>(undefined);
  const [destinationCheckinMinutes, setDestinationCheckinMinutes] = useState<number | undefined>(undefined);
  const [destinationTravelMinutes, setDestinationTravelMinutes] = useState<number | undefined>(undefined);
  const [deleteConfirm, setDeleteConfirm] = useState<{ isOpen: boolean; route: any | null; error?: string; cascade?: boolean; cascadeChecked?: boolean }>({ isOpen: false, route: null });
  const [search, setSearch] = useState('');
  const [error, setError] = useState<string | null>(null);
  const errorBannerRef = useRef<HTMLDivElement>(null);

  // The form scrolls internally (long stop lists push the error banner above the fold), so a
  // submit failure can land silently off-screen with no visible indication anything went wrong.
  // Scroll the banner into view whenever a new error appears.
  useEffect(() => {
    if (error) errorBannerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }, [error]);
  const queryClient = useQueryClient();

  const { data: routes, isLoading: routesLoading } = useQuery({
    queryKey: ['routes'],
    queryFn: async () => {
      const result = await routesApi.getAll();
      return result;
    },
  });

  const { data: stations } = useQuery({
    queryKey: ['stations'],
    queryFn: stationsApi.getAll,
  });

  const createMutation = useMutation({
    mutationFn: routesApi.create,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['routes'] });
      setShowModal(false);
      setEditingRoute(null);
      setError(null);
    },
    onError: (e: any) => {
      const msg = e?.response?.data?.message || e?.message || 'Failed to create route';
      setError(Array.isArray(msg) ? msg.join(' ') : msg);
    },
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, data }: { id: string; data: any }) => routesApi.update(id, data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['routes'] });
      setShowModal(false);
      setEditingRoute(null);
      setError(null);
    },
    onError: (e: any) => {
      const msg = e?.response?.data?.message || e?.message || 'Failed to update route';
      setError(Array.isArray(msg) ? msg.join(' ') : msg);
    },
  });

  const deleteMutation = useMutation({
    mutationFn: ({ id, cascade }: { id: string; cascade?: boolean }) => routesApi.delete(id, cascade),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['routes'] });
    },
    onError: (e: any) => {
      const msg = e?.response?.data?.message || e?.message || 'Failed to delete route';
      const isFkError = msg?.includes('Cannot delete') || e?.response?.status === 400;
      if (isFkError && !deleteConfirm.cascade) {
        setDeleteConfirm(prev => ({ ...prev, cascade: true, cascadeChecked: false, error: Array.isArray(msg) ? msg.join(' ') : msg }));
      } else {
        setDeleteConfirm(prev => ({ ...prev, error: Array.isArray(msg) ? msg.join(' ') : msg }));
      }
    },
  });

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);

    if (!originStationId || !destinationStationId) {
      alert('Please select origin and destination stations');
      return;
    }

    if (originStationId === destinationStationId) {
      alert('Origin and destination must be different');
      return;
    }

    // Keep current stop order (already rearranged by user)
    const sortedMiddleStops = stops;

    // distanceKm = cumulative distance from origin (fare engine uses destStop.distanceKm - originStop.distanceKm)
    // travelMinutesToStop = minutes of travel from the PREVIOUS stop, used to estimate this
    // stop's arrival time. The origin (sequence 1) has no predecessor, so it gets none.
    const stopsArray = [
      { stationId: originStationId, sequence: 1, distanceKm: 0, checkinMinutesBefore: originCheckinMinutes ?? undefined },
      ...sortedMiddleStops.map((stop, idx) => ({
        stationId: stop.stationId,
        sequence: idx + 2,
        distanceKm: stop.distanceFromOrigin || 0,
        checkinMinutesBefore: stop.checkinMinutesBefore ?? undefined,
        travelMinutesToStop: stop.travelMinutesToStop ?? undefined,
      })),
      {
        stationId: destinationStationId,
        sequence: sortedMiddleStops.length + 2,
        distanceKm: destinationDistance || 0,
        checkinMinutesBefore: destinationCheckinMinutes ?? undefined,
        travelMinutesToStop: destinationTravelMinutes ?? undefined,
      },
    ];

    const checkinRaw = formData.get('checkinMinutesBefore') as string;
    const routeData = {
      code: formData.get('code') as string,
      name: formData.get('name') as string,
      description: formData.get('description') as string || undefined,
      active: !editingRoute ? (formData.get('active') !== 'false') : undefined,
      effectiveFrom: eatLocalToISO(formData.get('effectiveFrom') as string),
      // null (not undefined) so clearing the field on an edit explicitly clears effectiveUntil
      // server-side, instead of being silently dropped as "no change".
      effectiveUntil: formData.get('effectiveUntil') ? eatLocalToISO(formData.get('effectiveUntil') as string) : null,
      checkinMinutesBefore: checkinRaw ? parseInt(checkinRaw) : undefined,
      stops: stopsArray,
    };
    
    if (editingRoute) {
      await updateMutation.mutateAsync({ id: editingRoute.id, data: routeData });
    } else {
      await createMutation.mutateAsync(routeData);
    }
  };

  const addStop = () => {
    // distanceKm must be cumulative and strictly increasing (enforced server-side) — defaulting
    // every new stop to 0 made each one collide with the previous, so simply clicking "Add
    // Intermediate Stop" a few times and saving without hand-editing every distance always failed
    // validation. Default each new stop's distance a step past whatever precedes it instead.
    const lastDistance = stops.length > 0 ? (stops[stops.length - 1].distanceFromOrigin ?? 0) : 0;
    setStops([...stops, { stationId: '', sequence: stops.length + 1, distanceFromOrigin: lastDistance + 10 }]);
  };

  const removeStop = (index: number) => {
    setStops(stops.filter((_, i) => i !== index));
  };

  const updateStop = (index: number, field: keyof RouteStop, value: any) => {
    const updated = [...stops];
    updated[index] = { ...updated[index], [field]: value };
    setStops(updated);
  };

  const handleDragStart = (e: React.DragEvent, index: number) => {
    e.dataTransfer.setData('text/plain', index.toString());
  };

  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    (e.currentTarget as HTMLElement).style.opacity = '0.5';
  };

  const handleDragLeave = (e: React.DragEvent) => {
    (e.currentTarget as HTMLElement).style.opacity = '1';
  };

  const handleDrop = (e: React.DragEvent, targetIndex: number) => {
    e.preventDefault();
    (e.currentTarget as HTMLElement).style.opacity = '1';
    const sourceIndex = parseInt(e.dataTransfer.getData('text/plain'));
    if (sourceIndex === targetIndex) return;
    const newStops = [...stops];
    const [draggedStop] = newStops.splice(sourceIndex, 1);
    newStops.splice(targetIndex, 0, draggedStop);
    setStops(newStops);
  };

  const generateRouteCode = (originId: string, destId: string) => {
    if (!originId || !destId) return '';
    const origin = stations?.items?.find((s: any) => s.id === originId);
    const dest = stations?.items?.find((s: any) => s.id === destId);
    return origin && dest ? `${origin.code}-${dest.code}` : '';
  };

  const generateRouteName = (originId: string, destId: string) => {
    if (!originId || !destId) return '';
    const origin = stations?.items?.find((s: any) => s.id === originId);
    const dest = stations?.items?.find((s: any) => s.id === destId);
    return origin && dest ? `${origin.name} - ${dest.name}` : '';
  };

  const handleDelete = (route: any) => {
    setDeleteConfirm({ isOpen: true, route, error: undefined });
  };

  const confirmDelete = async () => {
    if (!deleteConfirm.route) return;
    try {
      await deleteMutation.mutateAsync({ id: deleteConfirm.route.id, cascade: deleteConfirm.cascade && deleteConfirm.cascadeChecked });
      setDeleteConfirm({ isOpen: false, route: null });
    } catch {
      // error is set by onError handler
    }
  };

  const routeColumns = [
    { key: 'code', label: 'Route Code', sortable: true },
    { key: 'name', label: 'Route Name', sortable: true },
    { key: 'description', label: 'Description', render: (route: any) => route.description || 'N/A' },
    {
      key: 'checkinMinutesBefore',
      label: 'Check-in Cutoff',
      render: (route: any) => `${route.checkinMinutesBefore ?? 30} min`,
    },
    {
      key: 'active',
      label: 'Status',
      render: (route: any) => (
        <Badge variant="status" status={route.active ? 'CONFIRMED' : 'CANCELLED'}>
          {route.active ? 'Active' : 'Inactive'}
        </Badge>
      ),
    },
  ];

  const filteredRoutes = (routes as any)?.items || (Array.isArray(routes) ? routes : []);
  const displayedRoutes = filteredRoutes.filter((route: any) => {
    if (!search) return true;
    const searchLower = search.toLowerCase();
    return (
      route.code?.toLowerCase().includes(searchLower) ||
      route.name?.toLowerCase().includes(searchLower) ||
      route.description?.toLowerCase().includes(searchLower)
    );
  });

  const openEditModal = async (route: any) => {
    setEditLoading(true);
    try {
      const full = await routesApi.getById(route.id) as any;
      const routeStops: any[] = full?.stops || [];
      setEditingRoute(full ?? route);
      if (routeStops.length >= 2) {
        const originStop = routeStops[0];
        const destStop   = routeStops[routeStops.length - 1];
        setOriginStationId(originStop.stationId);
        setOriginCheckinMinutes(originStop.checkinMinutesBefore ?? undefined);
        setDestinationStationId(destStop.stationId);
        setDestinationCheckinMinutes(destStop.checkinMinutesBefore ?? undefined);
        setDestinationDistance(destStop.distanceKm || 0);
        setDestinationTravelMinutes(destStop.travelMinutesToStop ?? undefined);
        setStops(routeStops.slice(1, -1).map((s: any) => ({
          stationId: s.stationId,
          sequence:  s.sequence,
          distanceKm: s.distanceKm,
          distanceFromOrigin: s.distanceKm || 0,
          checkinMinutesBefore: s.checkinMinutesBefore ?? undefined,
          travelMinutesToStop: s.travelMinutesToStop ?? undefined,
        })));
      }
      setError(null);
      setShowModal(true);
    } finally {
      setEditLoading(false);
    }
  };

  const routeActions = [
    {
      label: 'Edit',
      onClick: openEditModal,
      variant: 'secondary' as const,
      icon: Edit,
    },
    {
      label: 'Delete',
      onClick: handleDelete,
      variant: 'danger' as const,
      icon: Trash2,
    },
  ];

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold">Routes</h1>
          <p className="text-muted-foreground">Manage railway routes and coach templates</p>
        </div>
        {activeTab === 'routes' && (
          <ActionButton
            icon={Plus}
            onClick={() => {
              setEditingRoute(null);
              setOriginStationId('');
              setOriginCheckinMinutes(undefined);
              setDestinationStationId('');
              setDestinationCheckinMinutes(undefined);
              setDestinationDistance(undefined);
              setDestinationTravelMinutes(undefined);
              setStops([]);
              setError(null);
              setShowModal(true);
            }}
          >
            Add Route
          </ActionButton>
        )}
      </div>

      {/* Tabs */}
      <div className="flex gap-1 border-b">
        {(['routes', 'coaches'] as Tab[]).map((tab) => (
          <button
            key={tab}
            onClick={() => setActiveTab(tab)}
            className={`px-4 py-2 text-sm font-medium capitalize transition-colors border-b-2 -mb-px ${
              activeTab === tab
                ? 'border-primary text-primary'
                : 'border-transparent text-muted-foreground hover:text-foreground'
            }`}
          >
            {tab === 'coaches' ? 'Coach Templates' : 'Routes'}
          </button>
        ))}
      </div>

      {activeTab === 'routes' && (
        <>
          <div className="relative">
            <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
            <input
              type="text"
              placeholder="Search by code, name, or description..."
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              className="input pl-10 w-full"
            />
          </div>

          <DataTable
            data={displayedRoutes}
            columns={routeColumns}
            actions={routeActions}
            loading={routesLoading || editLoading}
            emptyMessage={search ? 'No routes match your search' : 'No routes found'}
          />
        </>
      )}

      {activeTab === 'coaches' && (
        <RouteCoachesTab routes={filteredRoutes} />
      )}

      <ConfirmDialog
        isOpen={deleteConfirm.isOpen}
        onClose={() => setDeleteConfirm({ isOpen: false, route: null })}
        onConfirm={confirmDelete}
        title="Delete Route"
        message={`Are you sure you want to delete ${deleteConfirm.route?.name}?`}
        confirmText="Delete"
        isDanger={true}
        isLoading={deleteMutation.isPending}
        error={deleteConfirm.error}
        warning={!deleteConfirm.cascade ? "This route may be referenced by schedules and bookings. Deleting it may impact these systems." : undefined}
        cascadeWarning={deleteConfirm.cascade ? "This route has related schedules that will also be permanently deleted." : undefined}
        cascadeChecked={deleteConfirm.cascadeChecked}
        onCascadeChange={(checked) => setDeleteConfirm(prev => ({ ...prev, cascadeChecked: checked }))}
      />

      <Modal
        isOpen={showModal}
        onClose={() => {
          setShowModal(false);
          setEditingRoute(null);
          setOriginStationId('');
          setOriginCheckinMinutes(undefined);
          setDestinationStationId('');
          setDestinationCheckinMinutes(undefined);
          setDestinationDistance(undefined);
          setDestinationTravelMinutes(undefined);
          setStops([]);
          setSearch('');
          setError(null);
        }}
        title={`${editingRoute ? 'Edit' : 'Add'} Route`}
        size="lg"
      >
        <form onSubmit={handleSubmit} className="space-y-4 max-h-[calc(100vh-200px)] overflow-y-auto">
          {error && (
            <div ref={errorBannerRef} className="bg-red-50 p-3 rounded-lg text-sm text-red-800">
              {error}
            </div>
          )}
          {editingRoute && (
            <div className="rounded-lg bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 p-3 text-sm text-yellow-800 dark:text-yellow-200">
              <p className="font-semibold">⚠ Warning</p>
              <p className="mt-1">Editing this route may impact schedules, trips, and bookings that reference it. Proceed with caution.</p>
            </div>
          )}
          <div className="grid grid-cols-2 gap-4">
            <div>
              <label className="label">Origin Station *</label>
              <select
                className="input"
                value={originStationId}
                onChange={(e) => setOriginStationId(e.target.value)}
                required
                disabled={!!editingRoute}
              >
                <option value="">Select Origin</option>
                {stations?.items?.map((station: any) => (
                  <option key={station.id} value={station.id}>
                    {station.name} ({station.code})
                  </option>
                ))}
              </select>
            </div>
            <div>
              <label className="label">Destination Station *</label>
              <select
                className="input"
                value={destinationStationId}
                onChange={(e) => setDestinationStationId(e.target.value)}
                required
                disabled={!!editingRoute}
              >
                <option value="">Select Destination</option>
                {stations?.items?.map((station: any) => (
                  <option key={station.id} value={station.id}>
                    {station.name} ({station.code})
                  </option>
                ))}
              </select>
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div>
              <label className="label">Route Code *</label>
              <input
                type="text"
                name="code"
                className="input"
                defaultValue={editingRoute ? editingRoute.code : undefined}
                key={editingRoute ? `code-edit-${editingRoute.id}` : `code-new-${originStationId}-${destinationStationId}`}
                placeholder={generateRouteCode(originStationId, destinationStationId) || 'e.g. ADD-DJI'}
                required
              />
              {!editingRoute && originStationId && destinationStationId && (
                <p className="text-xs text-muted-foreground mt-1">
                  Suggested: <button type="button" className="text-primary underline" onClick={(e) => { const inp = (e.currentTarget.closest('.grid')?.querySelector('input[name=code]') as HTMLInputElement); if (inp) inp.value = generateRouteCode(originStationId, destinationStationId); }}>{generateRouteCode(originStationId, destinationStationId)}</button>
                </p>
              )}
            </div>
            <div>
              <label className="label">Route Name *</label>
              <input
                type="text"
                name="name"
                className="input"
                defaultValue={editingRoute ? editingRoute.name : undefined}
                key={editingRoute ? `name-edit-${editingRoute.id}` : `name-new-${originStationId}-${destinationStationId}`}
                placeholder={generateRouteName(originStationId, destinationStationId) || 'e.g. Addis Ababa - Djibouti'}
                required
              />
              {!editingRoute && originStationId && destinationStationId && (
                <p className="text-xs text-muted-foreground mt-1">
                  Suggested: <button type="button" className="text-primary underline" onClick={(e) => { const inp = (e.currentTarget.closest('.grid')?.querySelector('input[name=name]') as HTMLInputElement); if (inp) inp.value = generateRouteName(originStationId, destinationStationId); }}>{generateRouteName(originStationId, destinationStationId)}</button>
                </p>
              )}
            </div>
          </div>

          <div>
            <label className="label">Description</label>
            <textarea
              name="description"
              className="input"
              rows={2}
              defaultValue={editingRoute?.description}
              placeholder="Outbound local route from [Origin] to [Destination]"
            />
          </div>

          <div>
            <label className="label">Check-in Cutoff (minutes before departure)</label>
            <input
              type="number"
              name="checkinMinutesBefore"
              className="input"
              defaultValue={editingRoute?.checkinMinutesBefore ?? 30}
              min={1}
              max={480}
              step={1}
              required
            />
            <p className="text-xs text-muted-foreground mt-1">
              Booking closes and check-in ends this many minutes before each stop's departure. Default: 30.
            </p>
          </div>

          {!editingRoute && (
            <div>
              <label className="label">Status</label>
              <select name="active" className="input" defaultValue="true">
                <option value="true">Active</option>
                <option value="false">Inactive</option>
              </select>
            </div>
          )}

          <div className="grid grid-cols-2 gap-4">
            <div>
              <label className="label">Effective From *</label>
              <input
                type="datetime-local"
                name="effectiveFrom"
                className="input"
                defaultValue={editingRoute?.effectiveFrom ? isoToEATLocal(editingRoute.effectiveFrom) : isoToEATLocal(new Date())}
                required
              />
            </div>
            <div>
              <label className="label">Effective Until</label>
              <input
                type="datetime-local"
                name="effectiveUntil"
                className="input"
                defaultValue={editingRoute?.effectiveUntil ? isoToEATLocal(editingRoute.effectiveUntil) : ''}
              />
            </div>
          </div>

          <div className="border-t pt-4">
            <div className="flex items-center justify-between mb-3">
              <label className="label mb-0">Route Stops</label>
              <span className="text-xs text-muted-foreground">Drag to rearrange · <span className="font-medium">Travel min</span> estimates arrival from the previous stop (falls back to distance if blank) · <span className="font-medium">Cutoff min</span> overrides route check-in window per stop (leave blank to inherit)</span>
            </div>

            <div className="space-y-2">
              <div className="flex gap-2 items-center p-3 bg-primary/10 rounded border-2 border-primary">
                <div className="flex-shrink-0 w-8 h-8 bg-primary text-primary-foreground rounded-full flex items-center justify-center text-sm font-medium">
                  1
                </div>
                <div className="flex-1 font-medium">
                  {originStationId ? (
                    <span>
                      {stations?.items?.find((s: any) => s.id === originStationId)?.name || 'Unknown'}
                      {' '}({stations?.items?.find((s: any) => s.id === originStationId)?.code || 'N/A'})
                    </span>
                  ) : (
                    <span className="text-muted-foreground">Select origin station above</span>
                  )}
                </div>
                <div className="w-28 flex-shrink-0">
                  <input
                    type="number"
                    className="input input-sm"
                    placeholder="cutoff min"
                    value={originCheckinMinutes ?? ''}
                    onChange={(e) => setOriginCheckinMinutes(e.target.value ? parseInt(e.target.value) : undefined)}
                    min={1}
                    title="Check-in cutoff override (minutes) for this stop"
                  />
                </div>
                <div className="text-sm text-muted-foreground w-12 text-right flex-shrink-0">0 km</div>
              </div>

              {stops.map((stop, index) => (
                <div
                  key={index}
                  draggable
                  onDragStart={(e) => handleDragStart(e, index)}
                  onDragOver={handleDragOver}
                  onDragLeave={handleDragLeave}
                  onDrop={(e) => handleDrop(e, index)}
                  className="flex gap-2 items-center p-3 bg-muted/50 rounded cursor-move hover:bg-muted transition-colors"
                >
                  <div className="flex-shrink-0 w-8 h-8 bg-secondary text-secondary-foreground rounded-full flex items-center justify-center text-sm font-medium">
                    {index + 2}
                  </div>
                  <div className="flex-1">
                    <select
                      className="input input-sm"
                      value={stop.stationId}
                      onChange={(e) => updateStop(index, 'stationId', e.target.value)}
                      required
                    >
                      <option value="">Select Station</option>
                      {stations?.items?.filter((s: any) =>
                        s.id !== originStationId &&
                        s.id !== destinationStationId &&
                        !stops.some((st, idx) => idx !== index && st.stationId === s.id)
                      ).map((station: any) => (
                        <option key={station.id} value={station.id}>
                          {station.name} ({station.code})
                        </option>
                      ))}
                    </select>
                  </div>
                  <div className="w-28">
                    <input
                      type="number"
                      className="input input-sm"
                      placeholder="km"
                      value={stop.distanceFromOrigin || ''}
                      onChange={(e) => updateStop(index, 'distanceFromOrigin', e.target.value ? parseFloat(e.target.value) : undefined)}
                      min="0"
                      step="0.1"
                      required
                    />
                  </div>
                  <div className="w-28">
                    <input
                      type="number"
                      className="input input-sm"
                      placeholder="travel min"
                      value={stop.travelMinutesToStop ?? ''}
                      onChange={(e) => updateStop(index, 'travelMinutesToStop', e.target.value ? parseInt(e.target.value) : undefined)}
                      min={1}
                      title="Travel time in minutes from the previous stop, used to estimate this stop's arrival time"
                    />
                  </div>
                  <div className="w-28">
                    <input
                      type="number"
                      className="input input-sm"
                      placeholder="cutoff min"
                      value={stop.checkinMinutesBefore ?? ''}
                      onChange={(e) => updateStop(index, 'checkinMinutesBefore', e.target.value ? parseInt(e.target.value) : undefined)}
                      min={1}
                      title="Check-in cutoff override (minutes) for this stop"
                    />
                  </div>
                  <button
                    type="button"
                    onClick={() => removeStop(index)}
                    className="flex-shrink-0 p-1 text-destructive hover:bg-destructive/10 rounded"
                  >
                    <X className="h-4 w-4" />
                  </button>
                </div>
              ))}

              {originStationId && destinationStationId && (
                <div className="flex justify-center py-2">
                  <ActionButton
                    type="button"
                    variant="secondary"
                    size="sm"
                    icon={Plus}
                    onClick={addStop}
                  >
                    Add Intermediate Stop
                  </ActionButton>
                </div>
              )}

              <div className="flex gap-2 items-center p-3 bg-primary/10 rounded border-2 border-primary">
                <div className="flex-shrink-0 w-8 h-8 bg-primary text-primary-foreground rounded-full flex items-center justify-center text-sm font-medium">
                  {stops.length + 2}
                </div>
                <div className="flex-1 font-medium">
                  {destinationStationId ? (
                    <span>
                      {stations?.items?.find((s: any) => s.id === destinationStationId)?.name || 'Unknown'}
                      {' '}({stations?.items?.find((s: any) => s.id === destinationStationId)?.code || 'N/A'})
                    </span>
                  ) : (
                    <span className="text-muted-foreground">Select destination station above</span>
                  )}
                </div>
                <div className="w-28">
                  {destinationStationId && (
                    <input
                      type="number"
                      className="input input-sm"
                      placeholder="cutoff min"
                      value={destinationCheckinMinutes ?? ''}
                      onChange={(e) => setDestinationCheckinMinutes(e.target.value ? parseInt(e.target.value) : undefined)}
                      min={1}
                      title="Check-in cutoff override (minutes) for this stop"
                    />
                  )}
                </div>
                <div className="w-28">
                  {destinationStationId && (
                    <input
                      type="number"
                      className="input input-sm"
                      placeholder="km"
                      value={destinationDistance || ''}
                      onChange={(e) => setDestinationDistance(e.target.value ? parseFloat(e.target.value) : undefined)}
                      min="0"
                      step="0.1"
                      required
                    />
                  )}
                </div>
                <div className="w-28">
                  {destinationStationId && (
                    <input
                      type="number"
                      className="input input-sm"
                      placeholder="travel min"
                      value={destinationTravelMinutes ?? ''}
                      onChange={(e) => setDestinationTravelMinutes(e.target.value ? parseInt(e.target.value) : undefined)}
                      min={1}
                      title="Travel time in minutes from the previous stop, used to estimate this stop's arrival time"
                    />
                  )}
                </div>
              </div>
            </div>
          </div>

          <div className="flex justify-end gap-2 pt-4">
            <ActionButton
              type="button"
              variant="secondary"
              onClick={() => {
                setShowModal(false);
                setEditingRoute(null);
                setOriginStationId('');
                setOriginCheckinMinutes(undefined);
                setDestinationStationId('');
                setDestinationCheckinMinutes(undefined);
                setDestinationDistance(undefined);
                setDestinationTravelMinutes(undefined);
                setStops([]);
                setSearch('');
                setError(null);
              }}
            >
              Cancel
            </ActionButton>
            <ActionButton
              type="submit"
              loading={createMutation.isPending || updateMutation.isPending}
            >
              {editingRoute ? 'Update' : 'Create'} Route
            </ActionButton>
          </div>
        </form>
      </Modal>
    </div>
  );
}
