import { useState, useMemo, useCallback, ReactNode } from "react";
import { Head } from '@inertiajs/react';
import { useQuery, useQueryClient } from "@tanstack/react-query";
import AdminLayout from '@/layouts/AdminLayout';
import { useAuth } from "@/hooks/useAuth";
import {
  format, addWeeks, subWeeks, startOfWeek, endOfWeek, addDays, eachDayOfInterval, isToday,
  startOfMonth, endOfMonth, addMonths, subMonths, isWeekend,
} from "date-fns";
import { ChevronLeft, ChevronRight, Users, MapPin, Clock, CheckCircle2, XCircle, GripVertical, AlertTriangle, CalendarDays, Pencil, ExternalLink } from "lucide-react";
import { useBankHolidays } from "@/hooks/useBankHolidays";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Calendar as CalendarPicker } from "@/components/ui/calendar";
import { cn } from "@/lib/utils";
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription,
} from "@/components/ui/dialog";
import { toast } from "sonner";
import { grossCents } from "@/lib/vat";
import EditDelegateDialog from "@/components/admin/EditDelegateDialog";
import { useCourseAvailability } from "@/hooks/useCourseAvailability";

const csrfToken = () =>
  (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? '';

interface BookingWithDetails {
  id: string;
  course_id: string;
  trainer_id: string;
  start_date: string;
  status: string;
  duration_override: number | null;
  courses: { title: string; days: number; capacity: number | null } | null;
  trainers: { first_name: string; last_name: string } | null;
}

interface OrderWithDetails {
  id: string;
  course_id: string;
  trainer_id: string | null;
  venue_id: string | null;
  start_date: string;
  status: string;
  customer_name: string;
  customer_email: string;
  num_delegates: number;
  price_cents: number;
  company_id: string | null;
  courses: { title: string; days: number; slug: string } | null;
  venues: { name: string; city: string | null } | null;
  training_companies: { name: string } | null;
}

interface DragState {
  booking: BookingWithDetails;
  originDate: string;
}

interface RescheduleConfirmation {
  booking: BookingWithDetails;
  oldDate: string;
  newDate: string;
  affectedOrders: OrderWithDetails[];
}

const TrainingCalendar = () => {
  const { user, companyId, hasRole, isSysLevel } = useAuth();
  const queryClient = useQueryClient();
  const { data: bankHolidays = [] } = useBankHolidays();
  const isCompanyManager = hasRole("company_manager") && !!companyId;
  // A signed-in trainer (no sys/manager role) should only see their own
  // bookings on the calendar. We resolve their trainer record by email and
  // narrow the rendered trainer list to that one row.
  const isTrainerOnly = hasRole("company_trainer") && !isSysLevel();
  const canDrag = isSysLevel();

  const { data: myTrainer } = useQuery({
    queryKey: ["my-trainer-profile", user?.email],
    enabled: isTrainerOnly && !!user?.email,
    queryFn: async () => {
      const res = await fetch(`/api/admin/trainers/by-email?email=${encodeURIComponent(user!.email!)}`);
      if (!res.ok) return null;
      return res.json();
    },
  });

  const [currentWeekStart, setCurrentWeekStart] = useState(() =>
    startOfWeek(new Date(), { weekStartsOn: 1 })
  );
  // First load is always weekly; toggled via the Week/Month buttons.
  const [viewMode, setViewMode] = useState<"week" | "month">("week");
  const [currentMonthStart, setCurrentMonthStart] = useState(() => startOfMonth(new Date()));
  const [selectedBooking, setSelectedBooking] = useState<{
    bookingId: string;
    courseId: string;
    trainerId: string;
    courseTitle: string;
    trainerName: string;
    date: string;
    courseDays: number;
    courseCapacity: number | null;
    orders: OrderWithDetails[];
  } | null>(null);
  const [rescheduleDate, setRescheduleDate] = useState<Date | undefined>(undefined);
  const [showReschedulePicker, setShowReschedulePicker] = useState(false);

  // Availability for the booking open in the dialog — drives the Reschedule
  // picker so only days this booking's trainer can actually run are selectable.
  // The query stays idle until a booking is open (courseId is undefined).
  const { isDateAvailableForTrainer, isLoading: rescheduleAvailabilityLoading } = useCourseAvailability(
    selectedBooking?.courseId,
    selectedBooking?.courseDays ?? 1,
    "",
  );

  // Duration adjustment state
  const [durationEdit, setDurationEdit] = useState<{
    bookingId: string;
    courseTitle: string;
    currentDays: number;
    newDays: number;
  } | null>(null);
  const [isDurationSaving, setIsDurationSaving] = useState(false);

  // Drag state
  const [dragState, setDragState] = useState<DragState | null>(null);
  const [dropTargetDate, setDropTargetDate] = useState<string | null>(null);
  const [rescheduleConfirm, setRescheduleConfirm] = useState<RescheduleConfirmation | null>(null);
  const [isRescheduling, setIsRescheduling] = useState(false);
  const [editDelegate, setEditDelegate] = useState<{ delegate: any; orderId: string } | null>(null);

  const weekEnd = endOfWeek(currentWeekStart, { weekStartsOn: 1 });
  const weekDays = eachDayOfInterval({ start: currentWeekStart, end: addDays(currentWeekStart, 4) });

  // The set of days shown in the grid. Weekly = Mon–Fri of the current week.
  // Monthly = every weekday in the current month.
  const monthDays = useMemo(
    () => eachDayOfInterval({
      start: currentMonthStart,
      end: endOfMonth(currentMonthStart),
    }).filter((d) => !isWeekend(d)),
    [currentMonthStart],
  );
  const displayDays = viewMode === "week" ? weekDays : monthDays;
  const rangeStart = viewMode === "week" ? currentWeekStart : currentMonthStart;
  const rangeEnd = viewMode === "week" ? weekEnd : endOfMonth(currentMonthStart);
  const rangeKey = format(rangeStart, "yyyy-MM-dd");

  const { data: trainers } = useQuery({
    // Include myTrainer.id in the key so trainer-only sessions wait for the
    // by-email lookup before the trainers list is considered "ready" — keeps
    // every downstream slice (trainerIds, render loop, isTrainerAvailable)
    // narrowed to the signed-in trainer without re-fetching all the per-trainer
    // queries with the full set first.
    queryKey: ["calendar-trainers", companyId, isTrainerOnly ? (myTrainer?.id ?? "pending") : "all"],
    enabled: !isTrainerOnly || !!myTrainer,
    queryFn: async () => {
      const url = isCompanyManager && companyId
        ? `/api/admin/calendar/trainers?company_id=${companyId}`
        : `/api/admin/calendar/trainers`;
      const res = await fetch(url);
      if (!res.ok) return [];
      return res.json() as Promise<Array<{ id: string; first_name: string; last_name: string; availability_mode: string }>>;
    },
    select: (data) => isTrainerOnly && myTrainer
      ? data.filter((t) => t.id === myTrainer.id)
      : data,
  });

  const trainerIds = trainers?.map((t) => t.id) || [];

  // Fetch weekly availability for all trainers
  const { data: weeklyAvailability } = useQuery({
    queryKey: ["calendar-weekly-avail", trainerIds],
    queryFn: async () => {
      const params = new URLSearchParams();
      trainerIds.forEach((id) => params.append('trainer_ids[]', id));
      const res = await fetch(`/api/admin/calendar/weekly-availability?${params.toString()}`);
      if (!res.ok) return [];
      return res.json();
    },
    enabled: trainerIds.length > 0,
  });

  // Fetch overrides for all trainers
  const { data: availabilityOverrides } = useQuery({
    queryKey: ["calendar-avail-overrides", trainerIds],
    queryFn: async () => {
      const params = new URLSearchParams();
      trainerIds.forEach((id) => params.append('trainer_ids[]', id));
      const res = await fetch(`/api/admin/calendar/availability-overrides?${params.toString()}`);
      if (!res.ok) return [];
      return res.json();
    },
    enabled: trainerIds.length > 0,
  });

  // Check if a trainer is available on a given date
  const isTrainerAvailable = useCallback((trainerId: string, dateStr: string): { available: boolean; reason?: string; kind?: "not-scheduled" | "bank-holiday" | "leave" } => {
    const trainer = trainers?.find((t) => t.id === trainerId);
    if (!trainer) return { available: true };

    const mode = trainer.availability_mode || "weekly";

    // Check for explicit override on this date
    const override = availabilityOverrides?.find(
      (o: any) => o.trainer_id === trainerId && o.override_date === dateStr
    );

    if (mode === "specific_dates") {
      if (override?.is_available) return { available: true };
      if (override && !override.is_available) return { available: false, reason: override.reason || "Not available", kind: "leave" };
      return { available: false, reason: "Not scheduled", kind: "not-scheduled" };
    }

    // Weekly mode
    if (override) {
      return override.is_available
        ? { available: true }
        : { available: false, reason: override.reason || "Leave / Unavailable", kind: "leave" };
    }

    // Check weekly schedule
    const dayOfWeek = new Date(dateStr + "T00:00:00").getDay();
    const weeklyEntry = weeklyAvailability?.find(
      (w: any) => w.trainer_id === trainerId && w.day_of_week === dayOfWeek
    );
    if (weeklyEntry && !weeklyEntry.is_available) {
      return { available: false, reason: "Not scheduled", kind: "not-scheduled" };
    }

    // Check bank holidays
    if (bankHolidays.some((bh) => bh.date === dateStr)) {
      return { available: false, reason: "Bank Holiday", kind: "bank-holiday" };
    }

    return { available: true };
  }, [trainers, weeklyAvailability, availabilityOverrides, bankHolidays]);

  const { data: bookings } = useQuery({
    queryKey: ["calendar-bookings-week", viewMode, rangeKey],
    queryFn: async () => {
      // Pad the start back 7 days so multi-day courses that started in the
      // previous range still render their continuation cells in this one.
      const queryStart = format(addDays(rangeStart, -7), "yyyy-MM-dd");
      const params = new URLSearchParams({
        start: queryStart,
        end: format(rangeEnd, "yyyy-MM-dd"),
      });
      const res = await fetch(`/api/admin/calendar/bookings?${params.toString()}`);
      if (!res.ok) return [] as BookingWithDetails[];
      return res.json() as Promise<BookingWithDetails[]>;
    },
  });

  const { data: orders } = useQuery({
    queryKey: ["calendar-orders-week", viewMode, rangeKey],
    queryFn: async () => {
      const queryStart = format(addDays(rangeStart, -7), "yyyy-MM-dd");
      const params = new URLSearchParams({
        start: queryStart,
        end: format(rangeEnd, "yyyy-MM-dd"),
      });
      const res = await fetch(`/api/admin/calendar/orders?${params.toString()}`);
      if (!res.ok) return [] as OrderWithDetails[];
      return res.json() as Promise<OrderWithDetails[]>;
    },
  });

  // Fetch resource blocks for conflict warnings
  const { data: resourceBlocks } = useQuery({
    queryKey: ["calendar-resource-blocks", viewMode, rangeKey],
    queryFn: async () => {
      const params = new URLSearchParams({
        start: format(rangeStart, "yyyy-MM-dd"),
        end: format(rangeEnd, "yyyy-MM-dd"),
      });
      const res = await fetch(`/api/admin/calendar/resource-blocks?${params.toString()}`);
      if (!res.ok) return [];
      return res.json();
    },
  });

  const getVenueConflicts = (venueId: string | null, dateStr: string) => {
    if (!venueId || !resourceBlocks) return [];
    return resourceBlocks.filter((b: any) => b.venue_id === venueId && b.blocked_date === dateStr);
  };

  // Helper: get N working days starting from a date (skips weekends & bank holidays)
  const getWorkingDays = useCallback((startDate: string, numDays: number): string[] => {
    const days: string[] = [];
    let current = new Date(startDate + "T00:00:00");
    while (days.length < numDays) {
      const dateStr = format(current, "yyyy-MM-dd");
      const dayOfWeek = current.getDay();
      const isBankHol = bankHolidays.some((bh) => bh.date === dateStr);
      if (dayOfWeek !== 0 && dayOfWeek !== 6 && !isBankHol) {
        days.push(dateStr);
      }
      current = addDays(current, 1);
    }
    return days;
  }, [bankHolidays]);

  // Helper: effective days for a booking (respects duration_override)
  const getEffectiveDays = useCallback((b: BookingWithDetails) => b.duration_override ?? b.courses?.days ?? 1, []);

  // Only render bookings that have at least one delegate. Zero-delegate rows —
  // imported standalone schedule slots, or any leftover booking with no orders —
  // are hidden so the calendar reflects courses people are actually attending.
  // Delegate count is keyed on (course, start_date, trainer), matching the
  // per-tile count used below.
  const visibleBookings = useMemo(() => {
    if (!bookings) return bookings;
    return bookings.filter((b) => {
      const delegates = orders
        ?.filter((o) => o.course_id === b.course_id && o.start_date === b.start_date && o.trainer_id === b.trainer_id)
        .reduce((sum, o) => sum + o.num_delegates, 0) || 0;
      return delegates > 0;
    });
  }, [bookings, orders]);

  const trainerDayMap = useMemo(() => {
    const map: Record<string, Record<string, { booking: BookingWithDetails; occupiedDays: string[] }[]>> = {};
    trainers?.forEach((t) => { map[t.id] = {}; });

    visibleBookings?.forEach((b) => {
      if (!map[b.trainer_id]) map[b.trainer_id] = {};
      const courseDays = getEffectiveDays(b);
      const occupiedDays = getWorkingDays(b.start_date, courseDays);
      const effectiveStart = occupiedDays[0] || b.start_date;
      if (!map[b.trainer_id][effectiveStart]) map[b.trainer_id][effectiveStart] = [];
      map[b.trainer_id][effectiveStart].push({ booking: b, occupiedDays });
    });
    return map;
  }, [trainers, visibleBookings, getWorkingDays, getEffectiveDays]);

  const trainerOccupiedDates = useMemo(() => {
    const map: Record<string, Record<string, { courseTitle: string; courseId: string; startDate: string }>> = {};
    trainers?.forEach((t) => { map[t.id] = {}; });

    visibleBookings?.forEach((b) => {
      const courseDays = getEffectiveDays(b);
      const occupiedDays = getWorkingDays(b.start_date, courseDays);
      occupiedDays.forEach((occupiedDate) => {
        if (!map[b.trainer_id]) map[b.trainer_id] = {};
        map[b.trainer_id][occupiedDate] = {
          courseTitle: b.courses?.title || "Course",
          courseId: b.course_id,
          startDate: b.start_date,
        };
      });
    });
    return map;
  }, [trainers, visibleBookings, getWorkingDays, getEffectiveDays]);

  const getDelegateCount = (courseId: string, startDate: string, trainerId: string) => {
    return orders
      ?.filter((o) => o.course_id === courseId && o.start_date === startDate && o.trainer_id === trainerId)
      .reduce((sum, o) => sum + o.num_delegates, 0) || 0;
  };

  const handleCourseClick = (bookingId: string, courseId: string, trainerId: string, courseTitle: string, trainerName: string, startDate: string, courseDays: number, courseCapacity: number | null) => {
    if (dragState) return;
    const matchingOrders = orders?.filter(
      (o) => o.course_id === courseId && o.start_date === startDate
    ) || [];
    setSelectedBooking({
      bookingId,
      courseId,
      trainerId,
      courseTitle,
      trainerName,
      date: startDate,
      courseDays,
      courseCapacity,
      orders: matchingOrders,
    });
    setRescheduleDate(undefined);
    setShowReschedulePicker(false);
  };


  // Drag handlers
  const handleDragStart = useCallback((e: React.DragEvent, booking: BookingWithDetails) => {
    if (!canDrag) return;
    e.dataTransfer.effectAllowed = "move";
    e.dataTransfer.setData("text/plain", booking.id);
    setDragState({ booking, originDate: booking.start_date });
  }, [canDrag]);

  const handleDragOver = useCallback((e: React.DragEvent, dateStr: string, trainerId: string) => {
    if (!dragState) return;
    if (trainerId !== dragState.booking.trainer_id) return;
    if (dateStr === dragState.originDate) return;
    e.preventDefault();
    e.dataTransfer.dropEffect = "move";
    setDropTargetDate(dateStr);
  }, [dragState]);

  const handleDragLeave = useCallback(() => {
    setDropTargetDate(null);
  }, []);

  const handleDrop = useCallback((e: React.DragEvent, dateStr: string, trainerId: string) => {
    e.preventDefault();
    setDropTargetDate(null);
    if (!dragState || trainerId !== dragState.booking.trainer_id || dateStr === dragState.originDate) return;

    const affectedOrders = orders?.filter(
      (o) => o.course_id === dragState.booking.course_id &&
             o.start_date === dragState.booking.start_date &&
             o.trainer_id === dragState.booking.trainer_id &&
             ["paid", "confirmed"].includes(o.status)
    ) || [];

    setRescheduleConfirm({
      booking: dragState.booking,
      oldDate: dragState.originDate,
      newDate: dateStr,
      affectedOrders,
    });
    setDragState(null);
  }, [dragState, orders]);

  const handleDragEnd = useCallback(() => {
    setDragState(null);
    setDropTargetDate(null);
  }, []);

  const confirmReschedule = async () => {
    if (!rescheduleConfirm) return;
    setIsRescheduling(true);

    try {
      const res = await fetch('/api/admin/functions/reschedule-booking', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
          'X-Requested-With': 'XMLHttpRequest',
          'X-CSRF-TOKEN': csrfToken(),
        },
        body: JSON.stringify({
          booking_id: rescheduleConfirm.booking.id,
          new_start_date: rescheduleConfirm.newDate,
        }),
      });

      if (!res.ok) {
        const err = await res.json().catch(() => ({ error: 'Failed' }));
        throw new Error(err.error || 'Failed to reschedule');
      }
      const data = await res.json();
      if (data?.error) throw new Error(data.error);

      toast.success(
        `Course rescheduled successfully. ${data.affected_orders ?? 0} booking(s) updated, ${data.emails_sent ?? 0} notification(s) sent.`
      );

      queryClient.invalidateQueries({ queryKey: ["calendar-bookings-week"] });
      queryClient.invalidateQueries({ queryKey: ["calendar-orders-week"] });

      setRescheduleConfirm(null);
    } catch (error: any) {
      toast.error(`Failed to reschedule: ${error.message}`);
    } finally {
      setIsRescheduling(false);
    }
  };

  // Fetch delegates when a booking is selected
  const selectedOrderIds = selectedBooking?.orders.map((o) => o.id) || [];
  const { data: delegates } = useQuery({
    queryKey: ["calendar-delegates", selectedOrderIds],
    enabled: selectedOrderIds.length > 0,
    queryFn: async () => {
      const params = new URLSearchParams();
      selectedOrderIds.forEach((id) => params.append('order_ids[]', id));
      const res = await fetch(`/api/admin/calendar/delegates?${params.toString()}`);
      if (!res.ok) return [];
      return res.json();
    },
  });

  // Fetch delegates for reschedule confirmation
  const rescheduleOrderIds = rescheduleConfirm?.affectedOrders.map((o) => o.id) || [];
  const { data: rescheduleDelegates } = useQuery({
    queryKey: ["reschedule-delegates", rescheduleOrderIds],
    enabled: rescheduleOrderIds.length > 0,
    queryFn: async () => {
      const params = new URLSearchParams();
      rescheduleOrderIds.forEach((id) => params.append('order_ids[]', id));
      const res = await fetch(`/api/admin/calendar/delegates?${params.toString()}`);
      if (!res.ok) return [];
      return res.json();
    },
  });

  const { data: calendarSubmissions } = useQuery({
    queryKey: ["calendar-form-submissions", selectedOrderIds],
    enabled: selectedOrderIds.length > 0,
    queryFn: async () => {
      const params = new URLSearchParams();
      selectedOrderIds.forEach((id) => params.append('order_ids[]', id));
      const res = await fetch(`/api/admin/calendar/form-submissions?${params.toString()}`);
      if (!res.ok) return [];
      return res.json();
    },
  });

  const totalDelegates = selectedBooking?.orders.reduce((s, o) => s + o.num_delegates, 0) || 0;

  const courseColors = useMemo(() => {
    const palette = [
      { bg: "bg-primary/15", text: "text-primary", border: "border-primary/30", occupied: "bg-primary/8" },
      { bg: "bg-blue-500/15", text: "text-blue-500", border: "border-blue-500/30", occupied: "bg-blue-500/8" },
      { bg: "bg-emerald-500/15", text: "text-emerald-500", border: "border-emerald-500/30", occupied: "bg-emerald-500/8" },
      { bg: "bg-purple-500/15", text: "text-purple-500", border: "border-purple-500/30", occupied: "bg-purple-500/8" },
      { bg: "bg-amber-500/15", text: "text-amber-600", border: "border-amber-500/30", occupied: "bg-amber-500/8" },
      { bg: "bg-rose-500/15", text: "text-rose-500", border: "border-rose-500/30", occupied: "bg-rose-500/8" },
    ];
    const map: Record<string, typeof palette[0]> = {};
    let idx = 0;
    bookings?.forEach((b) => {
      if (!map[b.course_id]) {
        map[b.course_id] = palette[idx % palette.length];
        idx++;
      }
    });
    return map;
  }, [bookings]);

  const formatDateDisplay = (d: string) => {
    return format(new Date(d + "T00:00:00"), "EEE, d MMM yyyy");
  };

  return (
    <>
      <Head title="Training Calendar" />
      <div>
        <div className="flex items-center justify-between mb-6">
          <h1 className="text-2xl font-bold text-foreground">Training Calendar</h1>
          {canDrag && (
            <Badge variant="outline" className="text-xs gap-1">
              <GripVertical className="w-3 h-3" /> Drag courses to reschedule
            </Badge>
          )}
        </div>

        {/* Range navigation + view toggle */}
        <div className="flex items-center justify-between mb-6 gap-3 flex-wrap">
          <Button
            variant="outline"
            size="sm"
            onClick={() =>
              viewMode === "week"
                ? setCurrentWeekStart(subWeeks(currentWeekStart, 1))
                : setCurrentMonthStart(subMonths(currentMonthStart, 1))
            }
          >
            <ChevronLeft className="w-4 h-4 mr-1" /> {viewMode === "week" ? "Previous Week" : "Previous Month"}
          </Button>
          <div className="text-center">
            <h2 className="text-lg font-semibold text-foreground">
              {viewMode === "week"
                ? `${format(currentWeekStart, "d MMM")} — ${format(addDays(currentWeekStart, 4), "d MMM yyyy")}`
                : format(currentMonthStart, "MMMM yyyy")}
            </h2>
            <p className="text-xs text-muted-foreground">
              {viewMode === "week" ? `Week ${format(currentWeekStart, "w")}` : `${monthDays.length} working days`}
            </p>
          </div>
          <div className="flex gap-2 items-center">
            {/* Week / Month toggle */}
            <div className="inline-flex rounded-md border border-border overflow-hidden">
              <Button
                variant={viewMode === "week" ? "default" : "ghost"}
                size="sm"
                className="rounded-none"
                onClick={() => setViewMode("week")}
              >
                Week
              </Button>
              <Button
                variant={viewMode === "month" ? "default" : "ghost"}
                size="sm"
                className="rounded-none"
                onClick={() => setViewMode("month")}
              >
                Month
              </Button>
            </div>
            <Button
              variant="outline"
              size="sm"
              onClick={() => {
                if (viewMode === "week") setCurrentWeekStart(startOfWeek(new Date(), { weekStartsOn: 1 }));
                else setCurrentMonthStart(startOfMonth(new Date()));
              }}
            >
              Today
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={() =>
                viewMode === "week"
                  ? setCurrentWeekStart(addWeeks(currentWeekStart, 1))
                  : setCurrentMonthStart(addMonths(currentMonthStart, 1))
              }
            >
              {viewMode === "week" ? "Next Week" : "Next Month"} <ChevronRight className="w-4 h-4 ml-1" />
            </Button>
          </div>
        </div>

        {/* Trainer grid — uses inline grid-template-columns so column count
            can vary between week (5) and month (~20-23) views. The wrapper
            scrolls horizontally when columns can't all fit. */}
        <div className="bg-card border border-border rounded-xl overflow-hidden">
          <div className={viewMode === "month" ? "overflow-x-auto" : ""}>
            <div className={viewMode === "month" ? "min-w-[1400px]" : ""}>
              {/* Header row */}
              <div
                className="grid border-b border-border"
                style={{ gridTemplateColumns: `200px repeat(${displayDays.length}, minmax(${viewMode === "month" ? "56px" : "0"}, 1fr))` }}
              >
                <div className="p-3 bg-muted/50 font-semibold text-sm text-foreground flex items-center">Trainer</div>
                {displayDays.map((day) => {
                  const today = isToday(day);
                  return (
                    <div key={format(day, "yyyy-MM-dd")} className={`p-2 text-center border-l border-border ${today ? "bg-primary/5" : "bg-muted/50"}`}>
                      <div className={`text-[10px] font-medium ${today ? "text-primary" : "text-muted-foreground"}`}>{format(day, "EEE")}</div>
                      <div className={`text-xs font-semibold ${today ? "text-primary" : "text-foreground"}`}>{format(day, viewMode === "month" ? "d" : "d MMM")}</div>
                    </div>
                  );
                })}
              </div>

              {trainers?.map((trainer) => (
                <div
                  key={trainer.id}
                  className="grid border-b border-border last:border-b-0"
                  style={{ gridTemplateColumns: `200px repeat(${displayDays.length}, minmax(${viewMode === "month" ? "56px" : "0"}, 1fr))` }}
                >
                  <div className="p-3 flex items-start gap-2 bg-muted/20">
                    <div className="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center shrink-0 mt-0.5">
                      <span className="text-xs font-bold text-primary">{trainer.first_name[0]}{trainer.last_name[0]}</span>
                    </div>
                    <div>
                      <div className="text-sm font-semibold text-foreground">{trainer.first_name} {trainer.last_name}</div>
                    </div>
                  </div>

                  {displayDays.map((day) => {
                const dateStr = format(day, "yyyy-MM-dd");
                const dayBookings = trainerDayMap[trainer.id]?.[dateStr] || [];
                const occupiedInfo = trainerOccupiedDates[trainer.id]?.[dateStr];
                const today = isToday(day);
                const isContinuation = occupiedInfo && dayBookings.length === 0;
                const color = occupiedInfo ? courseColors[occupiedInfo.courseId] : null;
                const isDropTarget = dropTargetDate === dateStr && dragState?.booking.trainer_id === trainer.id;

                return (
                  <div
                    key={dateStr}
                    className={`min-w-0 p-1.5 border-l border-border min-h-[80px] transition-colors ${
                      today ? "bg-primary/5" : ""
                    } ${isContinuation && color ? color.occupied : ""} ${
                      isDropTarget ? "bg-primary/20 ring-2 ring-primary ring-inset" : ""
                    }`}
                    onDragOver={(e) => handleDragOver(e, dateStr, trainer.id)}
                    onDragLeave={handleDragLeave}
                    onDrop={(e) => handleDrop(e, dateStr, trainer.id)}
                  >
                    {dayBookings.map(({ booking, occupiedDays }) => {
                      const courseDays = getEffectiveDays(booking);
                      const delegateCount = getDelegateCount(booking.course_id, booking.start_date, booking.trainer_id);
                      const bColor = courseColors[booking.course_id] || courseColors[Object.keys(courseColors)[0]];
                      const courseCapacity = booking.courses?.capacity ?? null;

                      // Scale the fill colour to the course's actual capacity so the
                      // thresholds (red ≤ ~37%, orange ≤ ~75%, green > 75%) still
                      // mean the same thing regardless of class size.
                      const fillRatio = courseCapacity && courseCapacity > 0 ? delegateCount / courseCapacity : 0;
                      const delegateBg = fillRatio <= 0.375 ? "bg-red-600" : fillRatio <= 0.75 ? "bg-orange-300" : "bg-green-400";
                      const delegateText = fillRatio <= 0.375 ? "text-white" : "text-black";

                      const bookingOrders = orders?.filter((o) => o.course_id === booking.course_id && o.start_date === booking.start_date && o.trainer_id === booking.trainer_id) || [];
                      const venueIds = [...new Set(bookingOrders.map((o) => o.venue_id).filter(Boolean))];
                      const conflicts = occupiedDays.flatMap((d) =>
                        venueIds.flatMap((vid) => getVenueConflicts(vid, d))
                      );
                      const hasConflict = conflicts.length > 0;

                      return (
                        <div
                          key={booking.id}
                          draggable={canDrag}
                          onDragStart={(e) => handleDragStart(e, booking)}
                          onDragEnd={handleDragEnd}
                          onClick={() =>
                            handleCourseClick(
                              booking.id,
                              booking.course_id,
                              booking.trainer_id,
                              booking.courses?.title || "Course",
                              `${booking.trainers?.first_name} ${booking.trainers?.last_name}`,
                              booking.start_date,
                              courseDays,
                              booking.courses?.capacity ?? null
                            )
                          }
                          className={`min-w-0 max-w-full overflow-hidden w-full text-left rounded-lg p-2 ${bColor.bg} border ${bColor.border} hover:opacity-80 transition-opacity cursor-pointer ${
                            canDrag ? "cursor-grab active:cursor-grabbing" : ""
                          } ${dragState?.booking.id === booking.id ? "opacity-40" : ""} ${hasConflict ? "ring-2 ring-amber-500" : ""}`}
                        >
                          <div className="flex items-start gap-1">
                            {canDrag && <GripVertical className="w-3 h-3 text-muted-foreground/50 shrink-0 mt-0.5" />}
                            <div className="min-w-0 flex-1">
                              <div className={`text-xs font-semibold ${bColor.text} leading-tight truncate flex items-center gap-1`}>
                                {hasConflict && (
                                  <AlertTriangle className="w-3 h-3 text-amber-500 shrink-0" />
                                )}
                                {booking.courses?.title}
                              </div>
                              <div className="flex items-center justify-between mt-1">
                                {hasRole("sys_admin") ? (
                                  <button
                                    onClick={(e) => {
                                      e.stopPropagation();
                                      setDurationEdit({
                                        bookingId: booking.id,
                                        courseTitle: booking.courses?.title || "Course",
                                        currentDays: courseDays,
                                        newDays: courseDays,
                                      });
                                    }}
                                    className="text-[10px] text-muted-foreground flex items-center gap-0.5 hover:text-primary transition-colors"
                                    title="Adjust duration"
                                  >
                                    <Clock className="w-3 h-3" /> {courseDays}d
                                  </button>
                                ) : (
                                  <span className="text-[10px] text-muted-foreground flex items-center gap-0.5">
                                    <Clock className="w-3 h-3" /> {courseDays}d
                                  </span>
                                )}
                                <span className={`text-[10px] font-bold px-1.5 py-0.5 rounded ${delegateBg} ${delegateText} flex items-center gap-0.5`}>
                                  <Users className="w-3 h-3" /> {delegateCount}{courseCapacity != null ? `/${courseCapacity}` : ""}
                                </span>
                              </div>
                            </div>
                          </div>
                        </div>
                      );
                    })}

                    {isContinuation && color && (
                      <button
                        onClick={() => {
                          const origBooking = bookings?.find(
                            (b) => b.course_id === occupiedInfo.courseId && b.start_date === occupiedInfo.startDate && b.trainer_id === trainer.id
                          );
                          if (origBooking) {
                            handleCourseClick(origBooking.id, occupiedInfo.courseId, trainer.id, occupiedInfo.courseTitle, `${trainer.first_name} ${trainer.last_name}`, occupiedInfo.startDate, getEffectiveDays(origBooking), origBooking.courses?.capacity ?? null);
                          }
                        }}
                        className={`min-w-0 max-w-full overflow-hidden w-full text-left rounded-lg p-2 ${color.bg} border ${color.border} hover:opacity-80 transition-opacity cursor-pointer opacity-60`}
                      >
                        <div className={`text-[10px] ${color.text} truncate italic`}>↳ {occupiedInfo.courseTitle} (cont.)</div>
                      </button>
                    )}

                    {!dayBookings.length && !isContinuation && (() => {
                      const avail = isTrainerAvailable(trainer.id, dateStr);
                      if (avail.available) {
                        return (
                          <div className="h-full flex items-center justify-center">
                            <span className="text-[10px] text-emerald-500/70">Available</span>
                          </div>
                        );
                      }
                      // Style each unavailability type distinctly so bank holidays
                      // and trainer leave stand out from the routine "Not scheduled"
                      // default for weekly non-working days.
                      const styles = avail.kind === "bank-holiday"
                        ? "bg-amber-500/15 text-amber-600 dark:text-amber-400 border border-amber-500/30 px-1.5 py-0.5 rounded font-medium not-italic"
                        : avail.kind === "leave"
                          ? "bg-purple-500/15 text-purple-600 dark:text-purple-300 border border-purple-500/30 px-1.5 py-0.5 rounded font-medium not-italic"
                          : "text-destructive/60 italic";
                      return (
                        <div className="h-full flex items-center justify-center">
                          <span className={`text-[10px] ${styles}`}>{avail.reason}</span>
                        </div>
                      );
                    })()}
                  </div>
                );
              })}
                </div>
              ))}
            </div>
          </div>

          {(!trainers || trainers.length === 0) && (
            <div className="p-8 text-center text-muted-foreground">No trainers found.</div>
          )}
        </div>

        {/* Reschedule confirmation dialog */}
        <Dialog open={!!rescheduleConfirm} onOpenChange={() => !isRescheduling && setRescheduleConfirm(null)}>
          <DialogContent className="sm:max-w-lg overflow-x-hidden">
            <DialogHeader className="min-w-0">
              <DialogTitle className="flex items-center gap-2">
                <AlertTriangle className="w-5 h-5 text-amber-500 shrink-0" />
                Confirm Reschedule
              </DialogTitle>
              <DialogDescription>
                This will update the course date and notify all affected contacts.
              </DialogDescription>
            </DialogHeader>

            {rescheduleConfirm && (
              <div className="space-y-4 min-w-0">
                <div className="bg-muted/50 rounded-lg p-4 space-y-3 overflow-hidden">
                  <div className="min-w-0">
                    <p className="text-sm font-semibold text-foreground truncate" title={rescheduleConfirm.booking.courses?.title}>{rescheduleConfirm.booking.courses?.title}</p>
                    <p className="text-xs text-muted-foreground truncate">
                      Trainer: {rescheduleConfirm.booking.trainers?.first_name} {rescheduleConfirm.booking.trainers?.last_name}
                    </p>
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div className="bg-destructive/10 rounded-md p-2.5">
                      <p className="text-[10px] font-medium text-destructive uppercase tracking-wide">From</p>
                      <p className="text-sm font-semibold text-foreground">{formatDateDisplay(rescheduleConfirm.oldDate)}</p>
                    </div>
                    <div className="bg-green-500/10 rounded-md p-2.5">
                      <p className="text-[10px] font-medium text-green-600 uppercase tracking-wide">To</p>
                      <p className="text-sm font-semibold text-foreground">{formatDateDisplay(rescheduleConfirm.newDate)}</p>
                    </div>
                  </div>
                </div>

                {rescheduleConfirm.affectedOrders.length > 0 && (
                  <div className="space-y-2">
                    <h4 className="text-sm font-semibold text-foreground">
                      People who will be notified ({rescheduleConfirm.affectedOrders.length} booking{rescheduleConfirm.affectedOrders.length > 1 ? "s" : ""})
                    </h4>
                    <div className="max-h-48 overflow-y-auto space-y-2">
                      {rescheduleConfirm.affectedOrders.map((order) => {
                        const orderDels = rescheduleDelegates?.filter((d: any) => d.order_id === order.id) || [];
                        return (
                          <div key={order.id} className="bg-secondary/30 rounded-md p-3 space-y-1.5 overflow-hidden">
                            <div className="flex items-center justify-between gap-2">
                              <div className="min-w-0 flex-1">
                                <p className="text-xs font-semibold text-foreground truncate" title={order.customer_name}>
                                  {order.customer_name}
                                </p>
                                <p className="text-[10px] text-muted-foreground truncate" title={order.customer_email}>
                                  {order.customer_email}
                                </p>
                              </div>
                              {order.training_companies && (
                                <Badge
                                  variant="outline"
                                  className="text-[10px] max-w-[180px] truncate shrink-0"
                                  title={(order.training_companies as any).name}
                                >
                                  {(order.training_companies as any).name}
                                </Badge>
                              )}
                            </div>
                            {orderDels.length > 0 && (
                              <div className="flex flex-wrap gap-1 pt-1">
                                {orderDels.map((d: any) => (
                                  <Badge
                                    key={d.id}
                                    variant="secondary"
                                    className="text-[10px] max-w-full truncate"
                                    title={`${d.first_name} ${d.last_name}${d.email ? ` (${d.email})` : ""}`}
                                  >
                                    {d.first_name} {d.last_name}
                                    {d.email && <span className="ml-1 text-muted-foreground">({d.email})</span>}
                                  </Badge>
                                ))}
                              </div>
                            )}
                          </div>
                        );
                      })}
                    </div>
                  </div>
                )}

                {rescheduleConfirm.affectedOrders.length === 0 && (
                  <p className="text-sm text-muted-foreground italic">No bookings affected — no notifications will be sent.</p>
                )}
              </div>
            )}

            <DialogFooter className="gap-2">
              <Button variant="outline" onClick={() => setRescheduleConfirm(null)} disabled={isRescheduling}>
                Cancel
              </Button>
              <Button onClick={confirmReschedule} disabled={isRescheduling}>
                {isRescheduling ? "Rescheduling..." : "Confirm Reschedule"}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>

        {/* Course detail dialog */}
        <Dialog open={!!selectedBooking} onOpenChange={() => setSelectedBooking(null)}>
          {/* overflow-x-hidden caps the dialog at max-w-xl even with absurd
              unbreakable strings inside; min-w-0 on the grid child lets
              `truncate` actually clip rather than expanding the grid track. */}
          <DialogContent className="sm:max-w-xl max-h-[85vh] overflow-y-auto overflow-x-hidden">
            <DialogHeader className="min-w-0">
              <DialogTitle className="flex items-center gap-2 min-w-0">
                <CalendarDays className="w-5 h-5 text-primary shrink-0" />
                <span className="truncate">{selectedBooking?.courseTitle}</span>
              </DialogTitle>
            </DialogHeader>

            {selectedBooking && (
              <div className="space-y-4 min-w-0">
                <div className="bg-muted/50 rounded-lg p-4 space-y-2">
                  <div className="grid grid-cols-2 gap-3 text-sm">
                    <div>
                      <span className="text-muted-foreground">Trainer</span>
                      <p className="font-medium text-foreground">{selectedBooking.trainerName}</p>
                    </div>
                    <div>
                      <span className="text-muted-foreground">Start Date</span>
                      <p className="font-medium text-foreground">{formatDateDisplay(selectedBooking.date)}</p>
                    </div>
                    <div>
                      <span className="text-muted-foreground">Duration</span>
                      <p className="font-medium text-foreground">{selectedBooking.courseDays} day{selectedBooking.courseDays > 1 ? "s" : ""}</p>
                    </div>
                    <div>
                      <span className="text-muted-foreground">Total Delegates</span>
                      <p className="font-medium text-foreground">
                        {selectedBooking.courseCapacity != null ? (
                          <>
                            <span className={totalDelegates >= selectedBooking.courseCapacity ? "text-destructive" : ""}>
                              {totalDelegates}/{selectedBooking.courseCapacity}
                            </span>
                            {totalDelegates >= selectedBooking.courseCapacity && (
                              <Badge variant="destructive" className="ml-2 text-[10px]">FULL</Badge>
                            )}
                          </>
                        ) : (
                          <span>{totalDelegates}</span>
                        )}
                      </p>
                    </div>
                  </div>
                </div>

                {/* Adjust duration section (sys admins only) */}
                {canDrag && (
                  <div className="border border-border rounded-lg p-4 flex items-center justify-between">
                    <div>
                      <h4 className="text-sm font-semibold text-foreground flex items-center gap-2">
                        <Pencil className="w-4 h-4" /> Adjust Duration
                      </h4>
                      <p className="text-xs text-muted-foreground mt-1">
                        Currently {selectedBooking.courseDays} day{selectedBooking.courseDays !== 1 ? "s" : ""} — change for this booking only.
                      </p>
                    </div>
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => {
                        setDurationEdit({
                          bookingId: selectedBooking.bookingId,
                          courseTitle: selectedBooking.courseTitle,
                          currentDays: selectedBooking.courseDays,
                          newDays: selectedBooking.courseDays,
                        });
                      }}
                    >
                      Edit Days
                    </Button>
                  </div>
                )}

                {/* Reschedule section (sys admins only) */}
                {canDrag && (
                  <div className="border border-border rounded-lg p-4 space-y-3">
                    <div className="flex items-center justify-between">
                      <h4 className="text-sm font-semibold text-foreground flex items-center gap-2">
                        <CalendarDays className="w-4 h-4" /> Reschedule Course
                      </h4>
                      {!showReschedulePicker && (
                        <Button variant="outline" size="sm" onClick={() => setShowReschedulePicker(true)}>
                          Pick New Date
                        </Button>
                      )}
                    </div>
                    {showReschedulePicker && (
                      <div className="space-y-3">
                        <p className="text-xs text-muted-foreground">Select a new start date for this course:</p>
                        <div className="flex justify-center">
                          <CalendarPicker
                            mode="single"
                            selected={rescheduleDate}
                            onSelect={setRescheduleDate}
                            disabled={(date) => {
                              // Until availability loads, keep the basic guard
                              // (past + weekends) so the picker isn't fully
                              // greyed out mid-fetch. Once loaded, only days the
                              // booking's trainer is actually free are allowed.
                              if (rescheduleAvailabilityLoading || !selectedBooking) {
                                return date < new Date() || isWeekend(date);
                              }
                              return !isDateAvailableForTrainer(selectedBooking.trainerId, date);
                            }}
                            className={cn("p-3 pointer-events-auto rounded-md border border-border")}
                          />
                        </div>
                        <div className="flex items-center justify-end gap-2">
                          <Button variant="outline" size="sm" onClick={() => { setShowReschedulePicker(false); setRescheduleDate(undefined); }}>
                            Cancel
                          </Button>
                          <Button
                            size="sm"
                            disabled={!rescheduleDate}
                            onClick={() => {
                              if (!rescheduleDate || !selectedBooking) return;
                              const newDateStr = format(rescheduleDate, "yyyy-MM-dd");
                              if (newDateStr === selectedBooking.date) {
                                toast.error("Please select a different date.");
                                return;
                              }
                              const matchingBooking = bookings?.find((b) => b.id === selectedBooking.bookingId);
                              if (!matchingBooking) return;
                              const affectedOrders = orders?.filter(
                                (o) => o.course_id === selectedBooking.courseId &&
                                       o.start_date === selectedBooking.date &&
                                       o.trainer_id === selectedBooking.trainerId &&
                                       ["paid", "confirmed"].includes(o.status)
                              ) || [];
                              setSelectedBooking(null);
                              setShowReschedulePicker(false);
                              setRescheduleDate(undefined);
                              setRescheduleConfirm({
                                booking: matchingBooking,
                                oldDate: selectedBooking.date,
                                newDate: newDateStr,
                                affectedOrders,
                              });
                            }}
                          >
                            Reschedule to {rescheduleDate ? format(rescheduleDate, "d MMM yyyy") : "..."}
                          </Button>
                        </div>
                      </div>
                    )}
                  </div>
                )}

                <div className="space-y-3">
                  <h3 className="text-sm font-semibold text-foreground flex items-center gap-2">
                    <Users className="w-4 h-4" /> Bookings ({selectedBooking.orders.length})
                  </h3>

                  {selectedBooking.orders.map((order) => {
                    const orderDelegates = delegates?.filter((d: any) => d.order_id === order.id) || [];
                    return (
                      <div key={order.id} className="bg-secondary/30 rounded-lg p-4 space-y-3 overflow-hidden">
                        <div className="flex items-start justify-between gap-3">
                          <div className="min-w-0 flex-1">
                            {order.training_companies && (
                              <p
                                className="text-sm font-semibold text-foreground truncate"
                                title={(order.training_companies as any).name}
                              >
                                {(order.training_companies as any).name}
                              </p>
                            )}
                            <p
                              className="text-xs text-muted-foreground truncate"
                              title={`${order.customer_name} • ${order.customer_email}`}
                            >
                              Booked by: {order.customer_name} • {order.customer_email}
                            </p>
                            {order.venues && (
                              <p className="text-xs text-muted-foreground flex items-center gap-1 mt-0.5 min-w-0">
                                <MapPin className="w-3 h-3 shrink-0" />
                                <span className="truncate">
                                  {(order.venues as any).name}
                                  {(order.venues as any).city && `, ${(order.venues as any).city}`}
                                </span>
                              </p>
                            )}
                          </div>
                          <div className="text-right shrink-0">
                            <div className="flex items-center justify-end gap-1.5">
                              <Badge variant="outline" className="text-[10px]">{order.status}</Badge>
                              <a
                                href={`/admin/orders?id=${encodeURIComponent(order.id)}`}
                                target="_blank"
                                rel="noopener noreferrer"
                                className="text-muted-foreground hover:text-foreground transition-colors"
                                title="Open order in new tab"
                              >
                                <ExternalLink className="w-3.5 h-3.5" />
                              </a>
                            </div>
                            <p className="text-xs font-medium text-foreground mt-1 whitespace-nowrap">£{(grossCents(order.price_cents) / 100).toFixed(2)} <span className="text-muted-foreground/70 font-normal">incl. VAT</span></p>
                          </div>
                        </div>

                        {orderDelegates.length > 0 && (
                          <div className="border-t border-border pt-2">
                            <p className="text-xs font-medium text-muted-foreground mb-1.5">
                              Delegates ({orderDelegates.length}) — Onboarding Forms
                            </p>
                            <div className="space-y-1.5">
                              {(() => {
                                // Booking edits only allowed on-the-day or later.
                                const todayIso = format(new Date(), "yyyy-MM-dd");
                                const canEditOrder = !order.start_date || order.start_date >= todayIso;
                                return orderDelegates.map((d: any) => {
                                  const email = d.email || "";
                                  const delegateSubs = email
                                    ? (calendarSubmissions?.filter(
                                        (s: any) => s.delegate_email.toLowerCase() === email.toLowerCase() && s.order_id === order.id
                                      ) || [])
                                    : [];
                                  const formTypes = ["TD-02", "TD-07", "TD-29"];
                                  return (
                                    <div key={d.id} className="flex items-center justify-between gap-2 rounded-lg bg-background/60 border border-border px-2.5 py-2">
                                      <div className="flex items-center gap-2 min-w-0">
                                        <div className="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center shrink-0">
                                          <span className="text-[10px] font-bold text-primary">{(d.first_name || "?")[0]}{(d.last_name || "?")[0]}</span>
                                        </div>
                                        <div className="min-w-0">
                                          <span className="text-xs font-medium text-foreground truncate block">{d.first_name} {d.last_name}</span>
                                          {email && <span className="text-[10px] text-muted-foreground truncate block">{email}</span>}
                                        </div>
                                      </div>
                                      <div className="flex items-center gap-1.5 shrink-0">
                                        {canEditOrder && (
                                          <Button
                                            variant="ghost"
                                            size="sm"
                                            className="h-6 w-6 p-0"
                                            title="Edit / swap delegate"
                                            onClick={(e) => {
                                              e.stopPropagation();
                                              setEditDelegate({ delegate: d, orderId: order.id });
                                            }}
                                          >
                                            <Pencil className="w-3 h-3" />
                                          </Button>
                                        )}
                                        {formTypes.map((ft) => {
                                          const done = delegateSubs.some((s: any) => s.form_type === ft);
                                          return (
                                            <div key={ft} className="flex flex-col items-center gap-0.5" title={`${ft}: ${done ? "Completed" : "Pending"}`}>
                                              {done ? <CheckCircle2 className="w-3.5 h-3.5 text-green-500" /> : <XCircle className="w-3.5 h-3.5 text-muted-foreground/40" />}
                                              <span className="text-[9px] text-muted-foreground">{ft}</span>
                                            </div>
                                          );
                                        })}
                                      </div>
                                    </div>
                                  );
                                });
                              })()}
                            </div>
                          </div>
                        )}
                      </div>
                    );
                  })}

                  {selectedBooking.orders.length === 0 && (
                    <p className="text-sm text-muted-foreground italic">No bookings for this course yet.</p>
                  )}
                </div>
              </div>
            )}
          </DialogContent>
        </Dialog>

        {/* Duration adjustment dialog */}
        <Dialog open={!!durationEdit} onOpenChange={() => !isDurationSaving && setDurationEdit(null)}>
          <DialogContent className="sm:max-w-sm">
            <DialogHeader>
              <DialogTitle className="flex items-center gap-2">
                <Pencil className="w-4 h-4 text-primary" />
                Adjust Duration
              </DialogTitle>
              <DialogDescription>
                Change the number of training days for this booked session.
              </DialogDescription>
            </DialogHeader>

            {durationEdit && (
              <div className="space-y-4">
                <p className="text-sm font-medium text-foreground">{durationEdit.courseTitle}</p>

                <div className="grid grid-cols-2 gap-4">
                  <div>
                    <label className="text-xs text-muted-foreground font-medium">Current Days</label>
                    <div className="mt-1 bg-muted/50 rounded-md px-3 py-2 text-sm font-semibold text-foreground">
                      {durationEdit.currentDays} day{durationEdit.currentDays !== 1 ? "s" : ""}
                    </div>
                  </div>
                  <div>
                    <label className="text-xs text-muted-foreground font-medium">New Days</label>
                    <input
                      type="number"
                      min={1}
                      max={30}
                      value={durationEdit.newDays}
                      onChange={(e) => setDurationEdit({ ...durationEdit, newDays: Math.max(1, parseInt(e.target.value) || 1) })}
                      className="mt-1 w-full rounded-md border border-input bg-background px-3 py-2 text-sm font-semibold text-foreground focus:outline-none focus:ring-2 focus:ring-primary"
                    />
                  </div>
                </div>

                {durationEdit.newDays < durationEdit.currentDays && (
                  <p className="text-xs text-muted-foreground bg-green-500/10 rounded-md p-2">
                    Reducing to {durationEdit.newDays} day{durationEdit.newDays !== 1 ? "s" : ""} will free up trainer availability on the removed days.
                  </p>
                )}
                {durationEdit.newDays > durationEdit.currentDays && (
                  <p className="text-xs text-muted-foreground bg-amber-500/10 rounded-md p-2">
                    Extending to {durationEdit.newDays} day{durationEdit.newDays !== 1 ? "s" : ""} will block additional trainer availability.
                  </p>
                )}
              </div>
            )}

            <DialogFooter className="gap-2">
              <Button variant="outline" onClick={() => setDurationEdit(null)} disabled={isDurationSaving}>
                Cancel
              </Button>
              <Button
                disabled={isDurationSaving || !durationEdit || durationEdit.newDays === durationEdit.currentDays}
                onClick={async () => {
                  if (!durationEdit) return;
                  setIsDurationSaving(true);
                  try {
                    const res = await fetch(`/api/admin/calendar/bookings/${durationEdit.bookingId}/duration`, {
                      method: 'POST',
                      headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json',
                        'X-Requested-With': 'XMLHttpRequest',
                        'X-CSRF-TOKEN': csrfToken(),
                      },
                      body: JSON.stringify({
                        duration_override: durationEdit.newDays,
                        course_title: durationEdit.courseTitle,
                        old_days: durationEdit.currentDays,
                      }),
                    });
                    if (!res.ok) {
                      const err = await res.json().catch(() => ({ error: 'Failed' }));
                      throw new Error(err.error || err.message || 'Failed to update duration');
                    }
                    const data = await res.json().catch(() => ({ ok: false }));
                    if (!data?.ok) throw new Error('Duration was not updated — booking not found?');

                    toast.success(`Duration updated from ${durationEdit.currentDays} to ${durationEdit.newDays} day${durationEdit.newDays !== 1 ? "s" : ""}`);
                    queryClient.invalidateQueries({ queryKey: ["calendar-bookings-week"] });
                    setDurationEdit(null);
                  } catch (err: any) {
                    toast.error(`Failed to update duration: ${err.message}`);
                  } finally {
                    setIsDurationSaving(false);
                  }
                }}
              >
                {isDurationSaving ? "Saving..." : "Update Duration"}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>

        {/* Edit / swap delegate */}
        <EditDelegateDialog
          open={!!editDelegate}
          onOpenChange={(o) => { if (!o) setEditDelegate(null); }}
          orderId={editDelegate?.orderId ?? ""}
          delegate={editDelegate?.delegate ?? null}
          onSaved={() => {
            queryClient.invalidateQueries({ queryKey: ["calendar-orders-week"] });
            queryClient.invalidateQueries({ queryKey: ["calendar-delegates"] });
            queryClient.invalidateQueries({ queryKey: ["calendar-form-submissions"] });
          }}
        />
      </div>
    </>
  );
};

TrainingCalendar.layout = (page: ReactNode) => <AdminLayout>{page}</AdminLayout>;

export default TrainingCalendar;
