'use client';

import { useState, useEffect, useRef } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Plus, Loader2, Zap, Trash2, Edit, Search, X, GripVertical, RefreshCw } from 'lucide-react';
import DataTable from '@/components/ui/DataTable';
import ActionButton from '@/components/ui/ActionButton';
import Modal from '@/components/ui/Modal';
import ConfirmDialog from '@/components/ui/ConfirmDialog';
import { apiClient } from '@/lib/api-client';
import { routeCoachTemplatesApi } from '@/lib/api';
import Pagination from '@/components/ui/Pagination';
import { usePagination } from '@/lib/use-pagination';
import { formatDateTime } from '@/lib/utils';
import { eatLocalToISO, isoToEATLocal } from '@/lib/timezone';
import DateTimePicker from '@/components/ui/DateTimePicker';

interface Schedule {
  id: string;
  trainId: string;
  routeId: string;
  departureAt: string;
  arrivalAt: string;
  status: string;
  stopsCount: number;
  train?: { id: string; name: string; number: string };
  originStation?: { id: string; name: string };
  destinationStation?: { id: string; name: string };
  coachAssignments?: Array<{ coachId: string; positionNumber: number; coach?: { id: string; number: string } }>;
  isPackageOnly?: boolean;
}

interface Train {
  id: string;
  name: string;
  number: string;
}

interface Route {
  id: string;
  name: string;
  code: string;
}

interface Coach {
  id: string;
  number: string;
  coachNumber?: string;
  capacity: number;
  sequence?: number;
  coachType?: { name: string };
}

