import { useState, useMemo } from "react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Badge } from "@/components/ui/badge";
import { Checkbox } from "@/components/ui/checkbox";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Separator } from "@/components/ui/separator";
import { buildMaterialReturnFinalPdfViewerHref } from "@/lib/materialReturnFinalPdf";
import { getReservationSalleScheduleSummary } from "@/lib/reservationSalle";
import { getMaterialEventLabel } from "@/lib/materialEvent";
import { loadXlsx } from "@/lib/loadXlsx";
import { trpc } from "@/lib/trpc";
import { 
  ArrowLeft, ArrowRight, Building2, Calendar, ChevronLeft, ChevronRight, 
  Clock, Download, Edit, ExternalLink, Loader2, MapPin, PackageCheck, RefreshCw, ShieldAlert, Users 
} from "lucide-react";
import { toast } from "sonner";
import { Link } from "wouter";

const SALLES_MJS = [
  { id: 'bureau_11_17', nom: 'Bureau 11–17 m²', color: 'bg-cyan-500', textColor: 'text-cyan-700', bgLight: 'bg-cyan-50 border-cyan-200', icon: '🗂️' },
  { id: 'salle_toucan', nom: 'Salle TOUCAN', color: 'bg-blue-500', textColor: 'text-blue-700', bgLight: 'bg-blue-50 border-blue-200', icon: '🦜' },
  { id: 'salle_ibis', nom: 'Salle IBIS', color: 'bg-emerald-500', textColor: 'text-emerald-700', bgLight: 'bg-emerald-50 border-emerald-200', icon: '🦩' },
  { id: 'salle_pelican', nom: 'Salle PELICAN', color: 'bg-purple-500', textColor: 'text-purple-700', bgLight: 'bg-purple-50 border-purple-200', icon: '🐦' },
  { id: 'dojo', nom: 'DOJO', color: 'bg-orange-500', textColor: 'text-orange-700', bgLight: 'bg-orange-50 border-orange-200', icon: '🥋' },
  { id: 'hall_amphitheatre', nom: 'Hall-Amphithéâtre', color: 'bg-red-500', textColor: 'text-red-700', bgLight: 'bg-red-50 border-red-200', icon: '🎭' },
  { id: 'vestiaires', nom: 'Vestiaires', color: 'bg-gray-500', textColor: 'text-gray-700', bgLight: 'bg-gray-50 border-gray-200', icon: '🚿' },
];

function getSalleConfig(salleId: string) {
  return SALLES_MJS.find(s => s.id === salleId) || SALLES_MJS.find(s => s.nom === salleId);
}

function getSalleColor(salleNom: string) {
  const salle = SALLES_MJS.find(s => s.nom === salleNom || s.id === salleNom);
  return salle?.color || 'bg-gray-400';
}

function getSalleBgLight(salleNom: string) {
  const salle = SALLES_MJS.find(s => s.nom === salleNom || s.id === salleNom);
  return salle?.bgLight || 'bg-gray-50 border-gray-200';
}

interface ReservationEvent {
  id: number;
  titre: string;
  associationName: string;
  associationEmail: string | null;
  dateDebut: Date;
  dateFin: Date;
  heureDebut: string;
  heureFin: string;
  useDetailedSchedule: boolean;
  horairesParJour: Array<{ date: string; heureDebut: string; heureFin: string }>;
  scheduleSummary: string;
  salles: string[];
  sallesIds: string[];
  nombreParticipants: string;
  motif: string;
}

interface MaterialCalendarEvent {
  requestId: number;
  associationId?: number;
  title: string;
  associationName: string;
  commune: string;
  manifestationStart: string;
  manifestationEnd: string;
  pickupDate: string;
  restitutionDate: string;
  useStartDate: string;
  useEndDate: string;
  requestedItems: Array<{
    key: string;
    label: string;
    quantity: number;
    granted: boolean;
    requested: boolean;
    extra: string;
  }>;
  motif: string;
  boardState: string;
  boardStateLabel: string;
  logisticServiceLabel: string;
  logisticRecipients: string[];
  followupStatus: string | null;
  issueFlag: boolean;
  finalPdfUrl: string | null;
  uploadLink: string | null;
}

const materialBoardStateClasses: Record<string, string> = {
  a_attribuer: "bg-slate-100 text-slate-700 border-slate-200",
  planifie: "bg-blue-100 text-blue-700 border-blue-200",
  terrain: "bg-amber-100 text-amber-700 border-amber-200",
  retard: "bg-red-100 text-red-700 border-red-200",
  conforme: "bg-green-100 text-green-700 border-green-200",
  litige: "bg-orange-100 text-orange-800 border-orange-200",
};

function parseReservations(data: any[]): ReservationEvent[] {
  return data.map(r => {
    let formData: any = {};
    try {
      formData = r.formData ? JSON.parse(r.formData) : {};
    } catch {
      formData = {};
    }

    return {
      id: r.id,
      titre: r.titre,
      associationName: r.associationName || 'Association inconnue',
      associationEmail: r.associationEmail,
      dateDebut: new Date(formData.dateReservation || r.createdAt),
      dateFin: new Date(formData.dateFinReservation || formData.dateReservation || r.createdAt),
      heureDebut: formData.heureDebut || '',
      heureFin: formData.heureFin || '',
      useDetailedSchedule: Boolean(formData.useDetailedSchedule),
      horairesParJour: Array.isArray(formData.horairesParJour)
        ? formData.horairesParJour.filter((slot: any) => slot?.date)
        : [],
      scheduleSummary: getReservationSalleScheduleSummary({
        useDetailedSchedule: Boolean(formData.useDetailedSchedule),
        horairesParJour: Array.isArray(formData.horairesParJour)
          ? formData.horairesParJour.filter((slot: any) => slot?.date)
          : [],
        heureDebut: formData.heureDebut || '',
        heureFin: formData.heureFin || '',
      }),
      salles: formData.sallesSelectionnees || [],
      sallesIds: formData.sallesIds || [],
      nombreParticipants: formData.nombreParticipants || '',
      motif: formData.motifReservation || r.description || '',
    };
  });
}

function getDaysInMonth(year: number, month: number): Date[] {
  const days: Date[] = [];
  const firstDay = new Date(year, month, 1);
  const lastDay = new Date(year, month + 1, 0);

  // Add padding days from previous month
  const startDow = firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1; // Monday = 0
  for (let i = startDow - 1; i >= 0; i--) {
    const d = new Date(year, month, -i);
    days.push(d);
  }

  // Add days of current month
  for (let i = 1; i <= lastDay.getDate(); i++) {
    days.push(new Date(year, month, i));
  }

  // Add padding days from next month
  const endDow = lastDay.getDay() === 0 ? 6 : lastDay.getDay() - 1;
  for (let i = 1; i < 7 - endDow; i++) {
    days.push(new Date(year, month + 1, i));
  }

  return days;
}

function isSameDay(a: Date, b: Date): boolean {
  return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
}

function isDateInRange(date: Date, start: Date, end: Date): boolean {
  const d = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  const s = new Date(start.getFullYear(), start.getMonth(), start.getDate());
  const e = new Date(end.getFullYear(), end.getMonth(), end.getDate());
  return d >= s && d <= e;
}

function isDateStringInRange(date: Date, start: string, end: string): boolean {
  if (!start || !end) return false;
  const current = date.toISOString().split("T")[0];
  return current >= start && current <= end;
}

function startOfWeek(date: Date) {
  const next = new Date(date);
  next.setHours(0, 0, 0, 0);
  next.setDate(next.getDate() - ((next.getDay() + 6) % 7));
  return next;
}

function addDays(date: Date, days: number) {
  const next = new Date(date);
  next.setDate(next.getDate() + days);
  return next;
}

function addMonths(date: Date, months: number) {
  const next = new Date(date);
  next.setMonth(next.getMonth() + months);
  return next;
}

function addYears(date: Date, years: number) {
  const next = new Date(date);
  next.setFullYear(next.getFullYear() + years);
  return next;
}

function toIsoDate(date: Date) {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate()).toISOString().split("T")[0];
}

function getMonthDates(year: number, month: number) {
  const lastDay = new Date(year, month + 1, 0).getDate();
  return Array.from({ length: lastDay }, (_, index) => new Date(year, month, index + 1));
}

const MONTH_NAMES = [
  'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
  'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'
];

const DAY_NAMES = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim'];

export default function ReservationCalendar({ readOnly = false }: { readOnly?: boolean }) {
  const today = new Date();
  const [currentDate, setCurrentDate] = useState(() => new Date(today.getFullYear(), today.getMonth(), today.getDate()));
  const [selectedEvent, setSelectedEvent] = useState<ReservationEvent | null>(null);
  const [selectedMaterialEvent, setSelectedMaterialEvent] = useState<MaterialCalendarEvent | null>(null);
  const [selectedSalleId, setSelectedSalleId] = useState<string | null>(null);
  const [selectedMaterialKey, setSelectedMaterialKey] = useState<string | null>(null);
  const [showChangeSalleDialog, setShowChangeSalleDialog] = useState(false);
  const [newSallesIds, setNewSallesIds] = useState<string[]>([]);
  const [changeRaison, setChangeRaison] = useState('');
  const [viewMode, setViewMode] = useState<'day' | 'week' | 'month' | 'year'>('month');
  const [resourceMode, setResourceMode] = useState<'salles' | 'materiel'>('salles');
  const currentMonth = currentDate.getMonth();
  const currentYear = currentDate.getFullYear();

  const { data: reservationsRaw, isLoading, refetch } = trpc.request.getApprovedReservations.useQuery();
  const { data: materialCalendarRaw, isLoading: materialCalendarLoading, refetch: refetchMaterialCalendar } = trpc.request.getMaterialCalendar.useQuery();
  const utils = trpc.useUtils();

  const changeSallesMutation = trpc.request.changeSalles.useMutation({
    onSuccess: (data) => {
      toast.success(`Salles modifiées avec succès. Notification envoyée à l'association.`);
      setShowChangeSalleDialog(false);
      setSelectedEvent(null);
      setNewSallesIds([]);
      setChangeRaison('');
      utils.request.getApprovedReservations.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors du changement de salle');
    },
  });

  const reservations = useMemo(() => {
    if (!reservationsRaw) return [];
    return parseReservations(reservationsRaw);
  }, [reservationsRaw]);

  const materialEvents = useMemo<MaterialCalendarEvent[]>(() => {
    return (materialCalendarRaw?.events || [])
      .filter((event) => typeof event.requestId === "number")
      .map((event) => ({
        ...event,
        requestId: Number(event.requestId),
      })) as MaterialCalendarEvent[];
  }, [materialCalendarRaw]);

  const selectedSalle = useMemo(
    () => SALLES_MJS.find(s => s.id === selectedSalleId) || null,
    [selectedSalleId]
  );

  const selectedMaterialInventory = useMemo(
    () => (materialCalendarRaw?.inventory || []).find((item: any) => item.key === selectedMaterialKey) || null,
    [materialCalendarRaw, selectedMaterialKey]
  );

  const filteredReservations = useMemo(() => {
    if (!selectedSalleId) return reservations;
    return reservations.filter(r => r.sallesIds.includes(selectedSalleId) || r.salles.includes(selectedSalle?.nom || selectedSalleId));
  }, [reservations, selectedSalleId, selectedSalle]);

  const filteredMaterialEvents = useMemo(() => {
    if (!selectedMaterialKey) return materialEvents;
    return materialEvents.filter((event) =>
      event.requestedItems.some((item) => item.key === selectedMaterialKey && item.quantity > 0)
    );
  }, [materialEvents, selectedMaterialKey]);

  const days = useMemo(() => getDaysInMonth(currentYear, currentMonth), [currentYear, currentMonth]);

  const weekDays = useMemo(() => {
    const result: Date[] = [];
    const weekStart = startOfWeek(currentDate);
    for (let i = 0; i < 7; i++) {
      const d = addDays(weekStart, i);
      result.push(d);
    }
    return result;
  }, [currentDate]);

  const monthDates = useMemo(() => getMonthDates(currentYear, currentMonth), [currentYear, currentMonth]);

  const yearMonths = useMemo(
    () => Array.from({ length: 12 }, (_, index) => new Date(currentYear, index, 1)),
    [currentYear]
  );

  const getEventsForDay = (date: Date) => {
    return filteredReservations.filter(r => isDateInRange(date, r.dateDebut, r.dateFin));
  };

  const getMaterialEventsForDay = (date: Date) => {
    return filteredMaterialEvents.filter((event) => isDateStringInRange(date, event.useStartDate, event.useEndDate));
  };

  const goToPrevious = () => {
    setCurrentDate((prev) => {
      if (viewMode === 'day') return addDays(prev, -1);
      if (viewMode === 'week') return addDays(prev, -7);
      if (viewMode === 'year') return addYears(prev, -1);
      return addMonths(prev, -1);
    });
  };

  const goToNext = () => {
    setCurrentDate((prev) => {
      if (viewMode === 'day') return addDays(prev, 1);
      if (viewMode === 'week') return addDays(prev, 7);
      if (viewMode === 'year') return addYears(prev, 1);
      return addMonths(prev, 1);
    });
  };

  const goToToday = () => {
    setCurrentDate(new Date(today.getFullYear(), today.getMonth(), today.getDate()));
  };

  const openChangeSalleDialog = (event: ReservationEvent) => {
    setSelectedEvent(event);
    setNewSallesIds(event.sallesIds.length > 0 ? [...event.sallesIds] : []);
    setChangeRaison('');
    setShowChangeSalleDialog(true);
  };

  const handleChangeSalles = () => {
    if (!selectedEvent) return;
    if (newSallesIds.length === 0) {
      toast.error('Veuillez sélectionner au moins une salle');
      return;
    }
    if (!changeRaison.trim()) {
      toast.error('Veuillez indiquer la raison du changement');
      return;
    }

    const newSallesNoms = newSallesIds.map(id => {
      const salle = SALLES_MJS.find(s => s.id === id);
      return salle?.nom || id;
    });

    changeSallesMutation.mutate({
      id: selectedEvent.id,
      newSallesIds,
      newSallesNoms,
      raison: changeRaison.trim(),
    });
  };

  const toggleSalle = (salleId: string) => {
    setNewSallesIds(prev =>
      prev.includes(salleId)
        ? prev.filter(id => id !== salleId)
        : [...prev, salleId]
    );
  };

  // Stats
  const totalReservations = reservations.length;
  const reservationsThisMonth = reservations.filter(r => 
    r.dateDebut.getMonth() === currentMonth && r.dateDebut.getFullYear() === currentYear
  ).length;

  // Salle usage count for current month
  const salleUsage = useMemo(() => {
    const usage: Record<string, number> = {};
    reservations.forEach(r => {
      if (r.dateDebut.getMonth() === currentMonth && r.dateDebut.getFullYear() === currentYear) {
        r.salles.forEach(s => {
          usage[s] = (usage[s] || 0) + 1;
        });
      }
    });
    return usage;
  }, [reservations, currentMonth, currentYear]);

  const salleReservations = useMemo(() => {
    if (!selectedSalleId || !selectedSalle) return [];
    return reservations
      .filter(r => r.sallesIds.includes(selectedSalleId) || r.salles.includes(selectedSalle.nom))
      .filter(r => r.dateFin >= new Date(today.getFullYear(), today.getMonth(), today.getDate()))
      .sort((a, b) => a.dateDebut.getTime() - b.dateDebut.getTime());
  }, [reservations, selectedSalleId, selectedSalle, today]);

  const materialReservations = useMemo(() => {
    if (!selectedMaterialKey || !selectedMaterialInventory) return [];
    return materialEvents
      .filter((event) =>
        event.requestedItems.some((item) => item.key === selectedMaterialKey && item.quantity > 0)
      )
      .filter((event) => {
        const endDate = event.useEndDate || event.restitutionDate;
        return endDate >= today.toISOString().split("T")[0];
      })
      .sort((a, b) => (a.useStartDate || a.manifestationStart).localeCompare(b.useStartDate || b.manifestationStart));
  }, [materialEvents, selectedMaterialKey, selectedMaterialInventory, today]);

  const materialStats = useMemo(() => {
    const currentMonthKey = `${currentYear}-${String(currentMonth + 1).padStart(2, "0")}`;
    const activeThisMonth = materialEvents.filter((event) => {
      const start = event.useStartDate || event.manifestationStart;
      const end = event.useEndDate || event.restitutionDate;
      return start.slice(0, 7) <= currentMonthKey && end.slice(0, 7) >= currentMonthKey;
    }).length;

    const countsByState = materialEvents.reduce<Record<string, number>>((acc, event) => {
      acc[event.boardState] = (acc[event.boardState] || 0) + 1;
      return acc;
    }, {});

    return {
      total: materialEvents.length,
      activeThisMonth,
      countsByState,
    };
  }, [materialEvents, currentMonth, currentYear]);

  const materialEventsByDay = useMemo(() => {
    const byDay = new Map<string, MaterialCalendarEvent[]>();
    for (const event of materialEvents) {
      if (!event.useStartDate || !event.useEndDate) continue;
      let cursor = new Date(`${event.useStartDate}T12:00:00`);
      const end = new Date(`${event.useEndDate}T12:00:00`);
      while (cursor <= end) {
        const iso = toIsoDate(cursor);
        const existing = byDay.get(iso) || [];
        existing.push(event);
        byDay.set(iso, existing);
        cursor = addDays(cursor, 1);
      }
    }
    return byDay;
  }, [materialEvents]);

  const materialStockByDay = useMemo(() => {
    const inventoryItems = (materialCalendarRaw?.inventory || []) as Array<{
      key: string;
      label: string;
      capacity: number | null;
      effectiveCapacity: number | null;
    }>;
    const byDay = new Map<string, Record<string, {
      reserved: number;
      total: number | null;
      remaining: number | null;
      overbooked: boolean;
    }>>();

    for (const [iso, events] of Array.from(materialEventsByDay.entries())) {
      const nextDay: Record<string, { reserved: number; total: number | null; remaining: number | null; overbooked: boolean }> = {};
      for (const item of inventoryItems) {
        const reserved = events.reduce((sum: number, event: MaterialCalendarEvent) => {
          const requested = event.requestedItems.find((entry: MaterialCalendarEvent["requestedItems"][number]) => entry.key === item.key);
          return sum + (requested?.quantity || 0);
        }, 0);
        const total = item.effectiveCapacity ?? item.capacity ?? null;
        const remaining = total === null ? null : total - reserved;
        nextDay[item.key] = {
          reserved,
          total,
          remaining,
          overbooked: remaining !== null && remaining < 0,
        };
      }
      byDay.set(iso, nextDay);
    }

    return byDay;
  }, [materialCalendarRaw, materialEventsByDay]);

  const visibleMaterialDates = useMemo(() => {
    if (viewMode === 'day') return [new Date(currentDate)];
    if (viewMode === 'week') return weekDays;
    if (viewMode === 'month') return monthDates;
    return [];
  }, [currentDate, monthDates, viewMode, weekDays]);

  const materialDaySummary = useMemo(() => {
    return visibleMaterialDates.map((date) => {
      const iso = toIsoDate(date);
      const dayStock = materialStockByDay.get(iso) || {};
      const dayEvents = materialEventsByDay.get(iso) || [];
      const selectedItemStock = selectedMaterialKey ? dayStock[selectedMaterialKey] || null : null;
      const overbookedItems = Object.entries(dayStock)
        .filter(([, value]) => value.overbooked)
        .map(([key]) => getMaterialEventLabel(key));
      return {
        iso,
        date,
        eventsCount: dayEvents.length,
        selectedItemStock,
        overbookedItems,
        items: dayStock,
      };
    });
  }, [visibleMaterialDates, materialStockByDay, materialEventsByDay, selectedMaterialKey]);

  const materialYearSummary = useMemo(() => {
    if (viewMode !== 'year') return [];
    return yearMonths.map((monthDate) => {
      const dates = getMonthDates(monthDate.getFullYear(), monthDate.getMonth());
      const monthEvents = materialEvents.filter((event) =>
        dates.some((date) => isDateStringInRange(date, event.useStartDate, event.useEndDate))
      );
      const selectedSnapshots = selectedMaterialKey
        ? dates.map((date) => materialStockByDay.get(toIsoDate(date))?.[selectedMaterialKey] || null).filter(Boolean) as Array<{
            reserved: number;
            total: number | null;
            remaining: number | null;
            overbooked: boolean;
          }>
        : [];
      const minRemaining = selectedSnapshots.length > 0
        ? selectedSnapshots.reduce<number | null>((min, snapshot) => {
            if (snapshot.remaining === null) return min;
            if (min === null) return snapshot.remaining;
            return Math.min(min, snapshot.remaining);
          }, null)
        : null;
      const peakReserved = selectedSnapshots.length > 0
        ? selectedSnapshots.reduce((max, snapshot) => Math.max(max, snapshot.reserved), 0)
        : 0;
      const tensionDays = dates.filter((date) => {
        const entries = materialStockByDay.get(toIsoDate(date));
        if (!entries) return false;
        if (selectedMaterialKey) {
          return Boolean(entries[selectedMaterialKey]?.overbooked);
        }
        return Object.values(entries).some((entry) => entry.overbooked);
      }).length;

      return {
        monthDate,
        monthLabel: MONTH_NAMES[monthDate.getMonth()],
        eventsCount: monthEvents.length,
        tensionDays,
        minRemaining,
        peakReserved,
      };
    });
  }, [materialEvents, materialStockByDay, selectedMaterialKey, viewMode, yearMonths]);

  if (isLoading || materialCalendarLoading) {
    return (
      <div className="flex items-center justify-center py-12">
        <Loader2 className="h-8 w-8 animate-spin text-primary" />
      </div>
    );
  }

  const currentViewLabel =
    viewMode === 'day'
      ? currentDate.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })
      : viewMode === 'week'
        ? `Semaine du ${weekDays[0].toLocaleDateString('fr-FR', { day: 'numeric', month: 'long' })} au ${weekDays[6].toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })}`
        : viewMode === 'year'
          ? `Année ${currentYear}`
          : `${MONTH_NAMES[currentMonth]} ${currentYear}`;

  const exportMaterialAvailabilityCsv = () => {
    const inventoryItems = ((materialCalendarRaw?.inventory || []) as Array<{
      key: string;
      label: string;
      capacity: number | null;
      effectiveCapacity: number | null;
    }>);

    const rows: string[] = [];
    if (selectedMaterialInventory) {
      if (viewMode === 'year') {
        rows.push("Mois,Reservations,Jours bloqués,Pic réservé,Reste minimum");
        materialYearSummary.forEach((entry) => {
          rows.push([
            entry.monthLabel,
            entry.eventsCount,
            entry.tensionDays,
            entry.peakReserved,
            entry.minRemaining === null ? "Libre" : entry.minRemaining,
          ].join(","));
        });
      } else {
        rows.push("Date,Stock total,Quantité réservée,Stock restant,Statut");
        materialDaySummary.forEach((entry) => {
          const snapshot = entry.selectedItemStock || {
            reserved: 0,
            total: selectedMaterialInventory.effectiveCapacity ?? selectedMaterialInventory.capacity ?? null,
            remaining: selectedMaterialInventory.effectiveCapacity ?? selectedMaterialInventory.capacity ?? null,
            overbooked: false,
          };
          rows.push([
            entry.iso,
            snapshot.total === null ? "Libre" : snapshot.total,
            snapshot.reserved,
            snapshot.remaining === null ? "Libre" : snapshot.remaining,
            snapshot.overbooked ? "Stock dépassé" : "Disponible",
          ].join(","));
        });
      }
    } else {
      rows.push("Matériel,Stock total,Réservé aujourd'hui,Stock restant aujourd'hui,Statut");
      inventoryItems.forEach((item) => {
        const todaySnapshot = materialStockByDay.get(toIsoDate(today))?.[item.key] || {
          reserved: 0,
          total: item.effectiveCapacity ?? item.capacity ?? null,
          remaining: item.effectiveCapacity ?? item.capacity ?? null,
          overbooked: false,
        };
        rows.push([
          `"${getMaterialEventLabel(item.key)}"`,
          todaySnapshot.total === null ? "Libre" : todaySnapshot.total,
          todaySnapshot.reserved,
          todaySnapshot.remaining === null ? "Libre" : todaySnapshot.remaining,
          todaySnapshot.overbooked ? "Stock dépassé" : "Disponible",
        ].join(","));
      });
    }

    const blob = new Blob([rows.join("\n")], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const anchor = document.createElement("a");
    anchor.href = url;
    anchor.download = selectedMaterialInventory
      ? `disponibilite-${selectedMaterialInventory.key}-${viewMode}-${toIsoDate(currentDate)}.csv`
      : `disponibilite-materiel-${toIsoDate(today)}.csv`;
    anchor.click();
    URL.revokeObjectURL(url);
  };

  const exportMaterialAvailabilityExcel = async () => {
    const XLSX = await loadXlsx();
    if (selectedMaterialInventory) {
      if (viewMode === 'year') {
        const rows = materialYearSummary.map((entry) => ({
          Mois: entry.monthLabel,
          Réservations: entry.eventsCount,
          "Jours bloqués": entry.tensionDays,
          "Pic réservé": entry.peakReserved,
          "Reste minimum": entry.minRemaining === null ? "Libre" : entry.minRemaining,
        }));
        const workbook = XLSX.utils.book_new();
        const worksheet = XLSX.utils.json_to_sheet(rows);
        XLSX.utils.book_append_sheet(workbook, worksheet, "Disponibilité");
        XLSX.writeFile(workbook, `disponibilite-${selectedMaterialInventory.key}-annee-${currentYear}.xlsx`);
        return;
      }

      const rows = materialDaySummary.map((entry) => {
        const snapshot = entry.selectedItemStock || {
          reserved: 0,
          total: selectedMaterialInventory.effectiveCapacity ?? selectedMaterialInventory.capacity ?? null,
          remaining: selectedMaterialInventory.effectiveCapacity ?? selectedMaterialInventory.capacity ?? null,
          overbooked: false,
        };
        return {
          Date: entry.iso,
          "Stock total": snapshot.total === null ? "Libre" : snapshot.total,
          "Quantité réservée": snapshot.reserved,
          "Stock restant": snapshot.remaining === null ? "Libre" : snapshot.remaining,
          Statut: snapshot.overbooked ? "Stock dépassé" : "Disponible",
        };
      });
      const workbook = XLSX.utils.book_new();
      const worksheet = XLSX.utils.json_to_sheet(rows);
      XLSX.utils.book_append_sheet(workbook, worksheet, "Disponibilité");
      XLSX.writeFile(workbook, `disponibilite-${selectedMaterialInventory.key}-${viewMode}-${toIsoDate(currentDate)}.xlsx`);
      return;
    }

    const inventoryItems = ((materialCalendarRaw?.inventory || []) as Array<{
      key: string;
      label: string;
      capacity: number | null;
      effectiveCapacity: number | null;
    }>);
    const rows = inventoryItems.map((item) => {
      const todaySnapshot = materialStockByDay.get(toIsoDate(today))?.[item.key] || {
        reserved: 0,
        total: item.effectiveCapacity ?? item.capacity ?? null,
        remaining: item.effectiveCapacity ?? item.capacity ?? null,
        overbooked: false,
      };
      return {
        Matériel: getMaterialEventLabel(item.key),
        "Stock total": todaySnapshot.total === null ? "Libre" : todaySnapshot.total,
        "Réservé aujourd'hui": todaySnapshot.reserved,
        "Stock restant aujourd'hui": todaySnapshot.remaining === null ? "Libre" : todaySnapshot.remaining,
        Statut: todaySnapshot.overbooked ? "Stock dépassé" : "Disponible",
      };
    });
    const workbook = XLSX.utils.book_new();
    const worksheet = XLSX.utils.json_to_sheet(rows);
    XLSX.utils.book_append_sheet(workbook, worksheet, "Disponibilité");
    XLSX.writeFile(workbook, `disponibilite-materiel-${toIsoDate(today)}.xlsx`);
  };

  return (
    <div className="space-y-6">
      {/* Header with stats */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
        <Card>
          <CardContent className="py-4">
            <div className="flex items-center gap-3">
              <div className="w-10 h-10 rounded-lg bg-[oklch(0.25_0.05_265)]/10 flex items-center justify-center">
                <Calendar className="h-5 w-5 text-[oklch(0.25_0.05_265)]" />
              </div>
              <div>
                <p className="text-2xl font-bold">{resourceMode === 'salles' ? totalReservations : materialStats.total}</p>
                <p className="text-xs text-muted-foreground">{resourceMode === 'salles' ? 'Réservations totales' : 'Dossiers matériel'}</p>
              </div>
            </div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="py-4">
            <div className="flex items-center gap-3">
              <div className="w-10 h-10 rounded-lg bg-green-100 flex items-center justify-center">
                <MapPin className="h-5 w-5 text-green-600" />
              </div>
              <div>
                <p className="text-2xl font-bold">{resourceMode === 'salles' ? reservationsThisMonth : materialStats.activeThisMonth}</p>
                <p className="text-xs text-muted-foreground">{resourceMode === 'salles' ? 'Ce mois-ci' : 'Actifs ce mois'}</p>
              </div>
            </div>
          </CardContent>
        </Card>
        <Card className="md:col-span-2">
          <CardContent className="py-4">
            <div className="flex items-center justify-between gap-3 mb-2">
              <p className="text-xs text-muted-foreground font-medium">
                {resourceMode === 'salles' ? 'Occupation des salles ce mois' : 'Pilotage du matériel et états logistiques'}
              </p>
              {resourceMode === 'salles' && selectedSalleId && (
                <Button variant="ghost" size="sm" onClick={() => setSelectedSalleId(null)}>
                  Réinitialiser
                </Button>
              )}
              {resourceMode === 'materiel' && selectedMaterialKey && (
                <Button variant="ghost" size="sm" onClick={() => setSelectedMaterialKey(null)}>
                  Réinitialiser
                </Button>
              )}
            </div>
            {resourceMode === 'salles' ? (
              <div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
                {SALLES_MJS.map(salle => {
                  const isActive = selectedSalleId === salle.id;
                  return (
                    <button
                      key={salle.id}
                      type="button"
                      onClick={() => setSelectedSalleId(prev => prev === salle.id ? null : salle.id)}
                      className={`rounded-lg border px-3 py-3 text-left transition-all hover:shadow-sm ${
                        isActive ? `${salle.bgLight} border-2` : 'bg-white hover:bg-muted/30'
                      }`}
                    >
                      <div className="flex items-center justify-between gap-3">
                        <div>
                          <p className="text-sm font-medium">{salle.icon} {salle.nom}</p>
                          <p className="text-xs text-muted-foreground mt-1">
                            {salleUsage[salle.nom] || 0} réservation(s)
                          </p>
                        </div>
                        <div className={`h-3 w-3 rounded-full ${salle.color}`} />
                      </div>
                    </button>
                  );
                })}
              </div>
            ) : (
              <div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
                {(materialCalendarRaw?.inventory || []).map((item: any) => (
                  <button
                    key={item.key}
                    type="button"
                    onClick={() => setSelectedMaterialKey((prev) => prev === item.key ? null : item.key)}
                    className={`rounded-lg border px-3 py-3 text-left transition-all hover:shadow-sm ${
                      selectedMaterialKey === item.key ? 'border-2 border-primary bg-primary/5' : 'bg-white hover:bg-muted/30'
                    }`}
                  >
                    <div className="flex items-center justify-between gap-3">
                      <div>
                        <p className="text-sm font-medium">{getMaterialEventLabel(item.key)}</p>
                        <p className="text-xs text-muted-foreground mt-1">
                          {item.capacity === null ? 'Suivi libre' : `${item.capacity} en stock théorique`}
                        </p>
                        <p className="text-xs text-muted-foreground mt-1">
                          {filteredMaterialEvents.filter((event) => event.requestedItems.some((entry) => entry.key === item.key && entry.quantity > 0)).length} demande(s) / réservation(s)
                        </p>
                      </div>
                      <PackageCheck className="h-4 w-4 text-primary" />
                    </div>
                  </button>
                ))}
              </div>
            )}
          </CardContent>
        </Card>
      </div>

      {resourceMode === 'materiel' && (materialCalendarRaw?.conflicts?.length || 0) > 0 && (
        <Card className="border-orange-200 bg-orange-50">
          <CardHeader className="pb-3">
            <CardTitle className="flex items-center gap-2 text-base text-orange-900">
              <ShieldAlert className="h-5 w-5" />
              Alertes de conflit matériel
            </CardTitle>
            <CardDescription className="text-orange-800">
              Le calendrier a détecté des matériels demandés au-delà du stock théorique ou encore signalés en litige.
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-2">
            {(materialCalendarRaw?.conflicts || []).map((conflict: any, index: number) => (
              <div key={`${conflict.requestId}-${conflict.materialKey}-${index}`} className="rounded-lg border border-orange-200 bg-white px-3 py-3 text-sm">
                <p className="font-medium text-orange-900">{conflict.message}</p>
                <p className="mt-1 text-orange-800">
                  Demande #{conflict.requestId} — {conflict.materialLabel}
                </p>
              </div>
            ))}
          </CardContent>
        </Card>
      )}

      {resourceMode === 'salles' && selectedSalle && (
        <Card className="border-primary/20 bg-primary/5">
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <span>{selectedSalle.icon}</span>
              {selectedSalle.nom}
            </CardTitle>
            <div className="text-sm text-muted-foreground">
              Visualisation des réservations en cours et à venir pour cette salle.
            </div>
          </CardHeader>
          <CardContent>
            {salleReservations.length > 0 ? (
              <div className="space-y-3">
                {salleReservations.map(event => (
                  <button
                    key={event.id}
                    type="button"
                    onClick={() => setSelectedEvent(event)}
                    className="w-full rounded-lg border bg-white p-4 text-left transition-colors hover:bg-muted/30"
                  >
                    <div className="flex items-start justify-between gap-4">
                      <div className="space-y-1">
                        <p className="font-medium">{event.associationName}</p>
                        <p className="text-sm text-muted-foreground">{event.titre}</p>
                      </div>
                      <Badge variant="outline" className={selectedSalle.bgLight}>
                        {selectedSalle.nom}
                      </Badge>
                    </div>
                    <div className="mt-3 grid gap-2 text-sm text-muted-foreground md:grid-cols-3">
                      <div className="flex items-center gap-2">
                        <Calendar className="h-4 w-4" />
                        <span>
                          {event.dateDebut.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })}
                          {event.dateFin.getTime() !== event.dateDebut.getTime()
                            ? ` au ${event.dateFin.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })}`
                            : ''}
                        </span>
                      </div>
                      <div className="flex items-center gap-2">
                        <Clock className="h-4 w-4" />
                        <span>{event.scheduleSummary}</span>
                      </div>
                      <div className="flex items-center gap-2">
                        <Users className="h-4 w-4" />
                        <span>{event.nombreParticipants ? `${event.nombreParticipants} participants` : 'Participants non renseignés'}</span>
                      </div>
                    </div>
                  </button>
                ))}
              </div>
            ) : (
              <div className="rounded-lg border bg-white p-6 text-sm text-muted-foreground">
                Aucune réservation en cours ou à venir pour cette salle.
              </div>
            )}
          </CardContent>
        </Card>
      )}

      {resourceMode === 'materiel' && selectedMaterialInventory && (
        <Card className="border-primary/20 bg-primary/5">
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <PackageCheck className="h-5 w-5 text-primary" />
              {getMaterialEventLabel(selectedMaterialInventory.key)}
            </CardTitle>
            <div className="text-sm text-muted-foreground">
              Toutes les demandes et réservations en cours ou à venir associées à ce matériel.
            </div>
          </CardHeader>
          <CardContent>
            {materialReservations.length > 0 ? (
              <div className="space-y-3">
                {materialReservations.map((event) => {
                  const selectedItem = event.requestedItems.find((item) => item.key === selectedMaterialInventory.key);
                  return (
                    <button
                      key={`${selectedMaterialInventory.key}-${event.requestId}`}
                      type="button"
                      onClick={() => setSelectedMaterialEvent(event)}
                      className="w-full rounded-lg border bg-white p-4 text-left transition-colors hover:bg-muted/30"
                    >
                      <div className="flex items-start justify-between gap-4">
                        <div className="space-y-1">
                          <p className="font-medium">{event.associationName}</p>
                          <p className="text-sm text-muted-foreground">{event.title}</p>
                        </div>
                        <div className="flex flex-col items-end gap-2">
                          <Badge variant="outline" className="bg-white">
                            {getMaterialEventLabel(selectedMaterialInventory.key)} x{selectedItem?.quantity || 0}
                          </Badge>
                          <Badge className={materialBoardStateClasses[event.boardState] || 'bg-muted/50'}>
                            {event.boardStateLabel}
                          </Badge>
                        </div>
                      </div>
                      <div className="mt-3 grid gap-2 text-sm text-muted-foreground md:grid-cols-3">
                        <div className="flex items-center gap-2">
                          <Calendar className="h-4 w-4" />
                          <span>
                            {event.useStartDate || event.manifestationStart}
                            {(event.useEndDate || event.restitutionDate) !== (event.useStartDate || event.manifestationStart)
                              ? ` au ${event.useEndDate || event.restitutionDate}`
                              : ''}
                          </span>
                        </div>
                        <div className="flex items-center gap-2">
                          <MapPin className="h-4 w-4" />
                          <span>{event.commune || 'Commune non renseignée'}</span>
                        </div>
                        <div className="flex items-center gap-2">
                          <Clock className="h-4 w-4" />
                          <span>Retrait {event.pickupDate || '-'} • Retour {event.restitutionDate || '-'}</span>
                        </div>
                      </div>
                    </button>
                  );
                })}
              </div>
            ) : (
              <div className="rounded-lg border bg-white p-6 text-sm text-muted-foreground">
                Aucune demande ou réservation en cours ou à venir pour ce matériel.
              </div>
            )}
          </CardContent>
        </Card>
      )}

      {resourceMode === 'materiel' && (
        <Card className="border-primary/20">
          <CardHeader>
            <CardTitle className="flex items-center gap-2">
              <PackageCheck className="h-5 w-5 text-primary" />
              {selectedMaterialInventory
                ? `Stock et disponibilité — ${getMaterialEventLabel(selectedMaterialInventory.key)}`
                : "Stock et disponibilité du matériel"}
            </CardTitle>
            <CardDescription>
              {selectedMaterialInventory
                ? "Stock total, quantité réservée et stock restant sur la période affichée. Clique sur un matériel pour voir toutes ses réservations."
                : "Vue synthétique du stock du jour. Sélectionne un matériel pour afficher le détail jour par jour, semaine par semaine, mois par mois ou sur l’année."}
            </CardDescription>
          </CardHeader>
          <CardContent className="space-y-4">
            <div className="flex flex-wrap gap-2">
              <Button type="button" variant="outline" size="sm" onClick={exportMaterialAvailabilityCsv}>
                <Download className="mr-2 h-4 w-4" />
                Export CSV
              </Button>
              <Button type="button" variant="outline" size="sm" onClick={() => void exportMaterialAvailabilityExcel()}>
                <Download className="mr-2 h-4 w-4" />
                Export Excel
              </Button>
            </div>
            {!selectedMaterialInventory ? (
              <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
                {((materialCalendarRaw?.inventory || []) as any[]).map((item) => {
                  const todaySnapshot = materialStockByDay.get(toIsoDate(today))?.[item.key] || {
                    reserved: 0,
                    total: item.effectiveCapacity ?? item.capacity ?? null,
                    remaining: item.effectiveCapacity ?? item.capacity ?? null,
                    overbooked: false,
                  };
                  return (
                    <button
                      key={`stock-summary-${item.key}`}
                      type="button"
                      onClick={() => setSelectedMaterialKey(item.key)}
                      className="rounded-lg border bg-white p-4 text-left transition-colors hover:bg-muted/30"
                    >
                      <div className="flex items-center justify-between gap-3">
                        <p className="font-medium">{getMaterialEventLabel(item.key)}</p>
                        <PackageCheck className="h-4 w-4 text-primary" />
                      </div>
                      <div className="mt-3 grid grid-cols-3 gap-2 text-xs">
                        <div className="rounded-md bg-muted/30 p-2">
                          <p className="text-muted-foreground">Stock total</p>
                          <p className="font-semibold">{todaySnapshot.total === null ? "Libre" : todaySnapshot.total}</p>
                        </div>
                        <div className="rounded-md bg-muted/30 p-2">
                          <p className="text-muted-foreground">Réservé ajd</p>
                          <p className="font-semibold">{todaySnapshot.reserved}</p>
                        </div>
                        <div className={`rounded-md p-2 ${todaySnapshot.overbooked ? 'bg-red-50 text-red-800' : 'bg-emerald-50 text-emerald-800'}`}>
                          <p className="text-muted-foreground">Restant ajd</p>
                          <p className="font-semibold">{todaySnapshot.remaining === null ? "Libre" : todaySnapshot.remaining}</p>
                        </div>
                      </div>
                    </button>
                  );
                })}
              </div>
            ) : viewMode === 'year' ? (
              <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
                {materialYearSummary.map((month) => (
                  <div
                    key={`material-year-${month.monthLabel}`}
                    className={`rounded-lg border p-4 ${month.tensionDays > 0 ? 'border-red-200 bg-red-50/60' : 'bg-white'}`}
                  >
                    <div className="flex items-center justify-between gap-3">
                      <p className="font-medium">{month.monthLabel}</p>
                      {month.tensionDays > 0 ? (
                        <Badge variant="destructive">{month.tensionDays} jour(s) bloqué(s)</Badge>
                      ) : (
                        <Badge variant="outline">OK</Badge>
                      )}
                    </div>
                    <div className="mt-3 space-y-2 text-sm">
                      <div className="flex items-center justify-between">
                        <span className="text-muted-foreground">Réservations</span>
                        <span className="font-medium">{month.eventsCount}</span>
                      </div>
                      <div className="flex items-center justify-between">
                        <span className="text-muted-foreground">Pic réservé</span>
                        <span className="font-medium">{month.peakReserved}</span>
                      </div>
                      <div className="flex items-center justify-between">
                        <span className="text-muted-foreground">Reste mini</span>
                        <span className={`font-medium ${month.minRemaining !== null && month.minRemaining < 0 ? 'text-red-700' : ''}`}>
                          {month.minRemaining === null ? 'Libre' : month.minRemaining}
                        </span>
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            ) : (
              <div className="space-y-3">
                <div className="rounded-lg border bg-muted/20 px-4 py-3 text-sm">
                  <span className="font-medium">{currentViewLabel}</span>
                  <span className="ml-2 text-muted-foreground">
                    Stock total, réservé et restant par jour pour {getMaterialEventLabel(selectedMaterialInventory.key)}.
                  </span>
                </div>
                <div className="max-h-[28rem] overflow-auto rounded-lg border">
                  <div className="divide-y">
                    {materialDaySummary.map((day) => {
                      const snapshot = day.selectedItemStock || {
                        reserved: 0,
                        total: selectedMaterialInventory.effectiveCapacity ?? selectedMaterialInventory.capacity ?? null,
                        remaining: selectedMaterialInventory.effectiveCapacity ?? selectedMaterialInventory.capacity ?? null,
                        overbooked: false,
                      };
                      return (
                        <div
                          key={`material-day-summary-${day.iso}`}
                          className={`grid gap-3 px-4 py-3 md:grid-cols-[1.5fr_repeat(4,minmax(0,1fr))] ${snapshot.overbooked ? 'bg-red-50/70' : 'bg-white'}`}
                        >
                          <div>
                            <p className="font-medium">{day.date.toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long' })}</p>
                            <p className="text-xs text-muted-foreground">{day.eventsCount} réservation(s) ce jour</p>
                          </div>
                          <div>
                            <p className="text-xs text-muted-foreground">Stock total</p>
                            <p className="font-semibold">{snapshot.total === null ? 'Libre' : snapshot.total}</p>
                          </div>
                          <div>
                            <p className="text-xs text-muted-foreground">Réservé</p>
                            <p className="font-semibold">{snapshot.reserved}</p>
                          </div>
                          <div>
                            <p className="text-xs text-muted-foreground">Restant</p>
                            <p className={`font-semibold ${snapshot.overbooked ? 'text-red-700' : 'text-emerald-700'}`}>
                              {snapshot.remaining === null ? 'Libre' : snapshot.remaining}
                            </p>
                          </div>
                          <div>
                            <p className="text-xs text-muted-foreground">Blocage</p>
                            <p className="font-semibold">{snapshot.overbooked ? 'Stock dépassé' : 'Disponible'}</p>
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              </div>
            )}
          </CardContent>
        </Card>
      )}

      {/* Calendar controls */}
      <Card>
        <CardHeader className="pb-2">
          <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-4">
              <div className="flex items-center gap-1">
                <Button variant="outline" size="icon" onClick={goToPrevious}>
                  <ChevronLeft className="h-4 w-4" />
                </Button>
                <Button variant="outline" size="icon" onClick={goToNext}>
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
              <h2 className="text-base font-bold sm:text-lg">
                {currentViewLabel}
              </h2>
            </div>
            <div className="flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:justify-end">
              <div className="grid grid-cols-2 overflow-hidden rounded-lg border sm:flex">
                <Button
                  variant={resourceMode === 'salles' ? 'default' : 'ghost'}
                  size="sm"
                  className="rounded-none"
                  onClick={() => setResourceMode('salles')}
                >
                  Salles
                </Button>
                <Button
                  variant={resourceMode === 'materiel' ? 'default' : 'ghost'}
                  size="sm"
                  className="rounded-none"
                  onClick={() => setResourceMode('materiel')}
                >
                  Matériel
                </Button>
              </div>
              <Button variant="outline" size="sm" className="w-full sm:w-auto" onClick={goToToday}>
                Aujourd'hui
              </Button>
              <div className="grid grid-cols-2 overflow-hidden rounded-lg border sm:flex">
                <Button 
                  variant={viewMode === 'day' ? 'default' : 'ghost'} 
                  size="sm" 
                  className="rounded-none"
                  onClick={() => setViewMode('day')}
                >
                  Jour
                </Button>
                <Button 
                  variant={viewMode === 'month' ? 'default' : 'ghost'} 
                  size="sm" 
                  className="rounded-none"
                  onClick={() => setViewMode('month')}
                >
                  Mois
                </Button>
                <Button 
                  variant={viewMode === 'week' ? 'default' : 'ghost'} 
                  size="sm" 
                  className="rounded-none"
                  onClick={() => setViewMode('week')}
                >
                  Semaine
                </Button>
                <Button 
                  variant={viewMode === 'year' ? 'default' : 'ghost'} 
                  size="sm" 
                  className="rounded-none"
                  onClick={() => setViewMode('year')}
                >
                  Année
                </Button>
              </div>
              <Button variant="outline" size="icon" className="self-end sm:self-auto" onClick={() => {
                refetch();
                refetchMaterialCalendar();
              }}>
                <RefreshCw className="h-4 w-4" />
              </Button>
            </div>
          </div>
        </CardHeader>
        <CardContent>
          {/* Legend */}
            <div className="flex flex-wrap gap-3 mb-4 pb-3 border-b">
              {resourceMode === 'salles' ? SALLES_MJS.map(salle => (
                <div key={salle.id} className="flex items-center gap-1.5 text-xs">
                  <div className={`w-3 h-3 rounded-sm ${salle.color}`} />
                  <span className="text-muted-foreground">{salle.nom}</span>
                </div>
              )) : Object.entries(materialBoardStateClasses).map(([key, className]) => (
                <div key={key} className="flex items-center gap-1.5 text-xs">
                  <div className={`w-3 h-3 rounded-sm border ${className}`} />
                  <span className="text-muted-foreground">
                    {materialCalendarRaw?.events.find((entry) => entry.boardState === key)?.boardStateLabel
                      || key.replace(/_/g, ' ')}
                  </span>
                </div>
              ))}
              {resourceMode === 'salles' && selectedSalle && (
                <Badge variant="outline" className={selectedSalle.bgLight}>
                  Filtre actif : {selectedSalle.icon} {selectedSalle.nom}
                </Badge>
              )}
              {resourceMode === 'materiel' && selectedMaterialInventory && (
                <Badge variant="outline" className="bg-primary/5 text-primary border-primary/20">
                  Filtre actif : {getMaterialEventLabel(selectedMaterialInventory.key)}
                </Badge>
              )}
            </div>

          {viewMode === 'day' && (
            <div className="space-y-4">
              <div className={`rounded-xl border p-4 ${resourceMode === 'materiel' && materialDaySummary[0]?.overbookedItems.length ? 'border-red-200 bg-red-50/60' : 'bg-white'}`}>
                <div className="flex items-center justify-between gap-3">
                  <div>
                    <p className="text-sm text-muted-foreground">
                      {currentDate.toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })}
                    </p>
                    <p className="text-lg font-semibold">
                      {resourceMode === 'salles' ? `${getEventsForDay(currentDate).length} réservation(s)` : `${getMaterialEventsForDay(currentDate).length} dossier(s) matériel`}
                    </p>
                  </div>
                  {resourceMode === 'materiel' && selectedMaterialInventory && materialDaySummary[0]?.selectedItemStock ? (
                    <Badge variant="outline" className={materialDaySummary[0].selectedItemStock.overbooked ? 'bg-red-100 text-red-700 border-red-200' : 'bg-emerald-100 text-emerald-700 border-emerald-200'}>
                      {materialDaySummary[0].selectedItemStock.remaining === null
                        ? 'Stock libre'
                        : `${materialDaySummary[0].selectedItemStock.remaining} restant(s) / ${materialDaySummary[0].selectedItemStock.total}`}
                    </Badge>
                  ) : null}
                </div>
              </div>

              <div className="space-y-3">
                {(resourceMode === 'salles' ? getEventsForDay(currentDate) : getMaterialEventsForDay(currentDate)).map((event: any) => (
                  <button
                    key={resourceMode === 'salles' ? event.id : event.requestId}
                    onClick={() => resourceMode === 'salles' ? setSelectedEvent(event as ReservationEvent) : setSelectedMaterialEvent(event as MaterialCalendarEvent)}
                    className={`w-full rounded-lg border p-4 text-left transition-colors hover:bg-muted/30 ${
                      resourceMode === 'salles'
                        ? 'bg-white'
                        : materialBoardStateClasses[(event as MaterialCalendarEvent).boardState] || 'bg-muted/50'
                    }`}
                  >
                    <div className="flex items-start justify-between gap-3">
                      <div>
                        <p className="font-medium">{resourceMode === 'salles' ? (event as ReservationEvent).associationName : (event as MaterialCalendarEvent).associationName}</p>
                        <p className="text-sm text-muted-foreground">{resourceMode === 'salles' ? (event as ReservationEvent).titre : (event as MaterialCalendarEvent).title}</p>
                      </div>
                      {resourceMode === 'materiel' && (
                        <Badge className={materialBoardStateClasses[(event as MaterialCalendarEvent).boardState] || 'bg-muted/50'}>
                          {(event as MaterialCalendarEvent).boardStateLabel}
                        </Badge>
                      )}
                    </div>
                    <div className="mt-3 text-sm text-muted-foreground">
                      {resourceMode === 'salles'
                        ? (event as ReservationEvent).scheduleSummary || 'Horaires non renseignés'
                        : (event as MaterialCalendarEvent).requestedItems.map((item) => `${item.label} x${item.quantity}`).join(', ')}
                    </div>
                  </button>
                ))}
                {(resourceMode === 'salles' ? getEventsForDay(currentDate) : getMaterialEventsForDay(currentDate)).length === 0 && (
                  <div className="rounded-lg border border-dashed p-6 text-center text-sm text-muted-foreground">
                    Aucune réservation sur cette journée.
                  </div>
                )}
              </div>
            </div>
          )}

          {/* Month view */}
          {viewMode === 'month' && (
            <div className="overflow-x-auto">
              <div className="grid min-w-[42rem] grid-cols-7 gap-px overflow-hidden rounded-lg bg-border">
              {/* Day headers */}
              {DAY_NAMES.map(day => (
                <div key={day} className="bg-muted/50 p-2 text-center text-xs font-medium text-muted-foreground">
                  {day}
                </div>
              ))}
              {/* Day cells */}
              {days.map((date, i) => {
                const events = resourceMode === 'salles' ? getEventsForDay(date) : getMaterialEventsForDay(date);
                const isCurrentMonth = date.getMonth() === currentMonth;
                const isToday = isSameDay(date, today);
                return (
                  <div
                    key={i}
                    className={`bg-background min-h-[90px] p-1 ${!isCurrentMonth ? 'opacity-40' : ''} ${isToday ? 'ring-2 ring-[oklch(0.25_0.05_265)] ring-inset' : ''} ${
                      resourceMode === 'materiel' && (
                        selectedMaterialKey
                          ? Boolean(materialStockByDay.get(toIsoDate(date))?.[selectedMaterialKey]?.overbooked)
                          : Boolean(materialDaySummary.find((entry) => entry.iso === toIsoDate(date))?.overbookedItems.length)
                      )
                        ? 'bg-red-50/70'
                        : ''
                    }`}
                  >
                    <div className={`text-xs font-medium mb-1 px-1 ${isToday ? 'text-[oklch(0.25_0.05_265)]' : 'text-muted-foreground'}`}>
                      {date.getDate()}
                    </div>
                    {resourceMode === 'materiel' && selectedMaterialKey && isCurrentMonth && (
                      <div className="mb-1 px-1">
                        {(() => {
                          const stock = materialStockByDay.get(toIsoDate(date))?.[selectedMaterialKey];
                          if (!stock) return <div className="text-[10px] text-muted-foreground">0 / {selectedMaterialInventory?.effectiveCapacity ?? selectedMaterialInventory?.capacity ?? 'libre'}</div>;
                          return (
                            <div className={`text-[10px] font-medium ${stock.overbooked ? 'text-red-700' : 'text-emerald-700'}`}>
                              {stock.remaining === null ? 'Libre' : `${stock.remaining}/${stock.total}`}
                            </div>
                          );
                        })()}
                      </div>
                    )}
                    <div className="space-y-0.5">
                      {events.slice(0, 3).map((event: any) => (
                        <button
                          key={resourceMode === 'salles' ? event.id : event.requestId}
                          onClick={() => resourceMode === 'salles' ? setSelectedEvent(event as ReservationEvent) : setSelectedMaterialEvent(event as MaterialCalendarEvent)}
                          className="w-full text-left"
                        >
                          {resourceMode === 'salles' ? (
                            <div className="flex items-center gap-1 px-1 py-0.5 rounded text-[10px] leading-tight hover:opacity-80 transition-opacity bg-muted/50">
                              {(event as ReservationEvent).salles.slice(0, 2).map((salle, si) => (
                                <div key={si} className={`w-2 h-2 rounded-full flex-shrink-0 ${getSalleColor(salle)}`} />
                              ))}
                              <span className="truncate font-medium">{(event as ReservationEvent).associationName}</span>
                            </div>
                          ) : (
                            <div className={`flex items-center gap-1 px-1 py-0.5 rounded text-[10px] leading-tight hover:opacity-80 transition-opacity border ${materialBoardStateClasses[(event as MaterialCalendarEvent).boardState] || 'bg-muted/50'}`}>
                              <div className="w-2 h-2 rounded-full bg-primary flex-shrink-0" />
                              <span className="truncate font-medium">{(event as MaterialCalendarEvent).associationName}</span>
                            </div>
                          )}
                        </button>
                      ))}
                      {events.length > 3 && (
                        <div className="text-[10px] text-muted-foreground px-1">
                          +{events.length - 3} autres
                        </div>
                      )}
                    </div>
                  </div>
                );
              })}
              </div>
            </div>
          )}

          {/* Week view */}
          {viewMode === 'week' && (
            <div className="overflow-x-auto">
              <div className="grid min-w-[42rem] grid-cols-7 gap-2">
              {weekDays.map((date, i) => {
                const events = resourceMode === 'salles' ? getEventsForDay(date) : getMaterialEventsForDay(date);
                const isToday = isSameDay(date, today);
                const selectedDayStock = resourceMode === 'materiel' && selectedMaterialKey
                  ? materialStockByDay.get(toIsoDate(date))?.[selectedMaterialKey]
                  : null;
                return (
                  <div key={i} className={`rounded-lg border p-2 min-h-[200px] ${isToday ? 'border-[oklch(0.25_0.05_265)] bg-[oklch(0.25_0.05_265)]/5' : ''} ${
                    selectedDayStock?.overbooked ? 'border-red-200 bg-red-50/60' : ''
                  }`}>
                    <div className="text-center mb-2">
                      <div className="text-xs text-muted-foreground">{DAY_NAMES[i]}</div>
                      <div className={`text-lg font-bold ${isToday ? 'text-[oklch(0.25_0.05_265)]' : ''}`}>
                        {date.getDate()}
                      </div>
                      {resourceMode === 'materiel' && selectedMaterialKey && (
                        <div className={`mt-1 text-[10px] font-medium ${selectedDayStock?.overbooked ? 'text-red-700' : 'text-emerald-700'}`}>
                          {selectedDayStock
                            ? selectedDayStock.remaining === null
                              ? 'Libre'
                              : `${selectedDayStock.remaining}/${selectedDayStock.total}`
                            : `0/${selectedMaterialInventory?.effectiveCapacity ?? selectedMaterialInventory?.capacity ?? 'libre'}`}
                        </div>
                      )}
                    </div>
                    <div className="space-y-1.5">
                      {events.map((event: any) => (
                        <button
                          key={resourceMode === 'salles' ? event.id : event.requestId}
                          onClick={() => resourceMode === 'salles' ? setSelectedEvent(event as ReservationEvent) : setSelectedMaterialEvent(event as MaterialCalendarEvent)}
                          className={`w-full text-left p-1.5 rounded border text-xs hover:shadow-sm transition-shadow ${
                            resourceMode === 'salles'
                              ? getSalleBgLight((event as ReservationEvent).salles[0] || '')
                              : materialBoardStateClasses[(event as MaterialCalendarEvent).boardState] || 'bg-muted/50'
                          }`}
                        >
                          <div className="font-medium truncate">{resourceMode === 'salles' ? (event as ReservationEvent).associationName : (event as MaterialCalendarEvent).associationName}</div>
                          {resourceMode === 'salles' ? (
                            <>
                              {(event as ReservationEvent).scheduleSummary && (
                                <div className="text-muted-foreground flex items-center gap-1 mt-0.5">
                                  <Clock className="h-2.5 w-2.5" />
                                  {(event as ReservationEvent).scheduleSummary}
                                </div>
                              )}
                              <div className="flex gap-0.5 mt-1">
                                {(event as ReservationEvent).salles.map((salle, si) => (
                                  <div key={si} className={`w-2 h-2 rounded-full ${getSalleColor(salle)}`} />
                                ))}
                              </div>
                            </>
                          ) : (
                            <div className="text-muted-foreground flex items-center gap-1 mt-0.5">
                              <PackageCheck className="h-2.5 w-2.5" />
                              {(event as MaterialCalendarEvent).requestedItems.map((item) => `${item.label} x${item.quantity}`).join(', ')}
                            </div>
                          )}
                        </button>
                      ))}
                      {events.length === 0 && (
                        <div className="text-center text-[10px] text-muted-foreground py-4 opacity-50">
                          Aucune réservation
                        </div>
                      )}
                    </div>
                  </div>
                );
              })}
              </div>
            </div>
          )}

          {viewMode === 'year' && (
            <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
              {yearMonths.map((monthDate) => {
                const monthIndex = monthDate.getMonth();
                const monthReservations = resourceMode === 'salles'
                  ? reservations.filter((event) => event.dateDebut.getMonth() === monthIndex && event.dateDebut.getFullYear() === currentYear)
                  : [];
                const monthMaterialSummary = resourceMode === 'materiel'
                  ? materialYearSummary.find((entry) => entry.monthDate.getMonth() === monthIndex)
                  : materialYearSummary.find((entry) => entry.monthDate.getMonth() === monthIndex);
                return (
                  <button
                    key={`year-month-${monthIndex}`}
                    type="button"
                    onClick={() => {
                      setCurrentDate(new Date(currentYear, monthIndex, 1));
                      setViewMode('month');
                    }}
                    className={`rounded-lg border p-4 text-left transition-colors hover:bg-muted/30 ${
                      resourceMode === 'materiel' && monthMaterialSummary && monthMaterialSummary.tensionDays > 0
                        ? 'border-red-200 bg-red-50/60'
                        : 'bg-white'
                    }`}
                  >
                    <div className="flex items-center justify-between gap-3">
                      <p className="font-medium">{MONTH_NAMES[monthIndex]}</p>
                      <Badge variant="outline">
                        {resourceMode === 'salles'
                          ? `${monthReservations.length} réservation(s)`
                          : `${monthMaterialSummary?.eventsCount || 0} dossier(s)`}
                      </Badge>
                    </div>
                    {resourceMode === 'materiel' && monthMaterialSummary ? (
                      <div className="mt-3 space-y-1 text-sm text-muted-foreground">
                        <p>Jours bloqués : <span className="font-medium text-foreground">{monthMaterialSummary.tensionDays}</span></p>
                        {selectedMaterialKey && (
                          <>
                            <p>Pic réservé : <span className="font-medium text-foreground">{monthMaterialSummary.peakReserved}</span></p>
                            <p>Reste mini : <span className={`font-medium ${monthMaterialSummary.minRemaining !== null && monthMaterialSummary.minRemaining < 0 ? 'text-red-700' : 'text-foreground'}`}>{monthMaterialSummary.minRemaining === null ? 'Libre' : monthMaterialSummary.minRemaining}</span></p>
                          </>
                        )}
                      </div>
                    ) : (
                      <div className="mt-3 text-sm text-muted-foreground">
                        Cliquer pour ouvrir le mois.
                      </div>
                    )}
                  </button>
                );
              })}
            </div>
          )}
        </CardContent>
      </Card>

      {/* Event detail dialog */}
      <Dialog open={!!selectedEvent && !showChangeSalleDialog} onOpenChange={() => setSelectedEvent(null)}>
        <DialogContent className="max-w-lg">
          {selectedEvent && (
            <>
              <DialogHeader>
                <DialogTitle className="flex items-center gap-2">
                  <Calendar className="h-5 w-5 text-[oklch(0.25_0.05_265)]" />
                  Détails de la réservation
                </DialogTitle>
                <DialogDescription>{selectedEvent.titre}</DialogDescription>
              </DialogHeader>
              <div className="space-y-4 py-2">
                {/* Association */}
                <div className="flex items-start gap-3">
                  <Building2 className="h-4 w-4 text-muted-foreground mt-0.5" />
                  <div>
                    <p className="font-medium text-sm">{selectedEvent.associationName}</p>
                    {selectedEvent.associationEmail && (
                      <p className="text-xs text-muted-foreground">{selectedEvent.associationEmail}</p>
                    )}
                  </div>
                </div>

                <Separator />

                {/* Salles */}
                <div>
                  <p className="text-xs font-medium text-muted-foreground mb-2">Salles attribuées</p>
                  <div className="flex flex-wrap gap-2">
                    {selectedEvent.salles.map((salle, i) => {
                      const config = SALLES_MJS.find(s => s.nom === salle || s.id === salle);
                      return (
                        <Badge key={i} variant="outline" className={config?.bgLight || ''}>
                          {config?.icon} {salle}
                        </Badge>
                      );
                    })}
                  </div>
                </div>

                <Separator />

                {/* Dates et horaires */}
                <div className="grid grid-cols-2 gap-3 text-sm">
                  <div>
                    <p className="text-xs text-muted-foreground">Date début</p>
                    <p className="font-medium">{selectedEvent.dateDebut.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })}</p>
                  </div>
                  <div>
                    <p className="text-xs text-muted-foreground">Date fin</p>
                    <p className="font-medium">{selectedEvent.dateFin.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })}</p>
                  </div>
                  {selectedEvent.scheduleSummary && (
                    <div>
                      <p className="text-xs text-muted-foreground">Organisation horaire</p>
                      <p className="font-medium">{selectedEvent.scheduleSummary}</p>
                    </div>
                  )}
                  {selectedEvent.horairesParJour.length > 0 && (
                    <div className="col-span-2">
                      <p className="text-xs text-muted-foreground mb-2">Détail par journée</p>
                      <div className="space-y-2">
                        {selectedEvent.horairesParJour.map((slot) => (
                          <div key={slot.date} className="flex justify-between rounded-md bg-muted/40 px-3 py-2 text-sm">
                            <span className="font-medium">{new Date(`${slot.date}T12:00:00`).toLocaleDateString('fr-FR')}</span>
                            <span>{slot.heureDebut || '?'} — {slot.heureFin || '?'}</span>
                          </div>
                        ))}
                      </div>
                    </div>
                  )}
                  {selectedEvent.nombreParticipants && (
                    <div>
                      <p className="text-xs text-muted-foreground">Participants</p>
                      <p className="font-medium">{selectedEvent.nombreParticipants} personnes</p>
                    </div>
                  )}
                </div>

                {/* Motif */}
                {selectedEvent.motif && (
                  <>
                    <Separator />
                    <div>
                      <p className="text-xs text-muted-foreground mb-1">Motif</p>
                      <p className="text-sm">{selectedEvent.motif}</p>
                    </div>
                  </>
                )}
              </div>
              <DialogFooter className="gap-2">
                <Link href={`/dashboard/requests/${selectedEvent.id}`}>
                  <Button variant="outline" size="sm">
                    Voir la demande
                  </Button>
                </Link>
                {!readOnly && (
                  <Button 
                    size="sm" 
                    onClick={() => openChangeSalleDialog(selectedEvent)}
                    className="bg-[oklch(0.25_0.05_265)] hover:bg-[oklch(0.30_0.05_265)]"
                  >
                    <Edit className="mr-2 h-4 w-4" />
                    Modifier les salles
                  </Button>
                )}
              </DialogFooter>
            </>
          )}
        </DialogContent>
      </Dialog>

      <Dialog open={!!selectedMaterialEvent} onOpenChange={() => setSelectedMaterialEvent(null)}>
        <DialogContent className="max-w-xl">
          {selectedMaterialEvent && (
            <>
              <DialogHeader>
                <DialogTitle className="flex items-center gap-2">
                  <PackageCheck className="h-5 w-5 text-primary" />
                  Dossier matériel
                </DialogTitle>
                <DialogDescription>{selectedMaterialEvent.title}</DialogDescription>
              </DialogHeader>
              <div className="space-y-4 py-2">
                <div className="flex items-start justify-between gap-3">
                  <div>
                    <p className="font-medium text-sm">{selectedMaterialEvent.associationName}</p>
                    <p className="text-xs text-muted-foreground">{selectedMaterialEvent.commune || 'Commune non renseignée'}</p>
                  </div>
                  <Badge className={materialBoardStateClasses[selectedMaterialEvent.boardState] || 'bg-muted/50'}>
                    {selectedMaterialEvent.boardStateLabel}
                  </Badge>
                </div>

                <Separator />

                <div className="grid gap-3 text-sm md:grid-cols-2">
                  <div>
                    <p className="text-xs text-muted-foreground">Mise à disposition</p>
                    <p className="font-medium">{selectedMaterialEvent.pickupDate || '-'}</p>
                  </div>
                  <div>
                    <p className="text-xs text-muted-foreground">Restitution</p>
                    <p className="font-medium">{selectedMaterialEvent.restitutionDate || '-'}</p>
                  </div>
                  <div>
                    <p className="text-xs text-muted-foreground">Manifestation</p>
                    <p className="font-medium">
                      {selectedMaterialEvent.manifestationStart || '-'}
                      {selectedMaterialEvent.manifestationEnd && selectedMaterialEvent.manifestationEnd !== selectedMaterialEvent.manifestationStart
                        ? ` au ${selectedMaterialEvent.manifestationEnd}`
                        : ''}
                    </p>
                  </div>
                  <div>
                    <p className="text-xs text-muted-foreground">Service assigné</p>
                    <p className="font-medium">{selectedMaterialEvent.logisticServiceLabel || 'Non attribué'}</p>
                  </div>
                </div>

                <div>
                  <p className="text-xs text-muted-foreground mb-2">Matériel concerné</p>
                  <div className="space-y-2">
                    {selectedMaterialEvent.requestedItems.map((item) => (
                      <div key={item.key} className="flex items-center justify-between rounded-md border bg-muted/20 px-3 py-2 text-sm">
                        <span className="font-medium">{item.label}</span>
                        <span>x{item.quantity}</span>
                      </div>
                    ))}
                  </div>
                </div>

                {selectedMaterialEvent.issueFlag ? (
                  <div className="rounded-lg border border-orange-200 bg-orange-50 p-3 text-sm text-orange-900">
                    <div className="flex items-center gap-2 font-medium">
                      <ShieldAlert className="h-4 w-4" />
                      Alerte dégradation / litige
                    </div>
                    <p className="mt-1 text-orange-800">
                      Ce matériel a été signalé non conforme. Prévoir réparation, remplacement ou traitement de la caution avant la prochaine mise à disposition.
                    </p>
                  </div>
                ) : null}

                {selectedMaterialEvent.motif ? (
                  <div>
                    <p className="text-xs text-muted-foreground mb-1">Motif</p>
                    <p className="text-sm">{selectedMaterialEvent.motif}</p>
                  </div>
                ) : null}
              </div>
              <DialogFooter className="gap-2">
                <Link href={`/dashboard/requests/${selectedMaterialEvent.requestId}`}>
                  <Button variant="outline" size="sm">
                    Voir la demande
                  </Button>
                </Link>
                {!readOnly && (
                  <Link href="/admin?tab=logistique">
                    <Button variant="outline" size="sm">
                      Réassigner à un autre agent
                    </Button>
                  </Link>
                )}
                {selectedMaterialEvent.finalPdfUrl ? (
                  <a
                    href={buildMaterialReturnFinalPdfViewerHref({
                      url: selectedMaterialEvent.finalPdfUrl,
                      returnTo: "/admin?tab=calendrier",
                      title: "Consulter le PDF final de restitution",
                      downloadName: `fiche-finale-restitution-${selectedMaterialEvent.requestId}.pdf`,
                    })}
                  >
                    <Button size="sm">
                      <ExternalLink className="mr-2 h-4 w-4" />
                      Télécharger le PDF
                    </Button>
                  </a>
                ) : !readOnly && selectedMaterialEvent.uploadLink ? (
                  <a href={selectedMaterialEvent.uploadLink} target="_blank" rel="noopener noreferrer">
                    <Button size="sm">
                      <ExternalLink className="mr-2 h-4 w-4" />
                      Ouvrir le lien terrain
                    </Button>
                  </a>
                ) : null}
              </DialogFooter>
            </>
          )}
        </DialogContent>
      </Dialog>

      {/* Change salle dialog */}
      <Dialog open={!readOnly && showChangeSalleDialog} onOpenChange={(open) => {
        if (!open) {
          setShowChangeSalleDialog(false);
        }
      }}>
        <DialogContent className="max-w-md">
          {selectedEvent && (
            <>
              <DialogHeader>
                <DialogTitle>Modifier l'attribution des salles</DialogTitle>
                <DialogDescription>
                  {selectedEvent.associationName} — {selectedEvent.dateDebut.toLocaleDateString('fr-FR')}
                  {selectedEvent.scheduleSummary && ` — ${selectedEvent.scheduleSummary}`}
                </DialogDescription>
              </DialogHeader>
              <div className="space-y-4 py-2">
                {/* Current salles */}
                <div className="bg-muted/50 rounded-lg p-3">
                  <p className="text-xs font-medium text-muted-foreground mb-2">Salles actuelles</p>
                  <div className="flex flex-wrap gap-1.5">
                    {selectedEvent.salles.map((salle, i) => {
                      const config = SALLES_MJS.find(s => s.nom === salle);
                      return (
                        <Badge key={i} variant="secondary" className="text-xs">
                          {config?.icon} {salle}
                        </Badge>
                      );
                    })}
                  </div>
                </div>

                {/* New salles selection */}
                <div>
                  <Label className="text-sm font-medium">Nouvelles salles *</Label>
                  <div className="grid grid-cols-2 gap-2 mt-2">
                    {SALLES_MJS.map(salle => (
                      <div
                        key={salle.id}
                        className={`flex items-center space-x-2 p-2.5 rounded-lg border cursor-pointer transition-colors ${
                          newSallesIds.includes(salle.id) 
                            ? `${salle.bgLight} border-2` 
                            : 'hover:bg-muted/50'
                        }`}
                        onClick={() => toggleSalle(salle.id)}
                      >
                        <Checkbox
                          checked={newSallesIds.includes(salle.id)}
                          onCheckedChange={() => toggleSalle(salle.id)}
                        />
                        <div className="text-xs">
                          <span className="mr-1">{salle.icon}</span>
                          <span className="font-medium">{salle.nom}</span>
                        </div>
                      </div>
                    ))}
                  </div>
                </div>

                {/* Raison */}
                <div className="space-y-2">
                  <Label className="text-sm font-medium">Raison du changement *</Label>
                  <Textarea
                    value={changeRaison}
                    onChange={(e) => setChangeRaison(e.target.value)}
                    placeholder="Ex: Une autre association nécessite une salle plus grande pour un événement le même jour..."
                    rows={3}
                  />
                  <p className="text-xs text-muted-foreground">
                    Cette raison sera communiquée à l'association {selectedEvent.associationName}.
                  </p>
                </div>
              </div>
              <DialogFooter>
                <Button variant="outline" onClick={() => setShowChangeSalleDialog(false)}>
                  Annuler
                </Button>
                <Button
                  onClick={handleChangeSalles}
                  disabled={changeSallesMutation.isPending || newSallesIds.length === 0 || !changeRaison.trim()}
                  className="bg-[oklch(0.25_0.05_265)] hover:bg-[oklch(0.30_0.05_265)]"
                >
                  {changeSallesMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <Edit className="mr-2 h-4 w-4" />
                  )}
                  Confirmer le changement
                </Button>
              </DialogFooter>
            </>
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}