export default function SchedulesPage() {
  const [showModal, setShowModal] = useState(false);
  const [showAddModal, setShowAddModal] = useState(false);
  const [showEditModal, setShowEditModal] = useState(false);
  const [editingSchedule, setEditingSchedule] = useState<Schedule | null>(null);
  const [selectedSchedules, setSelectedSchedules] = useState<Set<string>>(new Set());
  const [deleteConfirm, setDeleteConfirm] = useState<{ isOpen: boolean; item: any | null; isBulk?: boolean; error?: string; cascade?: boolean; cascadeChecked?: boolean }>(
    { isOpen: false, item: null }
  );
  const [error, setError] = useState<string | null>(null);
  const errorBannerRef = useRef<HTMLDivElement>(null);
  const queryClient = useQueryClient();

  // These modals can scroll internally — a submit failure can land silently off-screen with no
  // visible indication anything went wrong. Scroll the banner into view when a new error appears.
  useEffect(() => {
    if (error) errorBannerRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }, [error]);

  const [bulkForm, setBulkForm] = useState({
    trainId: '',
    routeId: '',
    startDateTime: '',
    durationHours: '10',
    repeatEveryDays: '2',
    forNextDays: '15',
  });

  const [bulkCoachRows, setBulkCoachRows] = useState<{ coachId: string; positionNumber: number }[]>([]);

  const [addForm, setAddForm] = useState({ trainId: '', routeId: '', departureAt: '', arrivalAt: '' });
  const [addCoachRows, setAddCoachRows] = useState<{ coachId: string; positionNumber: number }[]>([]);

  const { data: singleRouteTemplate, isLoading: singleTemplateLoading } = useQuery({
    queryKey: ['route-coaches', addForm.routeId],
    queryFn: () => routeCoachTemplatesApi.get(addForm.routeId),
    enabled: !!addForm.routeId,
  });

  useEffect(() => {
    if (!addForm.routeId) { setAddCoachRows([]); return; }
    const rows: any[] = Array.isArray(singleRouteTemplate) ? singleRouteTemplate : (singleRouteTemplate as any)?.coaches ?? [];
    setAddCoachRows(rows.length ? rows.map((r: any) => ({ coachId: r.coachId ?? r.coach?.id, positionNumber: r.positionNumber })) : []);
  }, [singleRouteTemplate, addForm.routeId]);

  // Fetch route coach template when route changes
  const { data: routeTemplate, isLoading: templateLoading } = useQuery({
    queryKey: ['route-coaches', bulkForm.routeId],
    queryFn: () => routeCoachTemplatesApi.get(bulkForm.routeId),
    enabled: !!bulkForm.routeId,
  });

  useEffect(() => {
    if (!bulkForm.routeId) { setBulkCoachRows([]); return; }
    const rows: any[] = Array.isArray(routeTemplate) ? routeTemplate : (routeTemplate as any)?.coaches ?? [];
    setBulkCoachRows(
      rows.length
        ? rows.map((r: any) => ({ coachId: r.coachId ?? r.coach?.id, positionNumber: r.positionNumber }))
        : []
    );
  }, [routeTemplate, bulkForm.routeId]);

  const [editForm, setEditForm] = useState({
    departureAt: '',
    arrivalAt: '',
    status: 'SCHEDULED',
    coachIds: [] as string[],
    isPackageOnly: false,
  });

  const [filters, setFilters] = useState({
    search: '',
    trainId: '',
    routeId: '',
    date: '',
  });

  const { data: schedulesData, isLoading: schedulesLoading } = useQuery({
    queryKey: ['schedules', filters],
    queryFn: () => {
      const params = new URLSearchParams();
      if (filters.trainId) params.append('trainId', filters.trainId);
      if (filters.routeId) params.append('routeId', filters.routeId);
      if (filters.date) params.append('date', filters.date);
      return apiClient.get<Schedule[]>(`/schedules?${params.toString()}`);
    },
    retry: 1,
  });

  const { data: trainsData } = useQuery({
    queryKey: ['trains'],
    queryFn: () => apiClient.get<Train[]>('/fleet/trains'),
    retry: 1,
  });

  const { data: routesData } = useQuery({
    queryKey: ['routes'],
    queryFn: () => apiClient.get<Route[]>('/routes'),
    retry: 1,
  });

  const { data: coachesData } = useQuery({
    queryKey: ['coaches'],
    queryFn: () => apiClient.get<Coach[]>('/fleet/coaches'),
    retry: 1,
  });

  const bulkGenerateMutation = useMutation({
    mutationFn: (data: any) => apiClient.post('/schedules/bulk-generate', data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['schedules'] });
      setShowModal(false);
      setBulkForm({
        trainId: '',
        routeId: '',
        startDateTime: '',
        durationHours: '12',
        repeatEveryDays: '1',
        forNextDays: '30',
      });
      setBulkCoachRows([]);
      setError(null);
    },
    onError: (err: any) => {
      const msg = err.response?.data?.message || 'Failed to generate schedules';
      setError(Array.isArray(msg) ? msg.join(' ') : msg);
    },
  });

  const createScheduleMutation = useMutation({
    mutationFn: (data: any) => apiClient.post('/schedules', data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['schedules'] });
      setShowAddModal(false);
      setAddForm({ trainId: '', routeId: '', departureAt: '', arrivalAt: '' });
      setAddCoachRows([]);
      setError(null);
    },
    onError: (err: any) => {
      const msg = err.response?.data?.message || 'Failed to create schedule';
      setError(Array.isArray(msg) ? msg.join(' ') : msg);
    },
  });

  const updateScheduleMutation = useMutation({
    mutationFn: (data: { id: string; payload: any }) =>
      apiClient.patch(`/schedules/${data.id}`, data.payload),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['schedules'] });
      setShowEditModal(false);
      setEditingSchedule(null);
      setError(null);
    },
    onError: (err: any) => {
      const msg = err.response?.data?.message || 'Failed to update schedule';
      setError(Array.isArray(msg) ? msg.join(' ') : msg);
    },
  });

  const recalculateStopsMutation = useMutation({
    mutationFn: (id: string) => apiClient.post(`/schedules/${id}/recalculate-stops`, {}),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['schedules'] });
    },
  });

  const deleteScheduleMutation = useMutation({
    mutationFn: ({ id, cascade }: { id: string; cascade?: boolean }) => apiClient.delete(`/schedules/${id}${cascade ? '?cascade=true' : ''}`),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['schedules'] });
    },
    onError: (err: any) => {
      const msg = err?.response?.data?.message || err?.message || 'Failed to delete schedule';
      const isFkError = msg?.includes('Cannot delete') || err?.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 bulkDeleteMutation = useMutation({
    mutationFn: async (ids: string[]) => {
      await Promise.all(ids.map(id => apiClient.delete(`/schedules/${id}`)));
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['schedules'] });
      setSelectedSchedules(new Set());
    },
    onError: (err: any) => {
      const msg = err?.response?.data?.message || err?.message || 'Failed to delete schedules';
      setDeleteConfirm(prev => ({ ...prev, error: Array.isArray(msg) ? msg.join(' ') : msg }));
    },
  });

  const handleBulkSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setError(null);

    if (!bulkForm.trainId || !bulkForm.routeId || !bulkForm.startDateTime) {
      setError('Train, route, and start date/time are required');
      return;
    }

    const payload: any = {
      trainId: bulkForm.trainId,
      routeId: bulkForm.routeId,
      startDateTime: eatLocalToISO(bulkForm.startDateTime),
      durationHours: parseInt(bulkForm.durationHours),
      repeatEveryDays: parseInt(bulkForm.repeatEveryDays),
      forNextDays: parseInt(bulkForm.forNextDays),
    };

    const validCoaches = bulkCoachRows.filter((r) => r.coachId);
    if (validCoaches.length > 0) {
      payload.coachIds = validCoaches.map((r) => r.coachId);
    }

    await bulkGenerateMutation.mutateAsync(payload);
  };

  const handleAddSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setError(null);
    const dep = new Date(eatLocalToISO(addForm.departureAt));
    const arr = new Date(eatLocalToISO(addForm.arrivalAt));
    if (arr <= dep) { setError('Arrival must be after departure'); return; }
    const validCoaches = addCoachRows.filter((r) => r.coachId);
    await createScheduleMutation.mutateAsync({
      trainId: addForm.trainId,
      routeId: addForm.routeId,
      departureAt: dep.toISOString(),
      arrivalAt: arr.toISOString(),
      ...(validCoaches.length > 0 && { coachIds: validCoaches.map((r) => r.coachId) }),
    });
  };

  const handleEditSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setError(null);

    if (!editingSchedule) return;

    if (!editForm.departureAt || !editForm.arrivalAt) {
      setError('Departure and arrival times are required');
      return;
    }
    if (new Date(eatLocalToISO(editForm.arrivalAt)) <= new Date(eatLocalToISO(editForm.departureAt))) {
      setError('Arrival time must be after departure time');
      return;
    }

    const payload: any = {
      departureAt: eatLocalToISO(editForm.departureAt),
      arrivalAt: eatLocalToISO(editForm.arrivalAt),
      status: editForm.status,
      isPackageOnly: editForm.isPackageOnly,
      coaches: editForm.coachIds.map((coachId: string, idx: number) => ({
        coachId,
        positionNumber: idx + 1,
      })),
    };

    await updateScheduleMutation.mutateAsync({
      id: editingSchedule.id,
      payload,
    });
  };

  const handleDelete = (item: Schedule) => {
    setDeleteConfirm({ isOpen: true, item, isBulk: false });
  };

  const handleBulkDelete = () => {
    if (selectedSchedules.size === 0) return;
    setDeleteConfirm({ isOpen: true, item: Array.from(selectedSchedules), isBulk: true });
  };

  const confirmDelete = async () => {
    setDeleteConfirm(prev => ({ ...prev, error: undefined }));
    try {
      if (deleteConfirm.isBulk) {
        const ids = deleteConfirm.item as string[];
        await bulkDeleteMutation.mutateAsync(ids);
      } else if (deleteConfirm.item) {
        await deleteScheduleMutation.mutateAsync({ id: deleteConfirm.item.id, cascade: deleteConfirm.cascade && deleteConfirm.cascadeChecked });
      }
      setDeleteConfirm({ isOpen: false, item: null });
    } catch {
      // error is set by onError handler
    }
  };

  const handleEditClick = (schedule: Schedule) => {
    setEditingSchedule(schedule);
    setEditForm({
      departureAt: isoToEATLocal(schedule.departureAt),
      arrivalAt: isoToEATLocal(schedule.arrivalAt),
      status: schedule.status,
      coachIds: schedule.coachAssignments?.map((ca: any) => ca.coachId) || [],
      isPackageOnly: schedule.isPackageOnly ?? false,
    });
    setError(null);
    setShowEditModal(true);
  };

  const schedules = Array.isArray(schedulesData) ? schedulesData : (schedulesData as any)?.items || [];
  const trains = Array.isArray(trainsData) ? trainsData : (trainsData as any)?.items || [];
  const routes = Array.isArray(routesData) ? routesData : (routesData as any)?.items || [];
  const coaches = Array.isArray(coachesData) ? coachesData : (coachesData as any)?.items || [];

  const filteredSchedules = schedules.filter((schedule: Schedule) => {
    if (!filters.search) return true;
    const search = filters.search.toLowerCase();
    return (
      schedule.train?.name.toLowerCase().includes(search) ||
      schedule.train?.number.toLowerCase().includes(search) ||
      schedule.originStation?.name.toLowerCase().includes(search) ||
      schedule.destinationStation?.name.toLowerCase().includes(search) ||
      schedule.status.toLowerCase().includes(search)
    );
  });

  const { paged: pagedSchedules, page: schedulePage, totalPages: scheduleTotalPages, setPage: setSchedulePage } = usePagination(filteredSchedules as Schedule[], 20);

  const statusMap: Record<string, string> = {
    SCHEDULED: 'edr-badge-info',
    BOARDING: 'edr-badge-warning',
    EN_ROUTE: 'edr-badge-success',
    ARRIVED: 'edr-badge-secondary',
    CANCELLED: 'edr-badge-danger',
  };

  const scheduleColumns = [
    {
      key: 'checkbox',
      label: (
        <input
          type="checkbox"
          checked={selectedSchedules.size === filteredSchedules.length && filteredSchedules.length > 0}
          onChange={(e) => {
            if (e.target.checked) {
              setSelectedSchedules(new Set(filteredSchedules.map((s: Schedule) => s.id)));
            } else {
              setSelectedSchedules(new Set());
            }
          }}
          className="rounded"
        />
      ),
      render: (schedule: Schedule) => (
        <input
          type="checkbox"
          checked={selectedSchedules.has(schedule.id)}
          onChange={(e) => {
            const newSelected = new Set(selectedSchedules);
            if (e.target.checked) {
              newSelected.add(schedule.id);
            } else {
              newSelected.delete(schedule.id);
            }
            setSelectedSchedules(newSelected);
          }}
          className="rounded"
        />
      ),
    },
    {
      key: 'train.name',
      label: 'Train',
      sortable: true,
      render: (schedule: Schedule) => (
        <div className="font-medium font-mono">
          {schedule.train?.number}
        </div>
      ),
    },
    {
      key: 'route',
      label: 'Route',
      sortable: true,
      render: (schedule: Schedule) => (
        <div className="flex items-center gap-2">
          <span className="text-sm font-medium">
            {schedule.originStation?.name || 'Unknown'}
          </span>
          <span className="text-muted-foreground">→</span>
          <span className="text-sm font-medium">
            {schedule.destinationStation?.name || 'Unknown'}
          </span>
        </div>
      ),
    },
    {
      key: 'departureAt',
      label: 'Departure',
      sortable: true,
      render: (schedule: Schedule) => (
        <span className="font-mono text-sm">{formatDateTime(schedule.departureAt)}</span>
      ),
    },
    {
      key: 'arrivalAt',
      label: 'Arrival',
      sortable: true,
      render: (schedule: Schedule) => (
        <span className="font-mono text-sm">{formatDateTime(schedule.arrivalAt)}</span>
      ),
    },
    {
      key: 'coachAssignments',
      label: 'Coaches',
      render: (schedule: Schedule) => (
        <span className="text-sm font-medium">
          {schedule.coachAssignments?.length || 0}
        </span>
      ),
    },
    {
      key: 'status',
      label: 'Status',
      render: (schedule: Schedule) => (
        <div className="flex items-center gap-2">
          <span className={`edr-badge ${statusMap[schedule.status] || 'edr-badge-info'}`}>
            {schedule.status}
          </span>
          {schedule.isPackageOnly && (
            <span className="edr-badge edr-badge-warning">PKG</span>
          )}
        </div>
      ),
    },
  ] as any;

  const cancelScheduleMutation = useMutation({
    mutationFn: (id: string) => apiClient.patch(`/schedules/${id}/status`, { status: 'CANCELLED' }),
    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['schedules'] }),
  });

  const [cancelConfirm, setCancelConfirm] = useState<{ isOpen: boolean; item: Schedule | null }>({ isOpen: false, item: null });

  const scheduleActions = [
    {
      label: 'Edit',
      onClick: handleEditClick,
      variant: 'secondary' as const,
      icon: Edit,
    },
    {
      label: 'Cancel',
      onClick: (schedule: Schedule) => setCancelConfirm({ isOpen: true, item: schedule }),
      variant: 'danger' as const,
      icon: X,
      hidden: (schedule: Schedule) => schedule.status === 'CANCELLED',
    },
    {
      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-3xl font-bold text-foreground">Schedule Management</h1>
          <p className="text-muted-foreground mt-1">Create and manage train schedules</p>
        </div>
        <div className="flex gap-2">
          {selectedSchedules.size > 0 && (
            <ActionButton
              onClick={handleBulkDelete}
              variant="danger"
              loading={bulkDeleteMutation.isPending}
            >
              Delete {selectedSchedules.size} Schedule{selectedSchedules.size !== 1 ? 's' : ''}
            </ActionButton>
          )}
          <ActionButton
            icon={Plus}
            variant="secondary"
            onClick={() => { setError(null); setShowAddModal(true); }}
          >
            Add Schedule
          </ActionButton>
          <ActionButton
            icon={Zap}
            onClick={() => {
              setError(null);
              setShowModal(true);
            }}
          >
            Bulk Generate
          </ActionButton>
        </div>
      </div>

      <div className="card">
        <div className="mb-6 p-4 border-b border-border">
          <div className="space-y-4">
            <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 train name, number, station, or status..."
                value={filters.search}
                onChange={(e) => setFilters({ ...filters, search: e.target.value })}
                className="input pl-10 w-full"
              />
            </div>

            <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
              <div>
                <label className="label text-sm">Train</label>
                <select
                  value={filters.trainId}
                  onChange={(e) => setFilters({ ...filters, trainId: e.target.value })}
                  className="input"
                >
                  <option value="">All Trains</option>
                  {trains.map((train: Train) => (
                    <option key={train.id} value={train.id}>
                      {train.name} ({train.number})
                    </option>
                  ))}
                </select>
              </div>

              <div>
                <label className="label text-sm">Route</label>
                <select
                  value={filters.routeId}
                  onChange={(e) => setFilters({ ...filters, routeId: e.target.value })}
                  className="input"
                >
                  <option value="">All Routes</option>
                  {routes.map((route: Route) => (
                    <option key={route.id} value={route.id}>
                      {route.name} ({route.code})
                    </option>
                  ))}
                </select>
              </div>

              <div>
                <label className="label text-sm">Date</label>
                <input
                  type="date"
                  value={filters.date}
                  onChange={(e) => setFilters({ ...filters, date: e.target.value })}
                  className="input"
                />
              </div>

              <div className="flex items-end">
                <ActionButton
                  variant="secondary"
                  onClick={() => setFilters({ search: '', trainId: '', routeId: '', date: '' })}
                >
                  Clear Filters
                </ActionButton>
              </div>
            </div>
          </div>
        </div>

        <div className="pt-6">
          {schedulesLoading ? (
            <div className="flex items-center justify-center py-8">
              <Loader2 className="h-6 w-6 animate-spin" />
            </div>
          ) : filteredSchedules.length === 0 ? (
            <div className="text-center py-8 text-muted-foreground">
              No schedules found. {filters.search && 'Try adjusting your search.'}
            </div>
          ) : (
            <>
              <DataTable
                columns={scheduleColumns}
                data={pagedSchedules}
                actions={scheduleActions}
                loading={false}
                emptyMessage="No schedules found."
              />
              <Pagination currentPage={schedulePage} totalPages={scheduleTotalPages} onPageChange={setSchedulePage} />
            </>
          )}
        </div>
      </div>

      <ConfirmDialog
        isOpen={cancelConfirm.isOpen}
        onClose={() => setCancelConfirm({ isOpen: false, item: null })}
        onConfirm={async () => {
          if (cancelConfirm.item) {
            await cancelScheduleMutation.mutateAsync(cancelConfirm.item.id);
            setCancelConfirm({ isOpen: false, item: null });
          }
        }}
        title="Cancel Schedule"
        message={`Cancel the schedule departing ${cancelConfirm.item ? formatDateTime(cancelConfirm.item.departureAt) : ''}? Passengers with bookings will need to be notified separately.`}
        confirmText="Cancel Schedule"
        isDanger={true}
        isLoading={cancelScheduleMutation.isPending}
      />

      <ConfirmDialog
        isOpen={deleteConfirm.isOpen}
        onClose={() => setDeleteConfirm({ isOpen: false, item: null })}
        onConfirm={confirmDelete}
        title={deleteConfirm.isBulk ? 'Delete Multiple Schedules' : 'Delete Schedule'}
        message={
          deleteConfirm.isBulk
            ? `Are you sure you want to delete ${Array.isArray(deleteConfirm.item) ? deleteConfirm.item.length : 0} schedule(s)? This action cannot be undone.`
            : `Are you sure you want to delete this schedule departing on ${
                deleteConfirm.item ? formatDateTime(deleteConfirm.item.departureAt) : ''
              }?`
        }
        confirmText="Delete"
        isDanger={true}
        isLoading={deleteScheduleMutation.isPending || bulkDeleteMutation.isPending}
        error={deleteConfirm.error}
        warning={!deleteConfirm.cascade ? "Schedules with existing bookings cannot be deleted." : undefined}
        cascadeWarning={deleteConfirm.cascade ? "This schedule has related bookings or tickets that will also be permanently deleted." : undefined}
        cascadeChecked={deleteConfirm.cascadeChecked}
        onCascadeChange={(checked) => setDeleteConfirm(prev => ({ ...prev, cascadeChecked: checked }))}
      />

      <Modal
        isOpen={showAddModal}
        onClose={() => { setShowAddModal(false); setAddForm({ trainId: '', routeId: '', departureAt: '', arrivalAt: '' }); setAddCoachRows([]); setError(null); }}
        title="Add Schedule"
        size="xl"
      >
        <form onSubmit={handleAddSubmit} className="space-y-4">
          {error && <div ref={errorBannerRef} className="bg-red-50 p-3 rounded-lg text-sm text-red-800">{error}</div>}

          <div className="grid grid-cols-2 gap-4">
            <div>
              <label className="label">Train *</label>
              <select className="input" value={addForm.trainId} onChange={(e) => setAddForm({ ...addForm, trainId: e.target.value })} required>
                <option value="">Select Train</option>
                {trains.map((t: Train) => <option key={t.id} value={t.id}>{t.number} ({t.name})</option>)}
              </select>
            </div>
            <div>
              <label className="label">Route *</label>
              <select className="input" value={addForm.routeId} onChange={(e) => setAddForm({ ...addForm, routeId: e.target.value })} required>
                <option value="">Select Route</option>
                {routes.map((r: Route) => <option key={r.id} value={r.id}>{r.code} ({r.name})</option>)}
              </select>
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <DateTimePicker
              label="Departure *"
              value={addForm.departureAt}
              onChange={(v) => setAddForm({ ...addForm, departureAt: v })}
              required
            />
            <DateTimePicker
              label="Arrival *"
              value={addForm.arrivalAt}
              onChange={(v) => setAddForm({ ...addForm, arrivalAt: v })}
              required
            />
          </div>

          <div className="border-t pt-4">
            <div className="flex items-center justify-between mb-2">
              <label className="label mb-0">Coaches</label>
              <div className="flex items-center gap-3">
                {singleTemplateLoading && addForm.routeId && (
                  <span className="text-xs text-muted-foreground flex items-center gap-1"><Loader2 className="h-3 w-3 animate-spin" /> Loading template…</span>
                )}
                {!addForm.routeId && <span className="text-xs text-muted-foreground">Select a route to load its coach template</span>}
                <ActionButton type="button" variant="secondary" size="sm" icon={Plus}
                  disabled={addCoachRows.filter(r => r.coachId).length >= coaches.length}
                  onClick={() => setAddCoachRows([...addCoachRows, { coachId: '', positionNumber: addCoachRows.length + 1 }])}>
                  Add Coach
                </ActionButton>
              </div>
            </div>
            {addCoachRows.length === 0 ? (
              <p className="text-sm text-muted-foreground py-2">No coaches assigned.</p>
            ) : (
              <div className="space-y-2">
                {addCoachRows.length > 1 && <p className="text-xs text-muted-foreground">Drag <GripVertical className="inline h-3 w-3" /> to reorder</p>}
                {addCoachRows.map((row, i) => {
                  const selectedIds = new Set(addCoachRows.map((r) => r.coachId).filter(Boolean));
                  return (
                    <div key={i} draggable
                      onDragStart={(e) => e.dataTransfer.setData('add-coach-idx', i.toString())}
                      onDragOver={(e) => { e.preventDefault(); (e.currentTarget as HTMLElement).style.opacity = '0.5'; }}
                      onDragLeave={(e) => { (e.currentTarget as HTMLElement).style.opacity = '1'; }}
                      onDrop={(e) => {
                        e.preventDefault(); (e.currentTarget as HTMLElement).style.opacity = '1';
                        const src = parseInt(e.dataTransfer.getData('add-coach-idx'));
                        if (src === i) return;
                        const reordered = [...addCoachRows];
                        const [moved] = reordered.splice(src, 1);
                        reordered.splice(i, 0, moved);
                        setAddCoachRows(reordered.map((r, idx) => ({ ...r, positionNumber: idx + 1 })));
                      }}
                      className="flex gap-2 items-center p-2 bg-muted/50 rounded cursor-move hover:bg-muted transition-colors"
                    >
                      <GripVertical className="h-4 w-4 text-muted-foreground flex-shrink-0" />
                      <span className="w-6 text-center text-xs text-muted-foreground flex-shrink-0">{row.positionNumber}</span>
                      <select className="input input-sm flex-1" value={row.coachId}
                        onChange={(e) => { const u = [...addCoachRows]; u[i] = { ...u[i], coachId: e.target.value }; setAddCoachRows(u); }}>
                        <option value="">Select Coach</option>
                        {coaches.filter((c: Coach) => !selectedIds.has(c.id) || c.id === row.coachId).map((c: Coach) => (
                          <option key={c.id} value={c.id}>{c.number || c.coachNumber} — {c.coachType?.name} (Cap: {c.capacity})</option>
                        ))}
                      </select>
                      <button type="button" onClick={() => setAddCoachRows(addCoachRows.filter((_, idx) => idx !== i).map((r, idx) => ({ ...r, positionNumber: idx + 1 })))} className="p-1 text-destructive hover:bg-destructive/10 rounded flex-shrink-0">
                        <X className="h-4 w-4" />
                      </button>
                    </div>
                  );
                })}
              </div>
            )}
          </div>

          <div className="flex justify-end gap-2 pt-4">
            <ActionButton type="button" variant="secondary" onClick={() => { setShowAddModal(false); setAddForm({ trainId: '', routeId: '', departureAt: '', arrivalAt: '' }); setAddCoachRows([]); setError(null); }}>Cancel</ActionButton>
            <ActionButton type="submit" loading={createScheduleMutation.isPending}>Create Schedule</ActionButton>
          </div>
        </form>
      </Modal>

      <Modal
        isOpen={showModal}
        onClose={() => {
          setShowModal(false);
          setError(null);
          setBulkForm({
            trainId: '',
            routeId: '',
            startDateTime: '',
            durationHours: '12',
            repeatEveryDays: '1',
            forNextDays: '30',
          });
          setBulkCoachRows([]);
        }}
        title="Bulk Generate Schedules"
        size="lg"
      >
        <form onSubmit={handleBulkSubmit} className="space-y-4">
          {error && (
            <div ref={errorBannerRef} className="bg-red-50 p-3 rounded-lg text-sm text-red-800">
              {error}
            </div>
          )}

          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <div>
              <label className="label">Train *</label>
              <select
                value={bulkForm.trainId}
                onChange={(e) => setBulkForm({ ...bulkForm, trainId: e.target.value })}
                className="input"
                required
              >
                <option value="">Select Train</option>
                {trains.map((train: Train) => (
                  <option key={train.id} value={train.id}>
                    {train.number} ({train.name})
                  </option>
                ))}
              </select>
            </div>

            <div>
              <label className="label">Route *</label>
              <select
                value={bulkForm.routeId}
                onChange={(e) => setBulkForm({ ...bulkForm, routeId: e.target.value })}
                className="input"
                required
              >
                <option value="">Select Route</option>
                {routes.map((route: Route) => (
                  <option key={route.id} value={route.id}>
                    {route.code} ({route.name})
                  </option>
                ))}
              </select>
            </div>
          </div>

          <DateTimePicker
            label="Departure Date & Time *"
            value={bulkForm.startDateTime}
            onChange={(v) => setBulkForm({ ...bulkForm, startDateTime: v })}
            required
          />

          <div className="grid grid-cols-3 gap-4">
            <div>
              <label className="label">Duration (Hours)</label>
              <input
                type="number"
                min="1"
                placeholder={bulkForm.durationHours}
                onChange={(e) => setBulkForm({ ...bulkForm, durationHours: e.target.value })}
                className="input"
              />
            </div>

            <div>
              <label className="label">Repeat Every (Days)</label>
              <input
                type="number"
                min="1"
                placeholder={bulkForm.repeatEveryDays}
                onChange={(e) => setBulkForm({ ...bulkForm, repeatEveryDays: e.target.value })}
                className="input"
              />
            </div>

            <div>
              <label className="label">For Next (Days)</label>
              <input
                type="number"
                min="1"
                placeholder={bulkForm.forNextDays}
                onChange={(e) => setBulkForm({ ...bulkForm, forNextDays: e.target.value })}
                className="input"
              />
            </div>
          </div>

          <div className="border-t pt-4">
            <div className="flex items-center justify-between mb-2">
              <label className="label mb-0">Coaches</label>
              <div className="flex items-center gap-3">
                {templateLoading && bulkForm.routeId && (
                  <span className="text-xs text-muted-foreground flex items-center gap-1"><Loader2 className="h-3 w-3 animate-spin" /> Loading template…</span>
                )}
                {!bulkForm.routeId && (
                  <span className="text-xs text-muted-foreground">Select a route to load its coach template</span>
                )}
                <ActionButton type="button" variant="secondary" size="sm" icon={Plus}
                  disabled={bulkCoachRows.filter(r => r.coachId).length >= coaches.length}
                  onClick={() => setBulkCoachRows([...bulkCoachRows, { coachId: '', positionNumber: bulkCoachRows.length + 1 }])}>
                  Add Coach
                </ActionButton>
              </div>
            </div>

            {bulkCoachRows.length === 0 ? (
              <p className="text-sm text-muted-foreground py-2">No coaches assigned — schedules will be created without coach assignments.</p>
            ) : (
              <div className="space-y-2">
                {bulkCoachRows.length > 1 && (
                  <p className="text-xs text-muted-foreground">Drag <GripVertical className="inline h-3 w-3" /> to reorder</p>
                )}
                {bulkCoachRows.map((row, i) => {
                  const selectedIds = new Set(bulkCoachRows.map((r) => r.coachId).filter(Boolean));
                  return (
                    <div
                      key={i}
                      draggable
                      onDragStart={(e) => e.dataTransfer.setData('bulk-coach-idx', i.toString())}
                      onDragOver={(e) => { e.preventDefault(); (e.currentTarget as HTMLElement).style.opacity = '0.5'; }}
                      onDragLeave={(e) => { (e.currentTarget as HTMLElement).style.opacity = '1'; }}
                      onDrop={(e) => {
                        e.preventDefault();
                        (e.currentTarget as HTMLElement).style.opacity = '1';
                        const src = parseInt(e.dataTransfer.getData('bulk-coach-idx'));
                        if (src === i) return;
                        const reordered = [...bulkCoachRows];
                        const [moved] = reordered.splice(src, 1);
                        reordered.splice(i, 0, moved);
                        setBulkCoachRows(reordered.map((r, idx) => ({ ...r, positionNumber: idx + 1 })));
                      }}
                      className="flex gap-2 items-center p-2 bg-muted/50 rounded cursor-move hover:bg-muted transition-colors"
                    >
                      <GripVertical className="h-4 w-4 text-muted-foreground flex-shrink-0" />
                      <span className="w-6 text-center text-xs text-muted-foreground flex-shrink-0">{row.positionNumber}</span>
                      <select
                        className="input input-sm flex-1"
                        value={row.coachId}
                        onChange={(e) => {
                          const updated = [...bulkCoachRows];
                          updated[i] = { ...updated[i], coachId: e.target.value };
                          setBulkCoachRows(updated);
                        }}
                      >
                        <option value="">Select Coach</option>
                        {coaches
                          .filter((c: Coach) => !selectedIds.has(c.id) || c.id === row.coachId)
                          .map((c: Coach) => (
                            <option key={c.id} value={c.id}>
                              {c.number || c.coachNumber} — {c.coachType?.name} (Cap: {c.capacity})
                            </option>
                          ))}
                      </select>
                      <button
                        type="button"
                        onClick={() => setBulkCoachRows(bulkCoachRows.filter((_, idx) => idx !== i).map((r, idx) => ({ ...r, positionNumber: idx + 1 })))}
                        className="p-1 text-destructive hover:bg-destructive/10 rounded flex-shrink-0"
                      >
                        <X className="h-4 w-4" />
                      </button>
                    </div>
                  );
                })}
              </div>
            )}
          </div>

          <div className="bg-blue-50 p-4 rounded-lg">
            <p className="text-sm text-blue-900">
              <strong>Preview:</strong> Will create approximately{' '}
              <strong>{Math.ceil(parseInt(bulkForm.forNextDays) / parseInt(bulkForm.repeatEveryDays))}</strong>{' '}
              schedules, starting from the specified date, repeating every{' '}
              <strong>{bulkForm.repeatEveryDays}</strong> days for the next{' '}
              <strong>{bulkForm.forNextDays}</strong> days.
              {bulkCoachRows.filter(r => r.coachId).length > 0 && (
                <>
                  {' '}
                  Each schedule will have <strong>{bulkCoachRows.filter(r => r.coachId).length}</strong> coach(es) assigned.
                </>
              )}
            </p>
          </div>

          <div className="flex justify-end gap-2 pt-4">
            <ActionButton
              type="button"
              variant="secondary"
              onClick={() => {
                setShowModal(false);
                setError(null);
                setBulkForm({
                  trainId: '',
                  routeId: '',
                  startDateTime: '',
                  durationHours: '12',
                  repeatEveryDays: '1',
                  forNextDays: '30',
                });
                setBulkCoachRows([]);
              }}
            >
              Cancel
            </ActionButton>
            <ActionButton type="submit" loading={bulkGenerateMutation.isPending}>
              Generate Schedules
            </ActionButton>
          </div>
        </form>
      </Modal>

      <Modal
        isOpen={showEditModal}
        onClose={() => {
          setShowEditModal(false);
          setEditingSchedule(null);
          setError(null);
        }}
        title={`Edit Schedule: ${editingSchedule?.originStation?.name ?? ''} → ${editingSchedule?.destinationStation?.name ?? ''}`}
        size="xl"
      >
        {editingSchedule && (
          <form onSubmit={handleEditSubmit} className="space-y-4">
            {error && (
              <div ref={errorBannerRef} className="bg-red-50 p-3 rounded-lg text-sm text-red-800">
                {error}
              </div>
            )}

            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <DateTimePicker
                label="Departure Date & Time *"
                value={editForm.departureAt}
                onChange={(v) => setEditForm({ ...editForm, departureAt: v })}
                required
              />
              <DateTimePicker
                label="Arrival Date & Time *"
                value={editForm.arrivalAt}
                onChange={(v) => setEditForm({ ...editForm, arrivalAt: v })}
                required
              />
            </div>

            <div>
              <label className="label">Status</label>
              <select
                value={editForm.status}
                onChange={(e) => setEditForm({ ...editForm, status: e.target.value })}
                className="input"
              >
                <option value="SCHEDULED">Scheduled</option>
                <option value="BOARDING">Boarding</option>
                <option value="EN_ROUTE">En Route</option>
                <option value="ARRIVED">Arrived</option>
                <option value="CANCELLED">Cancelled</option>
              </select>
            </div>

            <div className="flex items-center gap-3 p-3 rounded-lg border border-border">
              <input
                type="checkbox"
                id="isPackageOnly"
                checked={editForm.isPackageOnly}
                onChange={(e) => setEditForm({ ...editForm, isPackageOnly: e.target.checked })}
                className="w-4 h-4 rounded"
              />
              <label htmlFor="isPackageOnly" className="text-sm cursor-pointer">
                <span className="font-medium">Package Only</span>
                <span className="block text-xs text-muted-foreground">Hide from public search — reserved for package bookings</span>
              </label>
            </div>

            <div>
              <div className="flex items-center justify-between mb-2">
                <label className="label">Coaches (Optional)</label>
                <button
                  type="button"
                  onClick={() => {
                    if (editForm.coachIds.length === coaches.length) {
                      setEditForm({ ...editForm, coachIds: [] });
                    } else {
                      setEditForm({ ...editForm, coachIds: coaches.map((c: Coach) => c.id) });
                    }
                  }}
                  className="text-xs text-primary hover:underline"
                >
                  {editForm.coachIds.length === coaches.length ? 'Deselect All' : 'Select All'}
                </button>
              </div>
              <div className="border border-border rounded-lg p-3 max-h-64 overflow-y-auto space-y-2">
                {coaches.length === 0 ? (
                  <p className="text-sm text-muted-foreground">No coaches available</p>
                ) : (
                  coaches.map((coach: Coach) => (
                    <label key={coach.id} className="flex items-center gap-2 cursor-pointer">
                      <input
                        type="checkbox"
                        checked={editForm.coachIds.includes(coach.id)}
                        onChange={(e) => {
                          if (e.target.checked) {
                            setEditForm({
                              ...editForm,
                              coachIds: [...editForm.coachIds, coach.id],
                            });
                          } else {
                            setEditForm({
                              ...editForm,
                              coachIds: editForm.coachIds.filter((id) => id !== coach.id),
                            });
                          }
                        }}
                        className="rounded"
                      />
                      <span className="text-sm">
                        {coach.sequence || 'N/A'} - {coach.number || coach.coachNumber} - {coach.coachType?.name} (Cap: {coach.capacity})
                      </span>
                    </label>
                  ))
                )}
              </div>
            </div>

            <div className="flex justify-end gap-2 pt-4">
              <ActionButton
                type="button"
                variant="secondary"
                onClick={() => {
                  setShowEditModal(false);
                  setEditingSchedule(null);
                  setError(null);
                }}
              >
                Cancel
              </ActionButton>
              <ActionButton
                type="button"
                variant="secondary"
                icon={RefreshCw}
                loading={recalculateStopsMutation.isPending}
                onClick={() => editingSchedule && recalculateStopsMutation.mutate(editingSchedule.id)}
              >
                Recalculate Stop Times
              </ActionButton>
              <ActionButton type="submit" loading={updateScheduleMutation.isPending}>
                Update Schedule
              </ActionButton>
            </div>
          </form>
        )}
      </Modal>
    </div>
  );
}
