import { useAuth } from "@/_core/hooks/useAuth";
import { AuthenticatedPageSkeleton } from "@/components/AuthenticatedPageSkeleton";
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 { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { Checkbox } from "@/components/ui/checkbox";
import { Separator } from "@/components/ui/separator";
import { buildRoutePrefetchHandlers } from "@/lib/routePrefetch";
import { trpc } from "@/lib/trpc";
import { ArrowLeft, Calendar, CheckCircle, ClipboardList, Clock, Copy, Download, Edit, Euro, FileText, Loader2, RotateCcw, Send, XCircle, Settings, Building2, Shield, AlertTriangle, MapPin, Users, CalendarDays, Trash2, ExternalLink, Ban, MoreHorizontal } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { Link, useParams, useLocation } from "wouter";
import { toast } from "sonner";
import { useEffect, useMemo, useState, type ReactNode } from "react";
import { emptyMaterialEventQuantities, emptyMaterialEventQuantityMap, emptyMaterialEventSelection, materialEventItems, parseMaterialEventQuantity } from "@/lib/materialEvent";
import { appendReturnToParam, buildMaterialReturnFinalPdfViewerHref } from "@/lib/materialReturnFinalPdf";
import { formatReservationSallePeriod, getReservationSalleScheduleSummary } from "@/lib/reservationSalle";
import {
  buildDecisionAdministrativeText,
  computeSallePricing,
  CONDITIONS_FINANCIERES_SALLE_TEXT,
  SALLE_FREQUENCY_LABELS,
  SALLE_USAGE_TYPE_LABELS,
  SALLE_WORKFLOW_PAYMENT_STATUS_LABELS,
  type SalleReservationFrequency,
  type SalleUsageType,
  type SalleWorkflowPaymentStatus,
} from "@shared/sallePricing";
import ccdsLogo from "@/assets/ccds.png";

type MaterialFinancialMode = "gratuite" | "gratuite_avec_caution" | "location_payante";
type MaterialContractStatus = "a_generer" | "generee" | "signee" | "refusee" | "annulee";
type SalleWorkflowQuoteStatus = "a_preparer" | "en_attente_association" | "accepte" | "refuse";
type SalleWorkflowDirectorStatus = "a_transmettre" | "en_attente_signature" | "signee";
type SalleFinalNotificationPreview = {
  associationName: string;
  datesLabel: string;
  billed: boolean;
  pricingTotalCents: number;
  quotePdfUrl: string;
  quotePdfName: string;
  decisionPdfUrl: string;
  decisionPdfName: string;
  requestPdfUrl: string;
  requestPdfName: string;
  invoicePdfUrl: string;
  invoicePdfName: string;
  invoiceGeneratedAt: string;
  ribDocumentUrl: string;
  ribDocumentName: string;
  mailPreview: string;
};
type SalleFinalDocumentPreview = {
  title: string;
  url: string;
};

const sallePaymentStatusClasses: Record<SalleWorkflowPaymentStatus, string> = {
  en_attente_paiement: "bg-amber-100 text-amber-800 border-amber-200",
  paiement_partiel: "bg-orange-100 text-orange-800 border-orange-200",
  paiement_recu: "bg-sky-100 text-sky-800 border-sky-200",
  paiement_valide: "bg-emerald-100 text-emerald-800 border-emerald-200",
};

/** Component to display a document row with download link */
function DocumentRow({ doc }: { doc: any }) {
  const { data: downloadData } = trpc.document.getDownloadUrl.useQuery(
    { id: doc.id },
    { enabled: !!doc.id }
  );

  const formatFileSize = (bytes: number) => {
    if (bytes < 1024) return `${bytes} o`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} Ko`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} Mo`;
  };

  return (
    <div className="flex items-center justify-between p-3 rounded-lg border bg-muted/30 hover:bg-muted/50 transition-colors">
      <div className="flex items-center gap-3">
        <FileText className="h-5 w-5 text-primary shrink-0" />
        <div>
          <p className="text-sm font-medium">{doc.nom || doc.filename || 'Document'}</p>
          <p className="text-xs text-muted-foreground">
            {doc.type && <span className="capitalize">{doc.type.replace(/_/g, ' ')}</span>}
            {doc.fileSize && <span> — {formatFileSize(doc.fileSize)}</span>}
          </p>
        </div>
      </div>
      {downloadData?.url && (
        <a href={downloadData.url} target="_blank" rel="noopener noreferrer">
          <Button variant="outline" size="sm">
            <Download className="mr-1.5 h-3.5 w-3.5" />
            Télécharger
          </Button>
        </a>
      )}
    </div>
  );
}

const requestTypeLabels: Record<string, string> = {
  subvention_fonctionnement: 'Subvention de fonctionnement',
  subvention_projet: 'Subvention de projet',
  agrement_jeunesse_education: 'Agrément Jeunesse et Éducation Populaire',
  agrement_sport: 'Agrément Sport',
  autorisation_occupation: 'Autorisation d\'occupation',
  demande_salle: 'Demande de salle',
  demande_materiel_evenementiel: 'Demande du matériel événementiel',
  autre: 'Autre demande',
};

const materialReturnStatusLabels: Record<string, string> = {
  planifie: 'Planifié',
  en_attente: 'En attente',
  en_cours: 'En cours',
  cloture: 'Clôturé / Récupéré',
};

const materialReturnStatusClasses: Record<string, string> = {
  planifie: 'bg-slate-100 text-slate-700 border-slate-200',
  en_attente: 'bg-red-100 text-red-700 border-red-200',
  en_cours: 'bg-amber-100 text-amber-700 border-amber-200',
  cloture: 'bg-green-100 text-green-700 border-green-200',
};

const materialReturnUploadLinkStateLabels: Record<string, string> = {
  active: "Actif",
  expired: "Expiré",
  closed: "Clôturé",
};

const materialReturnUploadLinkStateClasses: Record<string, string> = {
  active: "bg-emerald-100 text-emerald-800 border-emerald-200",
  expired: "bg-red-100 text-red-700 border-red-200",
  closed: "bg-slate-100 text-slate-700 border-slate-200",
};

const avisDSULabels: Record<string, { label: string; className: string }> = {
  favorable: { label: 'Favorable', className: 'bg-green-100 text-green-800 border-green-200' },
  defavorable: { label: 'Défavorable', className: 'bg-red-100 text-red-800 border-red-200' },
  favorable_avec_reserves: { label: 'Favorable avec réserves', className: 'bg-amber-100 text-amber-800 border-amber-200' },
};

function getStatusConfig(status: string) {
  const configs: Record<string, { label: string; className: string }> = {
    brouillon: { label: 'Brouillon', className: 'bg-gray-100 text-gray-700' },
    soumise: { label: 'Soumise', className: 'bg-blue-100 text-blue-700' },
    en_cours_traitement: { label: 'En cours de traitement', className: 'bg-yellow-100 text-yellow-700' },
    information_complementaire: { label: 'Information complémentaire requise', className: 'bg-orange-100 text-orange-700' },
    validee: { label: 'Validée', className: 'bg-green-100 text-green-700' },
    refusee: { label: 'Refusée', className: 'bg-red-100 text-red-700' },
    annulee: { label: 'Annulée', className: 'bg-gray-100 text-gray-500' },
  };
  return configs[status] || configs.brouillon;
}

function getReservationDailySlots(formData: any) {
  return Array.isArray(formData?.horairesParJour)
    ? formData.horairesParJour.filter((slot: any) => slot?.date)
    : [];
}

function StatusIcon({ status }: { status: string }) {
  switch (status) {
    case 'brouillon':
      return <FileText className="h-5 w-5" />;
    case 'soumise':
      return <Send className="h-5 w-5" />;
    case 'en_cours_traitement':
      return <Clock className="h-5 w-5" />;
    case 'information_complementaire':
      return <FileText className="h-5 w-5" />;
    case 'validee':
      return <CheckCircle className="h-5 w-5" />;
    case 'refusee':
      return <XCircle className="h-5 w-5" />;
    default:
      return <FileText className="h-5 w-5" />;
  }
}

/** Helper to format a date string nicely */
function formatDateFr(dateStr: string | Date | null | undefined): string {
  if (!dateStr) return '-';
  try {
    return new Date(dateStr).toLocaleDateString('fr-FR', {
      weekday: 'long',
      day: 'numeric',
      month: 'long',
      year: 'numeric',
    });
  } catch {
    return String(dateStr);
  }
}

function formatMaterialEventPeriod(formData: any): string {
  const start = formData?.dateDebutManifestation || formData?.dateManifestation;
  const end = formData?.dateFinManifestation || formData?.dateManifestation;

  if (!start && !end) return '-';
  if (start && end && start !== end) {
    return `${formatDateFr(start)} au ${formatDateFr(end)}`;
  }
  return formatDateFr(start || end);
}

function DetailLine({ label, value }: { label: string; value?: string | null }) {
  return (
    <div className="flex justify-between py-1.5 border-b border-dashed text-sm">
      <span className="text-muted-foreground">{label} :</span>
      <span className="font-medium text-right max-w-[60%]">{value || '-'}</span>
    </div>
  );
}

function DetailOverflowMenu({
  label = "Autres actions",
  children,
}: {
  label?: string;
  children: ReactNode;
}) {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline" size="sm" className="h-11 w-11 p-0 sm:h-9 sm:w-9" aria-label={label}>
          <MoreHorizontal className="h-4 w-4" />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="w-60">
        {children}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

function formatCentsAsEuroInput(cents: number | null | undefined) {
  if (cents === null || cents === undefined) return "";
  return String((cents / 100).toFixed(2));
}

function parseEuroInputToCents(value: string) {
  const normalized = String(value || "").trim().replace(",", ".");
  if (!normalized) return 0;
  const parsed = Number.parseFloat(normalized);
  if (!Number.isFinite(parsed) || parsed < 0) return 0;
  return Math.round(parsed * 100);
}

function getFinancialModeLabel(mode: MaterialFinancialMode | string | null | undefined) {
  switch (mode) {
    case 'gratuite':
      return 'Mise à disposition gratuite';
    case 'gratuite_avec_caution':
      return 'Mise à disposition gratuite avec caution';
    case 'location_payante':
      return 'Location payante';
    default:
      return '-';
  }
}

function getContractStatusLabel(status: MaterialContractStatus | string | null | undefined) {
  switch (status) {
    case 'a_generer':
      return 'À générer';
    case 'generee':
      return 'Générée';
    case 'signee':
      return 'Signée';
    case 'refusee':
      return 'Refusée';
    case 'annulee':
      return 'Annulée';
    default:
      return '-';
  }
}

function getContractStatusBadgeClass(status: MaterialContractStatus | string | null | undefined) {
  switch (status) {
    case 'a_generer':
      return 'bg-slate-100 text-slate-700 border-slate-200';
    case 'generee':
      return 'bg-blue-100 text-blue-700 border-blue-200';
    case 'signee':
      return 'bg-green-100 text-green-700 border-green-200';
    case 'refusee':
      return 'bg-red-100 text-red-700 border-red-200';
    case 'annulee':
      return 'bg-amber-100 text-amber-700 border-amber-200';
    default:
      return 'bg-slate-100 text-slate-700 border-slate-200';
  }
}

function getSalleWorkflowQuoteStatusLabel(status: SalleWorkflowQuoteStatus | string | null | undefined) {
  switch (status) {
    case "a_preparer":
      return "À préparer";
    case "en_attente_association":
      return "Réponse attendue de l'association";
    case "accepte":
      return "Devis accepté par l'association";
    case "refuse":
      return "Refusé par l'association";
    default:
      return "-";
  }
}

function getSalleWorkflowDirectorStatusLabel(status: SalleWorkflowDirectorStatus | string | null | undefined) {
  switch (status) {
    case "a_transmettre":
      return "À transmettre à la Directrice";
    case "en_attente_signature":
      return "En attente de signature";
    case "signee":
      return "Signée";
    default:
      return "-";
  }
}

function getSalleWorkflowStage(workflow: {
  quoteStatus?: SalleWorkflowQuoteStatus | string | null;
  directorStatus?: SalleWorkflowDirectorStatus | string | null;
  finalNotificationSentAt?: string | null;
  directorReturnComment?: string | null;
}) {
  if (workflow.finalNotificationSentAt) {
    return {
      label: "Demande finalisée",
      description: "L’association a reçu le dossier final signé, le devis validé et la facture.",
      className: "bg-green-100 text-green-700 border-green-200",
    };
  }
  if (workflow.directorStatus === "signee") {
    return {
      label: "Signé par la Direction - prêt à envoyer",
      description: "La Direction a signé. L’hôtesse peut maintenant préparer puis confirmer l’envoi final à l’association.",
      className: "bg-emerald-100 text-emerald-700 border-emerald-200",
    };
  }
  if (workflow.directorStatus === "en_attente_signature") {
    return {
      label: "En signature Direction",
      description: "Le dossier complet a été transmis à la Direction et attend une signature.",
      className: "bg-amber-100 text-amber-800 border-amber-200",
    };
  }
  if (workflow.quoteStatus === "accepte") {
    return {
      label: "Devis accepté par l’association",
      description: workflow.directorReturnComment
        ? "La Direction a renvoyé le dossier avec un commentaire. L’hôtesse peut l’ajuster avant une nouvelle transmission."
        : "L’association a validé le devis. À ce stade, l’hôtesse ne peut plus modifier le dossier et doit uniquement le transmettre à la Direction.",
      className: "bg-blue-100 text-blue-700 border-blue-200",
    };
  }
  if (workflow.quoteStatus === "en_attente_association") {
    return {
      label: "En attente de réponse de l'association",
      description: "Le devis et la décision administrative ont été envoyés. L’hôtesse et les autres profils de traitement doivent attendre l’accord de l’association.",
      className: "bg-violet-100 text-violet-700 border-violet-200",
    };
  }
  return {
    label: "Analyse hôtesse",
    description: "La demande a été soumise et l’hôtesse doit encore analyser le dossier.",
    className: "bg-slate-100 text-slate-700 border-slate-200",
  };
}

function getRequestDisplayStatusMeta(input: {
  status: string;
  type: string;
  salleWorkflow?: {
    quoteStatus?: SalleWorkflowQuoteStatus | string | null;
  } | null;
}) {
  if (input.type === "demande_salle" && input.salleWorkflow?.quoteStatus === "en_attente_association") {
    return {
      label: "En attente de réponse de l'association",
      className: "bg-violet-100 text-violet-700 border-violet-200",
    };
  }

  const fallback = {
    brouillon: { label: "Brouillon", className: "bg-gray-100 text-gray-700" },
    soumise: { label: "Soumise", className: "bg-blue-100 text-blue-700" },
    en_cours_traitement: { label: "En cours", className: "bg-yellow-100 text-yellow-700" },
    information_complementaire: { label: "Info requise", className: "bg-orange-100 text-orange-700" },
    validee: { label: "Validée", className: "bg-green-100 text-green-700" },
    refusee: { label: "Refusée", className: "bg-red-100 text-red-700" },
    annulee: { label: "Annulée", className: "bg-gray-100 text-gray-500" },
  } as const;

  return fallback[input.status as keyof typeof fallback] || {
    label: input.status,
    className: "bg-slate-100 text-slate-700",
  };
}

export default function RequestDetail() {
  const { user } = useAuth();
  const params = useParams<{ id: string }>();
  const [location, setLocation] = useLocation();
  const requestId = parseInt(params.id || '0');
  const searchParams = useMemo(() => {
    const queryIndex = location.indexOf("?");
    return new URLSearchParams(queryIndex >= 0 ? location.slice(queryIndex + 1) : "");
  }, [location]);
  const submittedFlag = searchParams.get("submitted") === "1";
  const submittedSource = searchParams.get("source") || "";
  
  // State for admin process dialog
  const [showProcessDialog, setShowProcessDialog] = useState(false);
  const [showLogisticsAssignmentDialog, setShowLogisticsAssignmentDialog] = useState(false);
  const [showSalleFinalDialog, setShowSalleFinalDialog] = useState(false);
  const [salleFinalPreview, setSalleFinalPreview] = useState<SalleFinalNotificationPreview | null>(null);
  const [salleFinalDocumentPreview, setSalleFinalDocumentPreview] = useState<SalleFinalDocumentPreview | null>(null);
  const [sallePaymentForm, setSallePaymentForm] = useState<{
    paymentStatus: SalleWorkflowPaymentStatus;
    amountReceivedEuros: string;
    paymentReceivedAt: string;
    paymentReference: string;
    paymentNotes: string;
  }>({
    paymentStatus: "en_attente_paiement",
    amountReceivedEuros: "",
    paymentReceivedAt: "",
    paymentReference: "",
    paymentNotes: "",
  });
  const [materialReturnLinkOverride, setMaterialReturnLinkOverride] = useState<null | {
    uploadLink: string;
    uploadTokenExpiresAt: Date | string;
    lastReminderSentAt: Date;
    reactivatedAt: Date;
    uploadLinkState: "active";
  }>(null);
  const [processData, setProcessData] = useState({
    status: '',
    commentaireAdmin: '',
    montantAccorde: '',
    recapServiceId: '',
    recapRecipients: '',
    recapServiceLabel: '',
    supervisionServiceId: '',
    supervisionRecipients: '',
    supervisionServiceLabel: '',
  });
  const [logisticsAssignmentData, setLogisticsAssignmentData] = useState({
    recapServiceId: '',
    recapRecipients: '',
    recapServiceLabel: '',
    supervisionServiceId: '',
    supervisionRecipients: '',
    supervisionServiceLabel: '',
  });

  // State for DSU form
  const [dsuData, setDsuData] = useState({
    dateReception: new Date().toISOString().split('T')[0],
    avisDSU: '' as string,
    conditionsParticulieres: '',
    cautionRequise: false,
    montantCaution: '',
    assuranceRequise: false,
    horairesImposes: '',
    responsableDSU: '',
    dateDecision: new Date().toISOString().split('T')[0],
    observationsDSU: '',
    salleReservation: {
      usageType: 'conventionne' as SalleUsageType,
      frequency: 'journee' as SalleReservationFrequency,
    },
    materielEvent: {
      itemsAccordes: emptyMaterialEventSelection(),
      quantitesAccordees: emptyMaterialEventQuantities(),
      autresPrecisions: '',
      financialDecision: {
        financialMode: 'gratuite' as MaterialFinancialMode,
        depositRequired: false,
        depositAmountEuros: '',
        rentalAmountEuros: '',
        pricingNotes: '',
        contractStatus: 'a_generer' as MaterialContractStatus,
        contractPdfUrl: '',
        contractPdfName: '',
        contractGeneratedAt: '',
        contractValidatedByUserId: null as number | null,
      },
    },
  });
  
  const { data: request, isLoading, error } = trpc.request.getById.useQuery(
    { id: requestId },
    { enabled: requestId > 0 }
  );
  const canManageLogistics = user?.role === 'super_admin' || Boolean(user?.canManageLogistics);
  const { data: operationalRecapServices } = trpc.operationalRecapService.listAll.useQuery(undefined, {
    enabled: !!user && canManageLogistics,
  });
  const { data: materialReturnFollowup } = trpc.materialReturn.getByRequestId.useQuery(
    { requestId },
    {
      enabled: !!user && canManageLogistics && requestId > 0,
    }
  );
  const { data: logisticsPolicy } = trpc.request.getLogisticsPolicy.useQuery(undefined, {
    enabled: !!user && canManageLogistics,
  });
  const utils = trpc.useUtils();
  const [litigationForm, setLitigationForm] = useState({
    blockedItems: Object.fromEntries(materialEventItems.map((item) => [item.key, "0"])) as Record<string, string>,
    estimatedDamageAmount: "",
    estimatedDamageSource: "manual" as "manual" | "replacement_value",
    arbitrationDecision: "partial_retention" as "partial_retention" | "full_retention" | "dismissed",
    arbitrationAmount: "",
    arbitrationNotes: "",
  });
  const normalizedOperationalRecapServices = useMemo(() => {
    return (operationalRecapServices || [])
      .filter((service): service is NonNullable<typeof service> => Boolean(service && typeof service === "object"))
      .map((service) => {
        const rawRecipientEmails = (service as { recipientEmails?: unknown }).recipientEmails;
        return {
          ...service,
          label: typeof service.label === "string" ? service.label : "",
          usage: service.usage === "controle" ? "controle" : "terrain",
          actif: Boolean(service.actif),
          recipientEmails: Array.isArray(rawRecipientEmails)
            ? rawRecipientEmails
                .map((entry) => String(entry || "").trim().toLowerCase())
                .filter(Boolean)
            : [],
        };
      });
  }, [operationalRecapServices]);
  const terrainOperationalRecapServices = useMemo(
    () => normalizedOperationalRecapServices.filter((service) => service.usage === "terrain"),
    [normalizedOperationalRecapServices]
  );
  const controlOperationalRecapServices = useMemo(
    () => normalizedOperationalRecapServices.filter((service) => service.usage === "controle"),
    [normalizedOperationalRecapServices]
  );
  const normalizedMaterialReturnFollowup = useMemo(() => {
    if (!materialReturnFollowup || typeof materialReturnFollowup !== "object") {
      return null;
    }

    return {
      ...materialReturnFollowup,
      serviceLabel: typeof materialReturnFollowup.serviceLabel === "string" ? materialReturnFollowup.serviceLabel : "",
      recipientEmails: Array.isArray(materialReturnFollowup.recipientEmails)
        ? materialReturnFollowup.recipientEmails.map((entry) => String(entry || "").trim()).filter(Boolean)
        : [],
      supervisionServiceLabel:
        typeof (materialReturnFollowup as { supervisionServiceLabel?: unknown }).supervisionServiceLabel === "string"
          ? String((materialReturnFollowup as { supervisionServiceLabel?: unknown }).supervisionServiceLabel)
          : "",
      supervisionRecipientEmails: Array.isArray((materialReturnFollowup as { supervisionRecipientEmails?: unknown }).supervisionRecipientEmails)
        ? ((materialReturnFollowup as { supervisionRecipientEmails?: unknown }).supervisionRecipientEmails as unknown[])
            .map((entry) => String(entry || "").trim())
            .filter(Boolean)
        : [],
    };
  }, [materialReturnFollowup]);

  useEffect(() => {
    setMaterialReturnLinkOverride(null);
  }, [
    normalizedMaterialReturnFollowup?.uploadLink,
    normalizedMaterialReturnFollowup?.uploadTokenExpiresAt,
    normalizedMaterialReturnFollowup?.lastReminderSentAt,
    normalizedMaterialReturnFollowup?.reactivatedAt,
  ]);

  const submitMutation = trpc.request.submit.useMutation({
    onSuccess: () => {
      toast.success('Demande soumise avec succès');
      utils.request.getById.invalidate({ id: requestId });
      utils.request.getMyRequests.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de la soumission');
    },
  });

  const duplicateMutation = trpc.request.duplicate.useMutation({
    onSuccess: (data) => {
      toast.success('Une copie brouillon de la demande a été créée');
      utils.request.getMyRequests.invalidate();
      navigate(
        data.type === 'demande_materiel_evenementiel'
          ? `/dashboard/requests/${data.id}`
          : `/dashboard/requests/${data.id}/edit`
      );
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de la duplication de la demande');
    },
  });

  const pdfMutation = trpc.request.generatePdf.useMutation({
    onSuccess: (data) => {
      // Ouvrir le PDF dans un nouvel onglet pour téléchargement
      const link = document.createElement('a');
      link.href = data.url;
      link.download = data.fileName;
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      toast.success('PDF généré avec succès');
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de la génération du PDF');
    },
  });

  const contractMutation = trpc.request.generateMaterialConvention.useMutation({
    onSuccess: (data) => {
      const link = document.createElement('a');
      link.href = data.url;
      link.download = data.fileName;
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      toast.success('Convention générée avec succès');
      utils.request.getById.invalidate({ id: requestId });
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de la génération de la convention');
    },
  });
  const salleContractMutation = trpc.request.generateSalleConvention.useMutation({
    onSuccess: (data) => {
      const link = document.createElement('a');
      link.href = data.url;
      link.download = data.fileName;
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      toast.success('Convention générée avec succès');
      utils.request.getById.invalidate({ id: requestId });
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de la génération de la convention');
    },
  });
  const sendSalleQuoteMutation = trpc.request.sendSalleQuote.useMutation({
    onSuccess: () => {
      toast.success("Devis et décision administrative envoyés à l'association");
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Erreur lors de l'envoi du devis");
    },
  });
  const respondSalleQuoteMutation = trpc.request.respondSalleQuote.useMutation({
    onSuccess: (data) => {
      toast.success(
        data.quoteStatus === "accepte"
          ? "Votre accord a bien été enregistré. Le dossier repart vers l’hôtesse."
          : "Votre refus a bien été enregistré."
      );
      utils.request.getById.invalidate({ id: requestId });
      utils.request.getMyRequests.invalidate();
      utils.request.search.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Impossible d'enregistrer votre réponse");
    },
  });
  const sendSalleToDirectorMutation = trpc.request.sendSalleToDirector.useMutation({
    onSuccess: () => {
      toast.success("Dossier transmis à la Directrice");
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Erreur lors de la transmission à la Directrice");
    },
  });
  const finalizeSalleReservationMutation = trpc.request.finalizeSalleReservation.useMutation({
    onSuccess: () => {
      toast.success("Dossier signé par la Direction. Il revient maintenant à l’hôtesse pour l’envoi final.");
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
      utils.request.getPending.invalidate();
      utils.stats.getDashboard.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Erreur lors de la signature du dossier");
    },
  });
  const prepareSalleFinalNotificationMutation = trpc.request.prepareSalleFinalNotification.useMutation({
    onSuccess: (data) => {
      setSalleFinalPreview(data);
      setShowSalleFinalDialog(true);
      utils.request.getById.invalidate({ id: requestId });
    },
    onError: (error) => {
      toast.error(error.message || "Impossible de préparer l’envoi final");
    },
  });
  const sendSalleFinalNotificationMutation = trpc.request.sendSalleFinalNotification.useMutation({
    onSuccess: () => {
      toast.success("Confirmation finale envoyée à l’association");
      setShowSalleFinalDialog(false);
      setSalleFinalPreview(null);
      setSalleFinalDocumentPreview(null);
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
      utils.request.getPending.invalidate();
      utils.stats.getDashboard.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Erreur lors de l’envoi final à l’association");
    },
  });
  const updateSallePaymentTrackingMutation = trpc.request.updateSallePaymentTracking.useMutation({
    onSuccess: () => {
      toast.success("Suivi de facturation mis à jour");
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
      utils.request.getSalleSignatureQueue.invalidate();
      utils.request.getPastForSignature.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Impossible de mettre à jour le suivi de facturation");
    },
  });

  const processMutation = trpc.request.process.useMutation({
    onSuccess: () => {
      toast.success(
        isDemandeSalle && processData.status === 'validee'
          ? "Demande traitée et devis envoyé à l'association"
          : 'Demande traitée avec succès'
      );
      setShowProcessDialog(false);
      setProcessData({
        status: '',
        commentaireAdmin: '',
        montantAccorde: '',
        recapServiceId: '',
        recapRecipients: '',
        recapServiceLabel: '',
        supervisionServiceId: '',
        supervisionRecipients: '',
        supervisionServiceLabel: '',
      });
      setDsuData({
        dateReception: new Date().toISOString().split('T')[0],
        avisDSU: '',
        conditionsParticulieres: '',
        cautionRequise: false,
        montantCaution: '',
        assuranceRequise: false,
        horairesImposes: '',
        responsableDSU: '',
        dateDecision: new Date().toISOString().split('T')[0],
        observationsDSU: '',
        salleReservation: {
          usageType: 'conventionne',
          frequency: 'journee',
        },
        materielEvent: {
          itemsAccordes: emptyMaterialEventSelection(),
          quantitesAccordees: emptyMaterialEventQuantities(),
          autresPrecisions: '',
          financialDecision: {
            financialMode: 'gratuite',
            depositRequired: false,
            depositAmountEuros: '',
            rentalAmountEuros: '',
            pricingNotes: '',
            contractStatus: 'a_generer',
            contractPdfUrl: '',
            contractPdfName: '',
            contractGeneratedAt: '',
            contractValidatedByUserId: null,
          },
        },
      });
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
      utils.request.getPending.invalidate();
      utils.stats.getDashboard.invalidate();
      utils.materialReturn.getByRequestId.invalidate({ requestId });
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors du traitement');
    },
  });

  const assignMaterialReturnMutation = trpc.materialReturn.assign.useMutation({
    onSuccess: (result) => {
      toast.success(
        result.emailSent
          ? 'Récupération assignée et email envoyé'
          : "Récupération assignée, mais l'email n'a pas pu partir automatiquement"
      );
      setShowLogisticsAssignmentDialog(false);
      setLogisticsAssignmentData({
        recapServiceId: '',
        recapRecipients: '',
        recapServiceLabel: '',
        supervisionServiceId: '',
        supervisionRecipients: '',
        supervisionServiceLabel: '',
      });
      utils.materialReturn.getByRequestId.invalidate({ requestId });
      utils.materialReturn.listAdminBoard.invalidate();
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Impossible d'assigner la récupération");
    },
  });

  const reactivateMaterialReturnMutation = trpc.materialReturn.reactivate.useMutation({
    onSuccess: (result, variables) => {
      const now = new Date();
      setMaterialReturnLinkOverride({
        uploadLink: result.uploadLink,
        uploadTokenExpiresAt: result.uploadTokenExpiresAt,
        lastReminderSentAt: now,
        reactivatedAt: now,
        uploadLinkState: "active",
      });
      toast.success(
        result.emailSent
          ? "Lien de restitution réactivé et envoyé"
          : "Lien de restitution réactivé, mais l'email n'a pas pu partir automatiquement"
      );
      utils.materialReturn.getByRequestId.invalidate({ requestId });
      utils.materialReturn.listAdminBoard.invalidate();
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || "Impossible de réactiver la restitution");
    },
  });

  const resolveLitigationMutation = trpc.materialReturn.resolveLitigation.useMutation({
    onSuccess: () => {
      toast.success("Arbitrage du litige enregistré");
      utils.materialReturn.getByRequestId.invalidate({ requestId });
      utils.request.getMaterialCalendar.invalidate();
      utils.request.getMaterialAvailability.invalidate();
      utils.request.getById.invalidate({ id: requestId });
    },
    onError: (error) => {
      toast.error(error.message || "Impossible d'enregistrer l'arbitrage");
    },
  });

  const reopenMutation = trpc.request.reopen.useMutation({
    onSuccess: () => {
      toast.success('La demande a été rouverte pour modification');
      utils.request.getById.invalidate({ id: requestId });
      utils.request.search.invalidate();
      utils.request.getPending.invalidate();
      utils.stats.getDashboard.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de la réouverture de la demande');
    },
  });

  const navigate = setLocation;
  const [showCancelDialog, setShowCancelDialog] = useState(false);
  const [cancelRaison, setCancelRaison] = useState('');

  const cancelMutation = trpc.request.cancel.useMutation({
    onSuccess: () => {
      toast.success('Demande annulée avec succès');
      setShowCancelDialog(false);
      setCancelRaison('');
      utils.request.getById.invalidate({ id: requestId });
      utils.request.getMyRequests.invalidate();
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de l\'annulation');
    },
  });

  const deleteMutation = trpc.request.delete.useMutation({
    onSuccess: () => {
      toast.success('Demande supprimée avec succès');
      navigate('/dashboard/requests');
    },
    onError: (error) => {
      toast.error(error.message || 'Erreur lors de la suppression');
    },
  });

  const handleProcess = (generateContract = false) => {
    if (!processData.status) {
      toast.error('Veuillez sélectionner un statut');
      return;
    }
    if ((isDemandeSalle || isDemandeMaterielEvenementiel) && !dsuData.responsableDSU.trim()) {
      toast.error('Le responsable DSU est obligatoire pour traiter la demande');
      return;
    }
    if (requestNeedsFinancialDecision && processData.status === 'validee' && !dsuData.materielEvent.financialDecision.financialMode) {
      toast.error(`Le mode financier est obligatoire pour valider cette ${isDemandeSalle ? 'demande de salle' : 'demande de matériel'}`);
      return;
    }
    if (
      isDemandeSalle
      && dsuData.materielEvent.financialDecision.financialMode === 'location_payante'
      && (!sallePricingPreview || sallePricingPreview.unsupportedSalles.length > 0)
    ) {
      toast.error(
        sallePricingPreview?.unsupportedSalles?.length
          ? `La tarification automatique n'est pas disponible pour : ${sallePricingPreview.unsupportedSalles.map((item) => item.salleNom).join(', ')}`
          : "Le devis ne peut pas être calculé automatiquement pour cette réservation"
      );
      return;
    }
    if (isDemandeMaterielEvenementiel && processData.status === 'validee' && !validateGrantedMaterialQuantities()) {
      return;
    }

    const baseDsuPayload = {
      dateReception: dsuData.dateReception || undefined,
      avisDSU: (dsuData.avisDSU || undefined) as 'favorable' | 'defavorable' | 'favorable_avec_reserves' | undefined,
      conditionsParticulieres: dsuData.conditionsParticulieres || undefined,
      cautionRequise: dsuData.cautionRequise,
      montantCaution: dsuData.montantCaution || undefined,
      assuranceRequise: dsuData.assuranceRequise,
      horairesImposes: dsuData.horairesImposes || undefined,
      responsableDSU: dsuData.responsableDSU.trim() || undefined,
      dateDecision: dsuData.dateDecision || undefined,
      observationsDSU: dsuData.observationsDSU || undefined,
    };
    const dsuPayload = isDemandeSalle
      ? {
          ...baseDsuPayload,
          cautionRequise: dsuData.materielEvent.financialDecision.depositRequired,
          montantCaution: dsuData.materielEvent.financialDecision.depositRequired
            ? dsuData.materielEvent.financialDecision.depositAmountEuros || undefined
            : undefined,
          salleReservation: {
            usageType: dsuData.salleReservation.usageType,
            frequency: dsuData.salleReservation.frequency,
          },
          materielEvent: {
            financialDecision: {
              financialMode: dsuData.materielEvent.financialDecision.financialMode,
              depositRequired: dsuData.materielEvent.financialDecision.depositRequired,
              depositAmountCents: parseEuroInputToCents(dsuData.materielEvent.financialDecision.depositAmountEuros),
              rentalAmountCents: parseEuroInputToCents(dsuData.materielEvent.financialDecision.rentalAmountEuros),
              pricingNotes: dsuData.materielEvent.financialDecision.pricingNotes || undefined,
              contractStatus: dsuData.materielEvent.financialDecision.contractStatus,
            },
          },
        }
      : isDemandeMaterielEvenementiel
        ? {
            ...baseDsuPayload,
            materielEvent: {
              itemsAccordes: dsuData.materielEvent.itemsAccordes,
              quantitesAccordees: dsuData.materielEvent.quantitesAccordees,
              autresPrecisions: dsuData.materielEvent.autresPrecisions || undefined,
              financialDecision: {
                financialMode: dsuData.materielEvent.financialDecision.financialMode,
                depositRequired: dsuData.materielEvent.financialDecision.depositRequired,
                depositAmountCents: parseEuroInputToCents(dsuData.materielEvent.financialDecision.depositAmountEuros),
                rentalAmountCents: parseEuroInputToCents(dsuData.materielEvent.financialDecision.rentalAmountEuros),
                pricingNotes: dsuData.materielEvent.financialDecision.pricingNotes || undefined,
                contractStatus: generateContract ? 'generee' : dsuData.materielEvent.financialDecision.contractStatus,
              },
            },
          }
        : undefined;

    processMutation.mutate({
      id: requestId,
      status: processData.status as any,
      commentaireAdmin: processData.commentaireAdmin || undefined,
      montantAccorde: processData.montantAccorde ? parseInt(processData.montantAccorde) * 100 : undefined,
      recapServiceId: processData.recapServiceId ? parseInt(processData.recapServiceId, 10) : undefined,
      recapRecipients: processData.recapRecipients
        ? processData.recapRecipients.split(/[,;\n]/).map(v => v.trim()).filter(Boolean)
        : undefined,
      recapServiceLabel: processData.recapServiceLabel || undefined,
      supervisionServiceId: processData.supervisionServiceId ? parseInt(processData.supervisionServiceId, 10) : undefined,
      supervisionRecipients: processData.supervisionRecipients
        ? processData.supervisionRecipients.split(/[,;\n]/).map(v => v.trim()).filter(Boolean)
        : undefined,
      supervisionServiceLabel: processData.supervisionServiceLabel || undefined,
      dsuData: dsuPayload,
      generateContract,
    });
  };

  const formatDateTime = (date: Date | string | null) => {
    if (!date) return '-';
    return new Date(date).toLocaleDateString('fr-FR', {
      day: '2-digit',
      month: 'long',
      year: 'numeric',
      hour: '2-digit',
      minute: '2-digit',
    });
  };

  const formatAmount = (cents: number | null) => {
    if (!cents) return '-';
    return new Intl.NumberFormat('fr-FR', { style: 'currency', currency: 'EUR' }).format(cents / 100);
  };

  const formData = useMemo(() => {
    if (!request?.formData) return {};
    try {
      return JSON.parse(request.formData);
    } catch {
      return {};
    }
  }, [request?.formData]);

  const status = useMemo(() => {
    return getStatusConfig(request?.status || 'brouillon');
  }, [request?.status]);
  const isAdmin =
    user?.role === 'accueil'
    || user?.role === 'logistique_controle'
    || user?.role === 'admin'
    || user?.role === 'super_admin'
    || user?.role === 'directrice'
    || Boolean(user?.canSignSalle);
  const canOperateSalleWorkflow =
    user?.role === 'accueil'
    || user?.role === 'admin'
    || user?.role === 'super_admin';
  const canOperateMaterialWorkflow =
    user?.role === 'logistique_controle'
    || user?.role === 'admin'
    || user?.role === 'super_admin'
    || canManageLogistics;
  const isDemandeSalle = request?.type === 'demande_salle';
  const isDemandeMaterielEvenementiel = request?.type === 'demande_materiel_evenementiel';
  const requestNeedsFinancialDecision = isDemandeSalle || isDemandeMaterielEvenementiel;
  const activeContractMutation = isDemandeSalle ? salleContractMutation : contractMutation;
  const reservationDailySlots = useMemo(() => getReservationDailySlots(formData), [formData]);
  const reservationPeriodSummary = useMemo(
    () => formatReservationSallePeriod({
      dateReservation: String(formData.dateReservation || ''),
      dateFinReservation: String(formData.dateFinReservation || ''),
    }),
    [formData]
  );
  const reservationScheduleSummary = useMemo(
    () => getReservationSalleScheduleSummary({
      useDetailedSchedule: Boolean(formData.useDetailedSchedule),
      horairesParJour: reservationDailySlots,
      heureDebut: String(formData.heureDebut || ''),
      heureFin: String(formData.heureFin || ''),
    }),
    [formData, reservationDailySlots]
  );
  const sallePricingPreview = useMemo(() => {
    if (!isDemandeSalle) return null;
    const sallesIds = Array.isArray(formData?.sallesIds)
      ? formData.sallesIds.filter((value: unknown): value is string => typeof value === 'string' && value.trim().length > 0)
      : [];
    if (sallesIds.length === 0) return null;
    return computeSallePricing({
      sallesIds,
      usageType: dsuData.salleReservation.usageType,
      frequency: dsuData.salleReservation.frequency,
      dateReservation: String(formData.dateReservation || ''),
      dateFinReservation: String(formData.dateFinReservation || ''),
    });
  }, [dsuData.salleReservation.frequency, dsuData.salleReservation.usageType, formData, isDemandeSalle]);
  const salleDecisionAdministrativeText = useMemo(() => {
    if (!isDemandeSalle) return '';
    return buildDecisionAdministrativeText({
      espace: Array.isArray(formData?.sallesSelectionnees) && formData.sallesSelectionnees.length > 0
        ? formData.sallesSelectionnees.join(', ')
        : '-',
      dates: reservationPeriodSummary,
      horaires: reservationScheduleSummary,
      association: String(formData?.nomAssociation || '-'),
    });
  }, [formData, isDemandeSalle, reservationPeriodSummary, reservationScheduleSummary]);
  const canDelete = !isAdmin && !!request && request.status !== 'validee' && request.status !== 'refusee' && request.status !== 'annulee';
  const canCancel = !isAdmin && !!request && request.status !== 'validee' && request.status !== 'refusee' && request.status !== 'annulee' && request.status !== 'brouillon';
  const rawReturnTo = searchParams.get("returnTo") || "";
  const backUrl = rawReturnTo.startsWith("/") ? rawReturnTo : isAdmin ? '/admin' : '/dashboard/requests';
  const canAssignMaterialReturn = canManageLogistics && isDemandeMaterielEvenementiel && request?.status === 'validee';
  const cadreDSU = formData.cadreDSU;
  const materialFinancialDecision = useMemo(() => {
    const raw = cadreDSU?.materielEvent?.financialDecision;
    if (!raw || typeof raw !== 'object') return null;

    const financialMode = ['gratuite', 'gratuite_avec_caution', 'location_payante'].includes(String(raw.financialMode))
      ? String(raw.financialMode) as MaterialFinancialMode
      : null;

    if (!financialMode) return null;

    return {
      financialMode,
      depositRequired: Boolean(raw.depositRequired),
      depositAmountCents: Number.isFinite(Number(raw.depositAmountCents)) ? Math.max(0, Number(raw.depositAmountCents)) : 0,
      rentalAmountCents: Number.isFinite(Number(raw.rentalAmountCents)) ? Math.max(0, Number(raw.rentalAmountCents)) : 0,
      pricingNotes: typeof raw.pricingNotes === 'string' ? raw.pricingNotes : '',
      contractStatus: ['a_generer', 'generee', 'signee', 'refusee', 'annulee'].includes(String(raw.contractStatus))
        ? String(raw.contractStatus) as MaterialContractStatus
        : 'a_generer',
      contractPdfUrl: typeof raw.contractPdfUrl === 'string' ? raw.contractPdfUrl : '',
      contractPdfName: typeof raw.contractPdfName === 'string' ? raw.contractPdfName : '',
      contractGeneratedAt: typeof raw.contractGeneratedAt === 'string' ? raw.contractGeneratedAt : '',
      contractValidatedByUserId: Number.isFinite(Number(raw.contractValidatedByUserId))
        ? Number(raw.contractValidatedByUserId)
        : null,
    };
  }, [cadreDSU]);
  const salleWorkflow = useMemo(() => {
    const raw = formData?.salleWorkflow;
    if (!raw || typeof raw !== "object") return null;
    return {
      quoteStatus: typeof raw.quoteStatus === "string" ? raw.quoteStatus as SalleWorkflowQuoteStatus : "a_preparer",
      quoteSentAt: typeof raw.quoteSentAt === "string" ? raw.quoteSentAt : "",
      quoteRespondedAt: typeof raw.quoteRespondedAt === "string" ? raw.quoteRespondedAt : "",
      quotePdfUrl: typeof raw.quotePdfUrl === "string" ? raw.quotePdfUrl : "",
      quotePdfName: typeof raw.quotePdfName === "string" ? raw.quotePdfName : "",
      administrativeDecisionPdfUrl: typeof raw.administrativeDecisionPdfUrl === "string" ? raw.administrativeDecisionPdfUrl : "",
      administrativeDecisionPdfName: typeof raw.administrativeDecisionPdfName === "string" ? raw.administrativeDecisionPdfName : "",
      directorStatus: typeof raw.directorStatus === "string" ? raw.directorStatus as SalleWorkflowDirectorStatus : "a_transmettre",
      directorTransmissionAt: typeof raw.directorTransmissionAt === "string" ? raw.directorTransmissionAt : "",
      directorSignedAt: typeof raw.directorSignedAt === "string" ? raw.directorSignedAt : "",
      directorSignedByName: typeof raw.directorSignedByName === "string" ? raw.directorSignedByName : "",
      directorReturnComment: typeof raw.directorReturnComment === "string" ? raw.directorReturnComment : "",
      directorReturnedAt: typeof raw.directorReturnedAt === "string" ? raw.directorReturnedAt : "",
      signedQuotePdfUrl: typeof raw.signedQuotePdfUrl === "string" ? raw.signedQuotePdfUrl : "",
      signedQuotePdfName: typeof raw.signedQuotePdfName === "string" ? raw.signedQuotePdfName : "",
      signedDecisionPdfUrl: typeof raw.signedDecisionPdfUrl === "string" ? raw.signedDecisionPdfUrl : "",
      signedDecisionPdfName: typeof raw.signedDecisionPdfName === "string" ? raw.signedDecisionPdfName : "",
      signedRequestPdfUrl: typeof raw.signedRequestPdfUrl === "string" ? raw.signedRequestPdfUrl : "",
      signedRequestPdfName: typeof raw.signedRequestPdfName === "string" ? raw.signedRequestPdfName : "",
      invoicePdfUrl: typeof raw.invoicePdfUrl === "string" ? raw.invoicePdfUrl : "",
      invoicePdfName: typeof raw.invoicePdfName === "string" ? raw.invoicePdfName : "",
      invoiceGeneratedAt: typeof raw.invoiceGeneratedAt === "string" ? raw.invoiceGeneratedAt : "",
      paymentStatus: typeof raw.paymentStatus === "string" ? raw.paymentStatus as SalleWorkflowPaymentStatus : null,
      paymentDueDate: typeof raw.paymentDueDate === "string" ? raw.paymentDueDate : "",
      amountReceivedCents: Number.isFinite(Number(raw.amountReceivedCents)) ? Number(raw.amountReceivedCents) : 0,
      paymentReceivedAt: typeof raw.paymentReceivedAt === "string" ? raw.paymentReceivedAt : "",
      paymentValidatedAt: typeof raw.paymentValidatedAt === "string" ? raw.paymentValidatedAt : "",
      paymentReference: typeof raw.paymentReference === "string" ? raw.paymentReference : "",
      paymentNotes: typeof raw.paymentNotes === "string" ? raw.paymentNotes : "",
      finalNotificationSentAt: typeof raw.finalNotificationSentAt === "string" ? raw.finalNotificationSentAt : "",
      pricing: raw.pricing && typeof raw.pricing === "object" ? raw.pricing : null,
    };
  }, [formData]);
  const salleWorkflowStage = useMemo(
    () => (salleWorkflow ? getSalleWorkflowStage(salleWorkflow) : null),
    [salleWorkflow]
  );
  const requestDisplayStatusMeta = useMemo(
    () => getRequestDisplayStatusMeta({ status: request?.status || "", type: request?.type || "", salleWorkflow }),
    [request?.status, request?.type, salleWorkflow]
  );
  const canRespondToSalleQuote = !isAdmin && isDemandeSalle && salleWorkflow?.quoteStatus === "en_attente_association";
  const waitingForAssociationResponse = isDemandeSalle && salleWorkflow?.quoteStatus === "en_attente_association";
  const canSignSalleWorkflow = user?.role === "super_admin" || user?.role === "directrice" || Boolean(user?.canSignSalle);
  const salleDirectorReturnedForRevision = isDemandeSalle
    && salleWorkflow?.quoteStatus === "accepte"
    && salleWorkflow?.directorStatus === "a_transmettre"
    && Boolean(salleWorkflow?.directorReturnComment);
  const salleLockedForFinalNotification = isDemandeSalle
    && salleWorkflow?.directorStatus === "signee"
    && !salleWorkflow?.finalNotificationSentAt;
  const canEdit = !isAdmin
    && !!request
    && (request.status === 'brouillon' || request.status === 'information_complementaire')
    && !canRespondToSalleQuote
    && !salleLockedForFinalNotification;
  const canSendSalleQuote = canOperateSalleWorkflow
    && isDemandeSalle
    && !!request
    && request.status !== "validee"
    && request.status !== "refusee"
    && request.status !== "annulee"
    && salleWorkflow?.quoteStatus !== "en_attente_association"
    && salleWorkflow?.directorStatus !== "en_attente_signature"
    && salleWorkflow?.directorStatus !== "signee";
  const canSendSalleToDirector = canOperateSalleWorkflow
    && isDemandeSalle
    && salleWorkflow?.quoteStatus === "accepte"
    && salleWorkflow?.directorStatus === "a_transmettre";
  const canFinalizeSalle =
    canSignSalleWorkflow
    && isDemandeSalle
    && salleWorkflow?.quoteStatus === "accepte"
    && salleWorkflow?.directorStatus === "en_attente_signature";
  const canPrepareSalleFinalNotification =
    canOperateSalleWorkflow
    && isDemandeSalle
    && salleWorkflow?.quoteStatus === "accepte"
    && salleWorkflow?.directorStatus === "signee"
    && !salleWorkflow?.finalNotificationSentAt;
  const canProcess = !!request
    && (
      (isDemandeSalle && canOperateSalleWorkflow)
      || (isDemandeMaterielEvenementiel && canOperateMaterialWorkflow)
      || (!isDemandeSalle && !isDemandeMaterielEvenementiel && (user?.role === 'admin' || user?.role === 'super_admin'))
    )
    && !!request
    && request.status !== 'brouillon'
    && request.status !== 'validee'
    && request.status !== 'refusee'
    && request.status !== 'annulee'
    && (
      !isDemandeSalle
      || !salleWorkflow
      || !salleWorkflow?.quoteStatus
      || salleWorkflow?.quoteStatus === "a_preparer"
      || salleWorkflow?.quoteStatus === "refuse"
      || salleDirectorReturnedForRevision
    );
  useEffect(() => {
    if (!salleWorkflow) return;
    setSallePaymentForm({
      paymentStatus: salleWorkflow.paymentStatus || "en_attente_paiement",
      amountReceivedEuros: Number.isFinite(Number(salleWorkflow.amountReceivedCents))
        && Number(salleWorkflow.amountReceivedCents) > 0
          ? (Number(salleWorkflow.amountReceivedCents) / 100).toFixed(2)
          : "",
      paymentReceivedAt: salleWorkflow.paymentReceivedAt ? String(salleWorkflow.paymentReceivedAt).slice(0, 10) : "",
      paymentReference: salleWorkflow.paymentReference || "",
      paymentNotes: salleWorkflow.paymentNotes || "",
    });
  }, [
    salleWorkflow?.amountReceivedCents,
    salleWorkflow?.paymentNotes,
    salleWorkflow?.paymentReceivedAt,
    salleWorkflow?.paymentReference,
    salleWorkflow?.paymentStatus,
  ]);

  const canUpdateSallePaymentTracking =
    canOperateSalleWorkflow
    && isDemandeSalle
    && materialFinancialDecision?.financialMode === "location_payante"
    && !!salleWorkflow
    && salleWorkflow.quoteStatus === "accepte";
  const sallePaymentIsLate = Boolean(
    materialFinancialDecision?.financialMode === "location_payante"
    && salleWorkflow?.paymentDueDate
    && !["paiement_recu", "paiement_valide"].includes(salleWorkflow.paymentStatus || "")
    && salleWorkflow.paymentDueDate < new Date().toISOString().slice(0, 10)
  );
  useEffect(() => {
    if (!isDemandeSalle) return;
    if (dsuData.materielEvent.financialDecision.financialMode !== 'location_payante') return;
    const computedAmount = sallePricingPreview && sallePricingPreview.unsupportedSalles.length === 0
      ? (sallePricingPreview.totalAmountCents / 100).toFixed(2)
      : '';
    setDsuData((prev) => {
      if (prev.materielEvent.financialDecision.rentalAmountEuros === computedAmount) return prev;
      return {
        ...prev,
        materielEvent: {
          ...prev.materielEvent,
          financialDecision: {
            ...prev.materielEvent.financialDecision,
            rentalAmountEuros: computedAmount,
          },
        },
      };
    });
  }, [
    dsuData.materielEvent.financialDecision.financialMode,
    isDemandeSalle,
    sallePricingPreview,
  ]);
  const handleSaveSallePaymentTracking = () => {
    if (!request) return;
    const normalizedAmount = sallePaymentForm.amountReceivedEuros.trim();
    const parsedAmount = normalizedAmount
      ? Math.max(0, Math.round(Number(normalizedAmount.replace(",", ".")) * 100))
      : 0;

    if (normalizedAmount && !Number.isFinite(parsedAmount)) {
      toast.error("Le montant reçu n’est pas valide");
      return;
    }

    updateSallePaymentTrackingMutation.mutate({
      id: request.id,
      paymentStatus: sallePaymentForm.paymentStatus,
      amountReceivedCents: parsedAmount,
      paymentReceivedAt: sallePaymentForm.paymentReceivedAt || undefined,
      paymentReference: sallePaymentForm.paymentReference.trim() || undefined,
      paymentNotes: sallePaymentForm.paymentNotes.trim() || undefined,
    });
  };
  const parseRecipientText = (value: string) =>
    value
      .split(/[,;\n]/)
      .map((entry) => entry.trim())
      .filter(Boolean);
  const handleMaterialReturnReactivation = (reason: string) => {
    const recipients = parseRecipientText(
      Array.isArray(normalizedMaterialReturnFollowup?.recipientEmails)
        ? normalizedMaterialReturnFollowup.recipientEmails.join(", ")
        : ""
    );
    reactivateMaterialReturnMutation.mutate({
      requestId,
      recapServiceLabel: normalizedMaterialReturnFollowup?.serviceLabel || undefined,
      recapRecipients: recipients.length > 0 ? recipients : undefined,
      supervisionServiceLabel: normalizedMaterialReturnFollowup?.supervisionServiceLabel || undefined,
      supervisionRecipients:
        Array.isArray(normalizedMaterialReturnFollowup?.supervisionRecipientEmails)
        && normalizedMaterialReturnFollowup.supervisionRecipientEmails.length > 0
          ? normalizedMaterialReturnFollowup.supervisionRecipientEmails
          : undefined,
      reason,
    });
  };
  const getRequestedQuantityForItem = (itemKey: string) => {
    const requestedQuantity = parseMaterialEventQuantity(formData.quantitesDemandees?.[itemKey]);
    return requestedQuantity > 0 ? String(requestedQuantity) : "1";
  };
  const validateGrantedMaterialQuantities = () => {
    const invalidItem = materialEventItems.find((item) => {
      if (!dsuData.materielEvent.itemsAccordes[item.key]) return false;
      return parseMaterialEventQuantity(dsuData.materielEvent.quantitesAccordees[item.key]) <= 0;
    });

    if (!invalidItem) return true;
    toast.error(`Renseigne une quantité accordée valide pour ${invalidItem.label}`);
    return false;
  };
  const applyOperationalRecapServiceToProcessData = (serviceId: string) => {
    const service = normalizedOperationalRecapServices.find((entry) => String(entry?.id) === serviceId);
    if (!service) {
      setProcessData((prev) => ({
        ...prev,
        recapServiceId: '',
      }));
      return;
    }

    setProcessData((prev) => ({
      ...prev,
      recapServiceId: String(service.id),
      recapServiceLabel: service.label,
      recapRecipients: service.recipientEmails.join(', '),
    }));
  };
  const applyOperationalSupervisionServiceToProcessData = (serviceId: string) => {
    const service = normalizedOperationalRecapServices.find((entry) => String(entry?.id) === serviceId);
    if (!service) {
      setProcessData((prev) => ({
        ...prev,
        supervisionServiceId: '',
      }));
      return;
    }

    setProcessData((prev) => ({
      ...prev,
      supervisionServiceId: String(service.id),
      supervisionServiceLabel: service.label,
      supervisionRecipients: service.recipientEmails.join(', '),
    }));
  };
  const applyOperationalRecapServiceToAssignmentData = (serviceId: string) => {
    const service = normalizedOperationalRecapServices.find((entry) => String(entry?.id) === serviceId);
    if (!service) {
      setLogisticsAssignmentData((prev) => ({
        ...prev,
        recapServiceId: '',
      }));
      return;
    }

    setLogisticsAssignmentData((prev) => ({
      ...prev,
      recapServiceId: String(service.id),
      recapServiceLabel: service.label,
      recapRecipients: service.recipientEmails.join(', '),
    }));
  };
  const applyOperationalSupervisionServiceToAssignmentData = (serviceId: string) => {
    const service = normalizedOperationalRecapServices.find((entry) => String(entry?.id) === serviceId);
    if (!service) {
      setLogisticsAssignmentData((prev) => ({
        ...prev,
        supervisionServiceId: '',
      }));
      return;
    }

    setLogisticsAssignmentData((prev) => ({
      ...prev,
      supervisionServiceId: String(service.id),
      supervisionServiceLabel: service.label,
      supervisionRecipients: service.recipientEmails.join(', '),
    }));
  };
  const requestedMaterialItems = useMemo(
    () =>
      isDemandeMaterielEvenementiel
        ? materialEventItems.filter((item) => formData.materielsDemandes?.[item.key])
        : [],
    [formData.materielsDemandes, isDemandeMaterielEvenementiel]
  );
  const nonRequestedMaterialItems = useMemo(
    () =>
      isDemandeMaterielEvenementiel
        ? materialEventItems.filter((item) => !formData.materielsDemandes?.[item.key])
        : [],
    [formData.materielsDemandes, isDemandeMaterielEvenementiel]
  );
  const materialReturnAssigned = Boolean(
    normalizedMaterialReturnFollowup?.serviceLabel ||
    (Array.isArray(normalizedMaterialReturnFollowup?.recipientEmails) && normalizedMaterialReturnFollowup.recipientEmails.length > 0)
  );
  const materialReturnDisplayFollowup = normalizedMaterialReturnFollowup;
  const canReassignMaterialReturn = materialReturnDisplayFollowup?.status !== "cloture";
  const materialReturnCurrentUploadLink = materialReturnLinkOverride?.uploadLink || materialReturnDisplayFollowup?.uploadLink || null;
  const materialReturnCurrentUploadTokenExpiresAt = materialReturnLinkOverride?.uploadTokenExpiresAt || materialReturnDisplayFollowup?.uploadTokenExpiresAt || null;
  const materialReturnCurrentLastReminderSentAt = materialReturnLinkOverride?.lastReminderSentAt || materialReturnDisplayFollowup?.lastReminderSentAt || null;
  const materialReturnCurrentReactivatedAt = materialReturnLinkOverride?.reactivatedAt || materialReturnDisplayFollowup?.reactivatedAt || null;
  const materialReturnCurrentUploadLinkState = materialReturnLinkOverride?.uploadLinkState || materialReturnDisplayFollowup?.uploadLinkState || "expired";
  const materialReturnCurrentFinalPdfUrl = materialReturnDisplayFollowup?.finalPdfUrl || materialReturnDisplayFollowup?.signedFileUrl || null;
  const currentMaterialAssignmentLabel = normalizedMaterialReturnFollowup?.serviceLabel || 'Service non assigné';
  const materialReturnLitigationPending = normalizedMaterialReturnFollowup?.litigationStatus === 'pending';
  const suggestedReplacementValue = materialEventItems.reduce((sum, item) => {
    const quantity = Number.parseInt(litigationForm.blockedItems[item.key] || '0', 10);
    const replacementValue = logisticsPolicy?.replacementValues?.[item.key];
    if (!Number.isFinite(quantity) || quantity <= 0 || replacementValue === null || replacementValue === undefined) {
      return sum;
    }
    return sum + (quantity * replacementValue);
  }, 0);
  const materialReturnLocationReference = [
    formData.commune,
    formData.direction,
    formData.service,
  ]
    .map((value: unknown) => String(value || "").trim())
    .filter(Boolean)
    .join(' • ') || request?.associationInfo?.ville || request?.titre || '-';

  const openProcessDialog = () => {
    if (waitingForAssociationResponse) {
      toast.info("Cette demande est en attente de réponse de l’association. Le traitement reprendra dès que le devis sera accepté.");
      return;
    }
    const pricing = cadreDSU?.materielEvent?.financialDecision;
    setProcessData({
      status: request?.status === 'soumise' ? '' : request?.status || '',
      commentaireAdmin: request?.commentaireAdmin || '',
      montantAccorde: request?.montantAccorde ? String(request.montantAccorde / 100) : '',
      recapServiceId:
        typeof formData.notificationTrace?.serviceId === 'number'
          ? String(formData.notificationTrace.serviceId)
          : '',
      recapRecipients: Array.isArray(formData.notificationTrace?.recipients) ? formData.notificationTrace.recipients.join(', ') : '',
      recapServiceLabel: formData.notificationTrace?.serviceLabel || '',
      supervisionServiceId:
        typeof formData.notificationTrace?.supervisionServiceId === 'number'
          ? String(formData.notificationTrace.supervisionServiceId)
          : '',
      supervisionRecipients: Array.isArray(formData.notificationTrace?.supervisionRecipients)
        ? formData.notificationTrace.supervisionRecipients.join(', ')
        : Array.isArray(normalizedMaterialReturnFollowup?.supervisionRecipientEmails)
          ? normalizedMaterialReturnFollowup.supervisionRecipientEmails.join(', ')
          : '',
      supervisionServiceLabel:
        formData.notificationTrace?.supervisionServiceLabel
        || normalizedMaterialReturnFollowup?.supervisionServiceLabel
        || '',
    });
    setDsuData({
      dateReception: cadreDSU?.dateReception || new Date().toISOString().split('T')[0],
      avisDSU: cadreDSU?.avisDSU || '',
      conditionsParticulieres: cadreDSU?.conditionsParticulieres || '',
      cautionRequise: Boolean(cadreDSU?.cautionRequise),
      montantCaution: cadreDSU?.montantCaution || '',
      assuranceRequise: Boolean(cadreDSU?.assuranceRequise),
      horairesImposes: cadreDSU?.horairesImposes || '',
      responsableDSU: cadreDSU?.responsableDSU || '',
      dateDecision: cadreDSU?.dateDecision || new Date().toISOString().split('T')[0],
      observationsDSU: cadreDSU?.observationsDSU || '',
      salleReservation: {
        usageType: cadreDSU?.salleReservation?.usageType === 'occasionnel'
          ? 'occasionnel'
          : (formData?.typeUsage === 'occasionnel' ? 'occasionnel' : 'conventionne'),
        frequency: cadreDSU?.salleReservation?.frequency === 'demi_journee' || cadreDSU?.salleReservation?.frequency === 'mensuel'
          ? cadreDSU.salleReservation.frequency
          : (formData?.frequence === 'demi_journee' || formData?.frequence === 'mensuel' ? formData.frequence : 'journee'),
      },
      materielEvent: {
        itemsAccordes: { ...emptyMaterialEventSelection(), ...(cadreDSU?.materielEvent?.itemsAccordes || {}) },
        quantitesAccordees: { ...emptyMaterialEventQuantities(), ...(cadreDSU?.materielEvent?.quantitesAccordees || {}) },
        autresPrecisions: cadreDSU?.materielEvent?.autresPrecisions || '',
        financialDecision: {
          financialMode: (pricing?.financialMode || 'gratuite') as MaterialFinancialMode,
          depositRequired: Boolean(pricing?.depositRequired),
          depositAmountEuros: formatCentsAsEuroInput(pricing?.depositAmountCents ?? null),
          rentalAmountEuros: formatCentsAsEuroInput(pricing?.rentalAmountCents ?? null),
          pricingNotes: pricing?.pricingNotes || '',
          contractStatus: (pricing?.contractStatus || 'a_generer') as MaterialContractStatus,
          contractPdfUrl: pricing?.contractPdfUrl || '',
          contractPdfName: pricing?.contractPdfName || '',
          contractGeneratedAt: pricing?.contractGeneratedAt || '',
          contractValidatedByUserId: pricing?.contractValidatedByUserId ?? null,
        },
      },
    });
    setShowProcessDialog(true);
  };

  useEffect(() => {
    if (!normalizedMaterialReturnFollowup) return;

    const blockedItems = Object.fromEntries(
      materialEventItems.map((item) => {
        const fallbackQuantity = requestedMaterialItems.some((entry) => entry.key === item.key)
          ? parseMaterialEventQuantity(formData.quantitesDemandees?.[item.key])
          : 0;
        const currentQuantity = normalizedMaterialReturnFollowup.blockedItems?.[item.key] ?? fallbackQuantity;
        return [item.key, String(currentQuantity || 0)];
      })
    ) as Record<string, string>;

    setLitigationForm({
      blockedItems,
      estimatedDamageAmount: formatCentsAsEuroInput(normalizedMaterialReturnFollowup.estimatedDamageAmount ?? null),
      estimatedDamageSource: normalizedMaterialReturnFollowup.estimatedDamageSource === "replacement_value" ? "replacement_value" : "manual",
      arbitrationDecision: normalizedMaterialReturnFollowup.arbitrationDecision || "partial_retention",
      arbitrationAmount: formatCentsAsEuroInput(normalizedMaterialReturnFollowup.arbitrationAmount ?? null),
      arbitrationNotes: normalizedMaterialReturnFollowup.arbitrationNotes || "",
    });
  }, [formData.quantitesDemandees, normalizedMaterialReturnFollowup, requestedMaterialItems]);

  if (isLoading) {
    return (
      <div className="portal-immersive-page min-h-screen overflow-x-hidden">
        <header className="border-b border-border bg-white sticky top-0 z-10">
          <div className="container py-4">
            <div className="flex flex-col items-start gap-3 sm:flex-row sm:items-center sm:gap-4">
              <Link href={backUrl}>
                <Button variant="ghost" className="gap-2 px-0 sm:px-3">
                  <ArrowLeft className="h-5 w-5" />
                  Retour
                </Button>
              </Link>
              <div>
                <h1 className="text-xl font-bold">Chargement de la demande</h1>
                <p className="text-sm text-muted-foreground">Préparation du suivi détaillé de votre dossier</p>
              </div>
            </div>
          </div>
        </header>
        <main className="container py-8">
          <div className="mx-auto max-w-5xl">
            <AuthenticatedPageSkeleton
              hero={false}
              message="Chargement des informations du dossier, des documents et du suivi de traitement..."
              cards={2}
              formRows={4}
            />
          </div>
        </main>
      </div>
    );
  }

  if (!request || error) {
    return (
      <div className="portal-immersive-page min-h-screen overflow-x-hidden">
        <header className="border-b border-border bg-white sticky top-0 z-10">
          <div className="container py-4">
            <div className="flex flex-col items-start gap-3 sm:flex-row sm:items-center sm:gap-4">
              <Link href={backUrl}>
                <Button variant="ghost" className="gap-2 px-0 sm:px-3">
                  <ArrowLeft className="h-5 w-5" />
                  Retour
                </Button>
              </Link>
              <h1 className="text-xl font-bold">Demande introuvable</h1>
            </div>
          </div>
        </header>
        <main className="container py-8">
          <Card className="max-w-md mx-auto">
            <CardContent className="py-12 text-center">
              <p className="text-muted-foreground">Cette demande n'existe pas ou vous n'y avez pas accès.</p>
              <Link href={backUrl}>
                <Button className="mt-4">Retour aux demandes</Button>
              </Link>
            </CardContent>
          </Card>
        </main>
      </div>
    );
  }

  return (
    <div className="portal-immersive-page min-h-screen overflow-x-hidden">
      {/* Header */}
      <header className="border-b border-border bg-white sticky top-0 z-10">
        <div className="container py-4">
          <div className="flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between">
            <div className="flex min-w-0 flex-col items-start gap-3 sm:flex-row sm:items-start sm:gap-4">
              <Link href={backUrl}>
                <Button variant="ghost" className="self-start gap-2 px-0 sm:px-3">
                  <ArrowLeft className="h-5 w-5" />
                  Retour
                </Button>
              </Link>
              <div className="min-w-0">
                <h1 className="break-words text-[1.7rem] font-bold leading-tight sm:text-3xl">{request.titre}</h1>
                <div className="mt-2 flex flex-wrap items-center gap-1.5 sm:gap-2">
                  <p className="text-sm text-muted-foreground">
                    {requestTypeLabels[request.type] || request.type}
                  </p>
                  <Badge variant="outline" className={requestDisplayStatusMeta.className}>
                    {requestDisplayStatusMeta.label}
                  </Badge>
                </div>
              </div>
            </div>
            <div className="flex w-full flex-col gap-2 sm:flex-row sm:flex-wrap xl:w-auto xl:justify-end">
              {canEdit && (
                <Link href={`/dashboard/requests/${request.id}/edit`} {...buildRoutePrefetchHandlers(`/dashboard/requests/${request.id}/edit`)}>
                  <Button variant="outline" className="w-full sm:w-auto">
                    <Edit className="mr-2 h-4 w-4" />
                    Éditer
                  </Button>
                </Link>
              )}
              {canRespondToSalleQuote && (
                <>
                  <Button
                    onClick={() => respondSalleQuoteMutation.mutate({ id: request.id, decision: "accepte" })}
                    disabled={respondSalleQuoteMutation.isPending}
                    className="w-full sm:w-auto"
                  >
                    {respondSalleQuoteMutation.isPending ? (
                      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    ) : (
                      <CheckCircle className="mr-2 h-4 w-4" />
                    )}
                    J’accepte le devis
                  </Button>
                  <Button
                    variant="destructive"
                    onClick={() => respondSalleQuoteMutation.mutate({ id: request.id, decision: "refuse" })}
                    disabled={respondSalleQuoteMutation.isPending}
                    className="w-full sm:w-auto"
                  >
                    {respondSalleQuoteMutation.isPending ? (
                      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                    ) : (
                      <XCircle className="mr-2 h-4 w-4" />
                    )}
                    Je refuse le devis
                  </Button>
                </>
              )}
              {!isAdmin && (
                <Button
                  variant="outline"
                  onClick={() => duplicateMutation.mutate({ id: request.id })}
                  disabled={duplicateMutation.isPending}
                  className="w-full sm:w-auto"
                >
                  {duplicateMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <Copy className="mr-2 h-4 w-4" />
                  )}
                  Dupliquer la demande
                </Button>
              )}
              {(request.status === 'brouillon' || request.status === 'information_complementaire') && !isAdmin && (
                <Button 
                  onClick={() => submitMutation.mutate({ id: request.id })}
                  disabled={submitMutation.isPending}
                  className="w-full sm:w-auto"
                >
                  {submitMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <Send className="mr-2 h-4 w-4" />
                  )}
                  {request.status === 'information_complementaire' ? 'Renvoyer' : 'Soumettre'}
                </Button>
              )}
              {canProcess && (
                <Button 
                  onClick={openProcessDialog}
                  className="bg-primary"
                >
                  <Settings className="mr-2 h-4 w-4" />
                  Traiter la demande
                </Button>
              )}
              {isAdmin && waitingForAssociationResponse && (
                <Button variant="outline" disabled className="w-full whitespace-normal text-left sm:w-auto">
                  Réponse de l’association attendue
                </Button>
              )}
              {canSendSalleQuote && materialFinancialDecision?.financialMode && (
                <Button
                  variant="outline"
                  onClick={() => sendSalleQuoteMutation.mutate({ id: request.id })}
                  disabled={sendSalleQuoteMutation.isPending}
                  className="w-full sm:w-auto"
                >
                  {sendSalleQuoteMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <Send className="mr-2 h-4 w-4" />
                  )}
                  Envoyer le devis
                </Button>
              )}
              {canSendSalleToDirector && (
                <Button
                  variant="outline"
                  onClick={() => sendSalleToDirectorMutation.mutate({ id: request.id })}
                  disabled={sendSalleToDirectorMutation.isPending}
                  className="w-full whitespace-normal sm:w-auto"
                >
                  {sendSalleToDirectorMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <ExternalLink className="mr-2 h-4 w-4" />
                  )}
                  Transmettre à la Directrice
                </Button>
              )}
              {canFinalizeSalle && (
                <Button
                  onClick={() => finalizeSalleReservationMutation.mutate({ id: request.id })}
                  disabled={finalizeSalleReservationMutation.isPending}
                  className="w-full sm:w-auto"
                >
                  {finalizeSalleReservationMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <CheckCircle className="mr-2 h-4 w-4" />
                  )}
                  Signer et valider
                </Button>
              )}
              {canPrepareSalleFinalNotification && (
                <Button
                  onClick={() => prepareSalleFinalNotificationMutation.mutate({ id: request.id })}
                  disabled={prepareSalleFinalNotificationMutation.isPending}
                  className="w-full whitespace-normal sm:w-auto"
                >
                  {prepareSalleFinalNotificationMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <Send className="mr-2 h-4 w-4" />
                  )}
                  Envoyer confirmation finale
                </Button>
              )}
              {canAssignMaterialReturn && (
                <Button
                  variant={materialReturnAssigned ? "outline" : "default"}
                  onClick={() => {
                    setLogisticsAssignmentData({
                      recapServiceId: '',
                      recapServiceLabel: normalizedMaterialReturnFollowup?.serviceLabel || '',
                      recapRecipients: Array.isArray(normalizedMaterialReturnFollowup?.recipientEmails)
                        ? normalizedMaterialReturnFollowup.recipientEmails.join(', ')
                        : '',
                      supervisionServiceId: '',
                      supervisionServiceLabel: normalizedMaterialReturnFollowup?.supervisionServiceLabel || '',
                      supervisionRecipients: Array.isArray(normalizedMaterialReturnFollowup?.supervisionRecipientEmails)
                        ? normalizedMaterialReturnFollowup.supervisionRecipientEmails.join(', ')
                        : '',
                    });
                    setShowLogisticsAssignmentDialog(true);
                  }}
                  className="w-full whitespace-normal sm:w-auto"
                >
                  <Users className="mr-2 h-4 w-4" />
                  {materialReturnAssigned ? 'Modifier l’assignation' : 'Assigner la récupération'}
                </Button>
              )}
              {isAdmin && user?.role !== 'accueil' && (request.status === 'validee' || request.status === 'refusee') && (
                <Button
                  variant="outline"
                  onClick={() => reopenMutation.mutate({ id: request.id })}
                  disabled={reopenMutation.isPending}
                  className="w-full sm:w-auto"
                >
                  {reopenMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <RotateCcw className="mr-2 h-4 w-4" />
                  )}
                  Rouvrir la demande
                </Button>
              )}
              {(isDemandeSalle || isDemandeMaterielEvenementiel) && (request.status === 'validee' || request.status === 'refusee') && (
                <Button
                  variant="outline"
                  onClick={() => pdfMutation.mutate({ id: request.id })}
                  disabled={pdfMutation.isPending}
                  className="w-full whitespace-normal sm:w-auto"
                >
                  {pdfMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <Download className="mr-2 h-4 w-4" />
                  )}
                  Télécharger le document
                </Button>
              )}
              {isAdmin && requestNeedsFinancialDecision && request.status === 'validee' && materialFinancialDecision?.financialMode && (
                <Button
                  variant="outline"
                  onClick={() => activeContractMutation.mutate({ id: request.id })}
                  disabled={activeContractMutation.isPending}
                  className="w-full whitespace-normal sm:w-auto"
                >
                  {activeContractMutation.isPending ? (
                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                  ) : (
                    <FileText className="mr-2 h-4 w-4" />
                  )}
                  {materialFinancialDecision.contractPdfUrl ? 'Régénérer la convention' : 'Générer la convention'}
                </Button>
              )}
              {canCancel && (
                <Button
                  variant="outline"
                  className="w-full border-orange-300 text-orange-600 hover:bg-orange-50 sm:w-auto"
                  onClick={() => setShowCancelDialog(true)}
                >
                  <Ban className="mr-2 h-4 w-4" />
                  Annuler la demande
                </Button>
              )}
              {canDelete && (
                <AlertDialog>
                  <AlertDialogTrigger asChild>
                    <Button variant="destructive" size="sm">
                      <Trash2 className="mr-2 h-4 w-4" />
                      Supprimer
                    </Button>
                  </AlertDialogTrigger>
                  <AlertDialogContent>
                    <AlertDialogHeader>
                      <AlertDialogTitle>Supprimer cette demande ?</AlertDialogTitle>
                      <AlertDialogDescription>
                        Cette action est irréversible. La demande « {request.titre} » sera définitivement supprimée.
                      </AlertDialogDescription>
                    </AlertDialogHeader>
                    <AlertDialogFooter>
                      <AlertDialogCancel>Annuler</AlertDialogCancel>
                      <AlertDialogAction
                        onClick={() => deleteMutation.mutate({ id: request.id })}
                        className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
                      >
                        {deleteMutation.isPending ? (
                          <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                        ) : (
                          <Trash2 className="mr-2 h-4 w-4" />
                        )}
                        Supprimer définitivement
                      </AlertDialogAction>
                    </AlertDialogFooter>
                  </AlertDialogContent>
                </AlertDialog>
              )}
            </div>
          </div>
        </div>
      </header>

      <main className="container py-8">
        <div className="max-w-3xl mx-auto space-y-6">
          {submittedFlag ? (
            <Card className="border-emerald-200 bg-emerald-50/80">
              <CardContent className="flex flex-col gap-4 p-6 md:flex-row md:items-center md:justify-between">
                <div className="space-y-2">
                  <div className="flex items-center gap-2 text-emerald-700">
                    <CheckCircle className="h-5 w-5" />
                    <p className="font-semibold">Votre demande a bien été transmise</p>
                  </div>
                  <p className="text-sm text-muted-foreground">
                    {submittedSource === "reservation-salle"
                      ? "Votre réservation a été enregistrée. Elle sera étudiée par le service concerné et vous pourrez suivre ici les prochaines étapes."
                      : submittedSource === "materiel-evenementiel"
                        ? "Votre demande de matériel a bien été enregistrée. Le service concerné l'examinera puis vous informera de la suite."
                        : "Votre demande est enregistrée. Elle sera étudiée par le service concerné et vous pourrez suivre son avancement depuis cette fiche."}
                  </p>
                </div>
                <div className="flex flex-wrap gap-3">
                  <Link href="/dashboard/requests" {...buildRoutePrefetchHandlers("/dashboard/requests")}>
                    <Button variant="outline">Suivre mes demandes</Button>
                  </Link>
                  <Link href="/dashboard" {...buildRoutePrefetchHandlers("/dashboard")}>
                    <Button>Retour au tableau de bord</Button>
                  </Link>
                </div>
              </CardContent>
            </Card>
          ) : null}

          {/* Status card */}
          <Card className={`border-2 ${request.status === 'validee' ? 'border-green-200 bg-green-50' : request.status === 'refusee' ? 'border-red-200 bg-red-50' : 'border-primary/20 bg-primary/5'}`}>
            <CardContent className="py-6">
              <div className="flex items-center gap-4">
                <div className={`w-12 h-12 rounded-full flex items-center justify-center ${status.className}`}>
                  <StatusIcon status={request.status} />
                </div>
                <div>
                  <h2 className="text-lg font-semibold">{status.label}</h2>
                  <p className="text-sm text-muted-foreground">
                    {request.status === 'brouillon' && 'Cette demande n\'a pas encore été soumise'}
                    {request.status === 'soumise' && 'Votre demande a été envoyée et est en attente de traitement'}
                    {request.status === 'en_cours_traitement' && 'Votre demande est en cours d\'examen'}
                    {request.status === 'information_complementaire' && 'Des informations supplémentaires sont nécessaires'}
                    {request.status === 'validee' && 'Félicitations ! Votre demande a été acceptée'}
                    {request.status === 'refusee' && 'Votre demande n\'a pas été retenue'}
                  </p>
                </div>
              </div>
              {request.commentaireAdmin && (
                <div className="mt-4 p-4 bg-white rounded-lg border">
                  <p className="text-sm font-medium mb-1">Commentaire du service :</p>
                  <p className="text-sm text-muted-foreground">{request.commentaireAdmin}</p>
                </div>
              )}
            </CardContent>
          </Card>

          {isAdmin && formData.notificationTrace && (
            <Card className="border-primary/20">
              <CardHeader>
                <CardTitle className="text-base">Traçabilité de diffusion</CardTitle>
                <CardDescription>
                  Récapitulatif interne lié au traitement de cette demande.
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-2 text-sm">
                <div className="flex justify-between py-1.5 border-b border-dashed">
                  <span className="text-muted-foreground">Service terrain / récupération :</span>
                  <span className="font-medium">{formData.notificationTrace.serviceLabel || '-'}</span>
                </div>
                <div className="flex justify-between py-1.5 border-b border-dashed">
                  <span className="text-muted-foreground">Destinataires :</span>
                  <span className="font-medium text-right max-w-[60%]">
                    {Array.isArray(formData.notificationTrace.recipients) && formData.notificationTrace.recipients.length > 0
                      ? formData.notificationTrace.recipients.join(', ')
                      : '-'}
                  </span>
                </div>
                <div className="flex justify-between py-1.5 border-b border-dashed">
                  <span className="text-muted-foreground">Canal :</span>
                  <span className="font-medium">{formData.notificationTrace.channel || '-'}</span>
                </div>
                <div className="flex justify-between py-1.5 border-b border-dashed">
                  <span className="text-muted-foreground">Traité par :</span>
                  <span className="font-medium">{formData.notificationTrace.processedBy || '-'}</span>
                </div>
                <div className="flex justify-between py-1.5 border-b border-dashed">
                  <span className="text-muted-foreground">Date :</span>
                  <span className="font-medium">{formatDateTime(formData.notificationTrace.processedAt || null)}</span>
                </div>
              </CardContent>
            </Card>
          )}

          {canAssignMaterialReturn && (
            <Card className={materialReturnAssigned ? "border-primary/20" : "border-orange-200 bg-orange-50/60"}>
              <CardHeader>
                <CardTitle className="text-base flex items-center gap-2">
                  <Users className="h-5 w-5 text-primary" />
                  Assignation logistique
                </CardTitle>
                <CardDescription>
                  Depuis ce dossier, l’administration peut attribuer ou ajuster immédiatement le service chargé de la récupération.
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                <div className="flex flex-wrap items-center gap-3">
                  <Badge className={materialReturnAssigned ? "bg-blue-100 text-blue-700 border-blue-200" : "bg-orange-100 text-orange-700 border-orange-200"}>
                    {materialReturnAssigned ? "Assigné" : "Non assigné"}
                  </Badge>
                  <span className="text-sm text-muted-foreground">
                    {materialReturnAssigned
                      ? `Actuellement : ${currentMaterialAssignmentLabel}`
                      : "Aucun agent ou service n'est encore désigné pour la restitution."}
                  </span>
                </div>
                <div className="rounded-lg border bg-background p-4 space-y-2">
                  <p className="text-sm font-medium">Ce que l’agent recevra</p>
                  <p className="text-sm text-muted-foreground">
                    Un lien terrain sécurisé, la fiche préremplie et le suivi automatique du retour matériel.
                  </p>
                  <p className="text-sm text-muted-foreground">
                    Le service de suivi interne reçoit séparément les confirmations de restitution, les retards et les alertes.
                  </p>
                </div>
                <div className="flex flex-wrap gap-2">
                  {canReassignMaterialReturn ? (
                    <Button
                      onClick={() => {
                      setLogisticsAssignmentData({
                        recapServiceId: '',
                        recapServiceLabel: normalizedMaterialReturnFollowup?.serviceLabel || '',
                        recapRecipients: Array.isArray(normalizedMaterialReturnFollowup?.recipientEmails)
                          ? normalizedMaterialReturnFollowup.recipientEmails.join(', ')
                          : '',
                        supervisionServiceId: '',
                        supervisionServiceLabel: normalizedMaterialReturnFollowup?.supervisionServiceLabel || '',
                        supervisionRecipients: Array.isArray(normalizedMaterialReturnFollowup?.supervisionRecipientEmails)
                          ? normalizedMaterialReturnFollowup.supervisionRecipientEmails.join(', ')
                          : '',
                      });
                      setShowLogisticsAssignmentDialog(true);
                      }}
                    >
                      <Users className="mr-2 h-4 w-4" />
                      {materialReturnAssigned ? "Réassigner et relancer" : "Assigner le service terrain"}
                    </Button>
                  ) : null}
                  <DetailOverflowMenu label="Actions logistiques complémentaires">
                    <DropdownMenuItem asChild>
                      <Link href="/admin?tab=logistique" {...buildRoutePrefetchHandlers("/admin?tab=logistique")}>
                        <ExternalLink className="h-4 w-4" />
                        Ouvrir le pilotage logistique
                      </Link>
                    </DropdownMenuItem>
                  </DetailOverflowMenu>
                </div>
              </CardContent>
            </Card>
          )}

          {canManageLogistics && isDemandeMaterielEvenementiel && materialReturnDisplayFollowup && (
            <Card className="border-primary/20">
              <CardHeader>
                <CardTitle className="text-base">Suivi de restitution</CardTitle>
                <CardDescription>
                  Pilotage automatique de la fiche d’état des lieux et du retour du matériel.
                </CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                <div className="flex flex-wrap items-center gap-3">
                  <Badge className={materialReturnStatusClasses[materialReturnDisplayFollowup.status] || materialReturnStatusClasses.planifie}>
                    {materialReturnStatusLabels[materialReturnDisplayFollowup.status] || materialReturnDisplayFollowup.status}
                  </Badge>
                  <Badge
                    variant="outline"
                    className={
                      materialReturnUploadLinkStateClasses[materialReturnCurrentUploadLinkState]
                      || materialReturnUploadLinkStateClasses.expired
                    }
                  >
                    Lien {materialReturnUploadLinkStateLabels[materialReturnCurrentUploadLinkState] || "Expiré"}
                  </Badge>
                  {materialReturnDisplayFollowup.issueFlag ? (
                    <Badge className="bg-amber-100 text-amber-800 border-amber-200">
                      Alerte dégradation / litige
                    </Badge>
                  ) : null}
                  <span className="text-sm text-muted-foreground">
                    Restitution prévue le {formatDateFr(materialReturnDisplayFollowup.restitutionDate)}
                  </span>
                </div>
                <div className="grid gap-2 text-sm">
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Envoi programmé</span>
                    <span className="font-medium">{formatDateTime(materialReturnDisplayFollowup.plannedSendAt || null)}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Document envoyé</span>
                    <span className="font-medium">{formatDateTime(materialReturnDisplayFollowup.sentAt || null)}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Service terrain / récupération</span>
                    <span className="font-medium text-right max-w-[60%]">{materialReturnDisplayFollowup.serviceLabel || '-'}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Destinataires terrain</span>
                    <span className="font-medium text-right max-w-[60%]">
                      {Array.isArray(materialReturnDisplayFollowup.recipientEmails) && materialReturnDisplayFollowup.recipientEmails.length > 0
                        ? materialReturnDisplayFollowup.recipientEmails.join(', ')
                        : '-'}
                    </span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Service interne de contrôle</span>
                    <span className="font-medium text-right max-w-[60%]">{materialReturnDisplayFollowup.supervisionServiceLabel || '-'}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Destinataires du contrôle interne</span>
                    <span className="font-medium text-right max-w-[60%]">
                      {Array.isArray(materialReturnDisplayFollowup.supervisionRecipientEmails) && materialReturnDisplayFollowup.supervisionRecipientEmails.length > 0
                        ? materialReturnDisplayFollowup.supervisionRecipientEmails.join(', ')
                        : '-'}
                    </span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Dépôt attendu jusqu’au</span>
                    <span className="font-medium">{formatDateFr(materialReturnCurrentUploadTokenExpiresAt)}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Dernière relance</span>
                    <span className="font-medium">{formatDateTime(materialReturnCurrentLastReminderSentAt)}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Suivi rouvert le</span>
                    <span className="font-medium">{formatDateTime(materialReturnCurrentReactivatedAt)}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Réactivé par</span>
                    <span className="font-medium text-right max-w-[60%]">{materialReturnDisplayFollowup.reactivatedByName || '-'}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Conformité</span>
                    <span className="font-medium">
                      {materialReturnDisplayFollowup.compliance === 'non_conforme' ? 'Non conforme / partielle' : materialReturnDisplayFollowup.compliance === 'conforme' ? 'Conforme' : '-'}
                    </span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Fiche déposée</span>
                    <span className="font-medium">{formatDateTime(materialReturnDisplayFollowup.uploadedAt || null)}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Validation finale</span>
                    <span className="font-medium">{formatDateTime(materialReturnDisplayFollowup.validatedAt || null)}</span>
                  </div>
                  <div className="flex justify-between py-1.5 border-b border-dashed">
                    <span className="text-muted-foreground">Lieu de constat</span>
                    <span className="font-medium text-right max-w-[60%]">
                      {materialReturnDisplayFollowup.geoLatitude && materialReturnDisplayFollowup.geoLongitude
                        ? `📍 ${materialReturnDisplayFollowup.geoLatitude}, ${materialReturnDisplayFollowup.geoLongitude}`
                        : materialReturnLocationReference}
                    </span>
                  </div>
                  {!materialReturnDisplayFollowup.geoLatitude || !materialReturnDisplayFollowup.geoLongitude ? (
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">État GPS</span>
                      <span className="font-medium text-right max-w-[60%]">
                        {materialReturnDisplayFollowup.geoFailureReason
                          ? `Non disponible (${materialReturnDisplayFollowup.geoFailureReason})`
                          : 'Non disponible'}
                      </span>
                    </div>
                  ) : null}
                </div>
                <div className="rounded-lg border bg-muted/20 p-4 space-y-2">
                  <p className="text-sm font-medium">
                    {materialReturnCurrentUploadLinkState === "expired"
                      ? "Le lien terrain est expiré, mais le suivi peut être rouvert."
                      : materialReturnCurrentUploadLinkState === "closed"
                        ? "Le suivi est clôturé. Aucun nouveau dépôt n’est attendu."
                        : "Le lien terrain est actif et peut être renvoyé à l’agent si nécessaire."}
                  </p>
                  <p className="text-sm text-muted-foreground">
                    On garde le même suivi de restitution. L’action ci-dessous réactive la fenêtre de dépôt si besoin et renvoie toujours un lien actif sans créer une nouvelle demande.
                  </p>
                </div>
                <div className="flex flex-wrap gap-2">
                  {materialReturnDisplayFollowup.status !== "cloture" ? (
                    <Button
                      variant={materialReturnCurrentUploadLinkState === "expired" ? "default" : "outline"}
                      onClick={() =>
                        handleMaterialReturnReactivation(
                          materialReturnCurrentUploadLinkState === "expired"
                            ? "Suivi rouvert et lien de restitution renvoyé"
                            : "Lien de restitution renvoyé"
                        )
                      }
                      disabled={reactivateMaterialReturnMutation.isPending || materialReturnLitigationPending}
                    >
                      {reactivateMaterialReturnMutation.isPending ? (
                        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                      ) : materialReturnCurrentUploadLinkState === "expired" ? (
                        <RotateCcw className="mr-2 h-4 w-4" />
                      ) : (
                        <Send className="mr-2 h-4 w-4" />
                      )}
                      {materialReturnCurrentUploadLinkState === "expired"
                        ? "Rouvrir et renvoyer le lien"
                        : "Renvoyer le lien actif"}
                    </Button>
                  ) : null}
                  {materialReturnCurrentUploadLink ? (
                    <a href={appendReturnToParam(materialReturnCurrentUploadLink, location)} target="_blank" rel="noopener noreferrer">
                      <Button variant="ghost">
                        <ExternalLink className="mr-2 h-4 w-4" />
                        Ouvrir le lien terrain
                      </Button>
                    </a>
                  ) : null}
                </div>
                {Array.isArray(materialReturnDisplayFollowup.discrepancyCategories) && materialReturnDisplayFollowup.discrepancyCategories.length > 0 ? (
                  <div className="rounded-lg border bg-muted/20 p-3 text-sm">
                    <p className="font-medium mb-2">Réserves signalées</p>
                    <p className="text-muted-foreground">{materialReturnDisplayFollowup.discrepancyCategories.join(', ')}</p>
                    {materialReturnDisplayFollowup.discrepancyDetails ? (
                      <p className="mt-2">{materialReturnDisplayFollowup.discrepancyDetails}</p>
                    ) : null}
                  </div>
                ) : null}
                {materialReturnDisplayFollowup.issueFlag ? (
                  <div className="rounded-lg border border-amber-200 bg-amber-50/70 p-4 space-y-4">
                    <div className="flex flex-wrap items-center justify-between gap-3">
                      <div>
                        <p className="font-medium text-amber-900">Arbitrage financier du litige</p>
                        <p className="text-sm text-amber-800">
                          Le stock reste gelé tant que l'arbitrage n'est pas validé.
                        </p>
                      </div>
                      <Badge className={materialReturnLitigationPending ? "bg-red-100 text-red-700 border-red-200" : "bg-green-100 text-green-700 border-green-200"}>
                        {materialReturnLitigationPending ? "Arbitrage en attente" : "Arbitrage clôturé"}
                      </Badge>
                    </div>

                    <div className="grid gap-4 md:grid-cols-2">
                      {materialEventItems.map((item) => (
                        <div key={item.key} className="rounded-lg border bg-white p-3 space-y-2">
                          <div className="flex items-center justify-between gap-3">
                            <Label htmlFor={`litigation-${item.key}`}>{item.label}</Label>
                            <span className="text-xs text-muted-foreground">
                              valeur {formatAmount(logisticsPolicy?.replacementValues?.[item.key] ?? null)}
                            </span>
                          </div>
                          <Input
                            id={`litigation-${item.key}`}
                            type="number"
                            min={0}
                            value={litigationForm.blockedItems[item.key] ?? "0"}
                            onChange={(event) =>
                              setLitigationForm((prev) => ({
                                ...prev,
                                blockedItems: {
                                  ...prev.blockedItems,
                                  [item.key]: event.target.value,
                                },
                              }))
                            }
                            disabled={!materialReturnLitigationPending || resolveLitigationMutation.isPending}
                          />
                          <p className="text-xs text-muted-foreground">
                            Quantité maintenue en indisponibilité tant que le litige n'est pas arbitré.
                          </p>
                        </div>
                      ))}
                    </div>

                    <div className="grid gap-4 md:grid-cols-2">
                      <div className="space-y-2">
                        <Label>Source du chiffrage</Label>
                        <Select
                          value={litigationForm.estimatedDamageSource}
                          onValueChange={(value: "manual" | "replacement_value") =>
                            setLitigationForm((prev) => ({ ...prev, estimatedDamageSource: value }))
                          }
                          disabled={!materialReturnLitigationPending || resolveLitigationMutation.isPending}
                        >
                          <SelectTrigger>
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="manual">Devis / saisie manuelle</SelectItem>
                            <SelectItem value="replacement_value">Valeur de remplacement</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-2">
                        <Label htmlFor="estimatedDamageAmount">Prejudice estime (EUR)</Label>
                        <Input
                          id="estimatedDamageAmount"
                          type="number"
                          min={0}
                          step="0.01"
                          value={litigationForm.estimatedDamageAmount}
                          onChange={(event) => setLitigationForm((prev) => ({ ...prev, estimatedDamageAmount: event.target.value }))}
                          disabled={litigationForm.estimatedDamageSource === 'replacement_value' || !materialReturnLitigationPending || resolveLitigationMutation.isPending}
                          placeholder={litigationForm.estimatedDamageSource === 'replacement_value' ? formatCentsAsEuroInput(suggestedReplacementValue) : '0.00'}
                        />
                        {litigationForm.estimatedDamageSource === 'replacement_value' ? (
                          <p className="text-xs text-muted-foreground">
                            Calcul automatique actuel : {formatAmount(suggestedReplacementValue)}
                          </p>
                        ) : null}
                      </div>
                      <div className="space-y-2">
                        <Label>Décision d'arbitrage</Label>
                        <Select
                          value={litigationForm.arbitrationDecision}
                          onValueChange={(value: "partial_retention" | "full_retention" | "dismissed") =>
                            setLitigationForm((prev) => ({ ...prev, arbitrationDecision: value }))
                          }
                          disabled={!materialReturnLitigationPending || resolveLitigationMutation.isPending}
                        >
                          <SelectTrigger>
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="partial_retention">Retenue partielle sur caution</SelectItem>
                            <SelectItem value="full_retention">Encaissement total de la caution</SelectItem>
                            <SelectItem value="dismissed">Classement sans suite</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>
                      <div className="space-y-2">
                        <Label htmlFor="arbitrationAmount">Montant retenu (EUR)</Label>
                        <Input
                          id="arbitrationAmount"
                          type="number"
                          min={0}
                          step="0.01"
                          value={litigationForm.arbitrationAmount}
                          onChange={(event) => setLitigationForm((prev) => ({ ...prev, arbitrationAmount: event.target.value }))}
                          disabled={!materialReturnLitigationPending || resolveLitigationMutation.isPending}
                          placeholder="0.00"
                        />
                      </div>
                    </div>

                    <div className="space-y-2">
                      <Label htmlFor="arbitrationNotes">Observations administratives</Label>
                      <Textarea
                        id="arbitrationNotes"
                        value={litigationForm.arbitrationNotes}
                        onChange={(event) => setLitigationForm((prev) => ({ ...prev, arbitrationNotes: event.target.value }))}
                        rows={4}
                        disabled={!materialReturnLitigationPending || resolveLitigationMutation.isPending}
                        placeholder="Ex. arbitrage validé après devis atelier, matériel libéré après remplacement..."
                      />
                    </div>

                    {materialReturnLitigationPending ? (
                      <Button
                        onClick={() => {
                          const blockedItems = Object.fromEntries(
                            materialEventItems.map((item) => [item.key, Number.parseInt(litigationForm.blockedItems[item.key] || '0', 10) || 0])
                          );
                          resolveLitigationMutation.mutate({
                            requestId,
                            blockedItems,
                            estimatedDamageAmount: litigationForm.estimatedDamageSource === 'manual'
                              ? parseEuroInputToCents(litigationForm.estimatedDamageAmount)
                              : null,
                            estimatedDamageSource: litigationForm.estimatedDamageSource,
                            arbitrationDecision: litigationForm.arbitrationDecision,
                            arbitrationAmount: parseEuroInputToCents(litigationForm.arbitrationAmount),
                            arbitrationNotes: litigationForm.arbitrationNotes,
                          });
                        }}
                        disabled={resolveLitigationMutation.isPending}
                      >
                        {resolveLitigationMutation.isPending ? (
                          <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                        ) : (
                          <Shield className="mr-2 h-4 w-4" />
                        )}
                        Clôturer l'arbitrage
                      </Button>
                    ) : (
                      <div className="grid gap-2 text-sm">
                        <div className="flex justify-between py-1.5 border-b border-dashed">
                          <span className="text-muted-foreground">Décision retenue</span>
                          <span className="font-medium">
                            {materialReturnDisplayFollowup.arbitrationDecision === 'full_retention'
                              ? 'Encaissement total de la caution'
                              : materialReturnDisplayFollowup.arbitrationDecision === 'dismissed'
                                ? 'Classement sans suite'
                                : 'Retenue partielle sur caution'}
                          </span>
                        </div>
                        <div className="flex justify-between py-1.5 border-b border-dashed">
                          <span className="text-muted-foreground">Montant arbitrage</span>
                          <span className="font-medium">{formatAmount(materialReturnDisplayFollowup.arbitrationAmount ?? null)}</span>
                        </div>
                        <div className="flex justify-between py-1.5 border-b border-dashed">
                          <span className="text-muted-foreground">Préjudice estimé</span>
                          <span className="font-medium">{formatAmount(materialReturnDisplayFollowup.estimatedDamageAmount ?? null)}</span>
                        </div>
                        {materialReturnDisplayFollowup.arbitrationNotes ? (
                          <div className="rounded-lg border bg-white p-3">
                            <p className="font-medium mb-1">Notes d'arbitrage</p>
                            <p className="text-muted-foreground">{materialReturnDisplayFollowup.arbitrationNotes}</p>
                          </div>
                        ) : null}
                      </div>
                    )}

                    {(materialReturnDisplayFollowup.litigationLetterUrl || materialReturnCurrentFinalPdfUrl) ? (
                      <DetailOverflowMenu label="Documents de restitution">
                        {materialReturnDisplayFollowup.litigationLetterUrl ? (
                          <DropdownMenuItem asChild>
                            <a href={materialReturnDisplayFollowup.litigationLetterUrl} target="_blank" rel="noopener noreferrer">
                              <FileText className="h-4 w-4" />
                              Télécharger le courrier de litige
                            </a>
                          </DropdownMenuItem>
                        ) : null}
                        {materialReturnCurrentFinalPdfUrl ? (
                          <DropdownMenuItem asChild>
                            <a
                              href={buildMaterialReturnFinalPdfViewerHref({
                                url: materialReturnCurrentFinalPdfUrl,
                                returnTo: location,
                                title: "Consulter le PDF final de restitution",
                                downloadName: `fiche-finale-restitution-${request.id}.pdf`,
                              })}
                            >
                              <Download className="h-4 w-4" />
                              Télécharger le PDF final
                            </a>
                          </DropdownMenuItem>
                        ) : null}
                      </DetailOverflowMenu>
                    ) : null}
                  </div>
                ) : null}
              </CardContent>
            </Card>
          )}

          {isAdmin && isDemandeSalle && (
            <Card className="border-primary/20 bg-primary/5">
              <CardHeader>
                <CardTitle className="flex items-center gap-2">
                  <Clock className="h-5 w-5 text-primary" />
                  Résumé administratif
                </CardTitle>
                <CardDescription>
                  Repères rapides pour instruire la demande de salle.
                </CardDescription>
              </CardHeader>
              <CardContent>
                <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
                  <div className="rounded-lg border bg-white p-4">
                    <p className="text-xs text-muted-foreground">Salle(s)</p>
                    <p className="font-semibold mt-1">
                      {(formData.sallesSelectionnees as string[])?.join(', ') || '-'}
                    </p>
                  </div>
                  <div className="rounded-lg border bg-white p-4">
                    <p className="text-xs text-muted-foreground">Période</p>
                    <p className="font-semibold mt-1">{reservationPeriodSummary}</p>
                  </div>
                  <div className="rounded-lg border bg-white p-4">
                    <p className="text-xs text-muted-foreground">Organisation horaire</p>
                    <p className="font-semibold mt-1">{reservationScheduleSummary}</p>
                  </div>
                  <div className="rounded-lg border bg-white p-4">
                    <p className="text-xs text-muted-foreground">Participants</p>
                    <p className="font-semibold mt-1">
                      {formData.nombreParticipants ? `${formData.nombreParticipants} personnes` : '-'}
                    </p>
                  </div>
                </div>
              </CardContent>
            </Card>
          )}

          {/* ============================================================ */}
          {/* FORMULAIRE OFFICIEL COMPLET - DEMANDE DE SALLE               */}
          {/* Visible pour l'association ET l'administration, à TOUTES les étapes */}
          {/* ============================================================ */}
          {isDemandeSalle && (
            <Card className="border-[oklch(0.25_0.05_265)]/30 overflow-hidden">
              {/* En-tête officiel */}
              <div className="bg-[oklch(0.25_0.05_265)] text-white px-6 py-4">
                <div className="text-center">
                  <div className="mb-3 flex justify-center">
                    <img src={ccdsLogo} alt="Logo CCDS" className="h-20 w-auto object-contain rounded bg-white/95 px-2 py-1" />
                  </div>
                  <p className="text-xs uppercase tracking-wider opacity-80">Communauté de Communes Des Savanes</p>
                  <h2 className="text-lg font-bold mt-1">Formulaire de Réservation d'un Local</h2>
                  <p className="text-sm opacity-80">Maison de la Jeunesse des Savanes</p>
                </div>
              </div>

              <CardContent className="p-6 space-y-6">
                {/* ---- Section 1 : Informations de l'association ---- */}
                <div>
                  <h3 className="font-semibold text-sm uppercase text-muted-foreground mb-3 flex items-center gap-2">
                    <Building2 className="h-4 w-4" />
                    Informations de l'association
                  </h3>
                  <div className="grid gap-2 text-sm">
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Nom de l'association :</span>
                      <span className="font-medium">{formData.nomAssociation || request.associationInfo?.nomAssociation || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Adresse :</span>
                      <span className="font-medium text-right max-w-[60%]">
                        {formData.adresseAssociation || 
                          (request.associationInfo ? [request.associationInfo.adresse, request.associationInfo.codePostal, request.associationInfo.ville].filter(Boolean).join(', ') : '') || '-'}
                      </span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Commune du siège :</span>
                      <span className="font-medium">{formData.communeSiege || request.associationInfo?.ville || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Représentant légal :</span>
                      <span className="font-medium">{formData.representantLegal || request.associationInfo?.nomRepresentant || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Téléphone :</span>
                      <span className="font-medium">{formData.telephoneAssociation || request.associationInfo?.telephone || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Email :</span>
                      <span className="font-medium">{formData.emailAssociation || request.associationInfo?.emailContact || '-'}</span>
                    </div>
                  </div>
                </div>

                <Separator />

                {/* ---- Section 2 : Local(aux) sollicité(s) ---- */}
                <div>
                  <h3 className="font-semibold text-sm uppercase text-muted-foreground mb-3 flex items-center gap-2">
                    <MapPin className="h-4 w-4" />
                    Local(aux) sollicité(s)
                  </h3>
                  {formData.sallesSelectionnees && (formData.sallesSelectionnees as string[]).length > 0 ? (
                    <div className="flex flex-wrap gap-2">
                      {(formData.sallesSelectionnees as string[]).map((salle: string, i: number) => (
                        <span
                          key={i}
                          className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-[oklch(0.25_0.05_265)]/10 text-[oklch(0.25_0.05_265)] text-sm font-medium"
                        >
                          <CheckCircle className="h-3.5 w-3.5" />
                          {salle}
                        </span>
                      ))}
                    </div>
                  ) : (
                    <p className="text-sm text-muted-foreground">-</p>
                  )}
                </div>

                <Separator />

                {/* ---- Section 3 : Détails de la réservation ---- */}
                <div>
                  <h3 className="font-semibold text-sm uppercase text-muted-foreground mb-3 flex items-center gap-2">
                    <CalendarDays className="h-4 w-4" />
                    Détails de la réservation
                  </h3>
                  <div className="grid gap-2 text-sm">
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Motif de la réservation :</span>
                      <span className="font-medium text-right max-w-[60%]">{formData.motifReservation || request.description || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Date de début :</span>
                      <span className="font-medium">{formatDateFr(formData.dateReservation)}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Date de fin :</span>
                      <span className="font-medium">
                        {formData.dateFinReservation && formData.dateFinReservation !== formData.dateReservation
                          ? formatDateFr(formData.dateFinReservation)
                          : formData.dateReservation
                            ? formatDateFr(formData.dateReservation)
                            : '-'}
                      </span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Organisation horaire :</span>
                      <span className="font-medium">{reservationScheduleSummary}</span>
                    </div>
                    {reservationDailySlots.length > 0 && (
                      <div className="py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground block mb-2">Détail par journée :</span>
                        <div className="space-y-2">
                          {reservationDailySlots.map((slot: any) => (
                            <div key={slot.date} className="flex justify-between gap-4 rounded-md bg-muted/40 px-3 py-2">
                              <span className="font-medium">{formatDateFr(slot.date)}</span>
                              <span>{slot.heureDebut || '?'} — {slot.heureFin || '?'}</span>
                            </div>
                          ))}
                        </div>
                      </div>
                    )}
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Nombre de participants :</span>
                      <span className="font-medium">
                        {formData.nombreParticipants ? `${formData.nombreParticipants} personnes` : '-'}
                      </span>
                    </div>
                    {isAdmin && (
                      <>
                        <div className="flex justify-between py-1.5 border-b border-dashed">
                          <span className="text-muted-foreground">Type d'usage :</span>
                          <span className="font-medium">{formData.typeUsage === 'occasionnel' ? 'Occasionnel' : 'Conventionné'}</span>
                        </div>
                        <div className="flex justify-between py-1.5 border-b border-dashed">
                          <span className="text-muted-foreground">Fréquence :</span>
                          <span className="font-medium">
                            {formData.frequence === 'demi_journee' ? 'Demi-journée' : formData.frequence === 'mensuel' ? 'Mensuel' : 'Journée'}
                          </span>
                        </div>
                      </>
                    )}
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Besoins complémentaires :</span>
                      <span className="font-medium text-right max-w-[60%]">{formData.besoinsComplementaires || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Matériel nécessaire :</span>
                      <span className="font-medium text-right max-w-[60%]">{formData.materielNecessaire || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Observations :</span>
                      <span className="font-medium text-right max-w-[60%]">{formData.observations || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Documents joints :</span>
                      <span className="font-medium">
                        {request.documentsJoints ? (() => {
                          try { return JSON.parse(request.documentsJoints).length; } catch { return 0; }
                        })() : 0} document(s)
                      </span>
                    </div>
                  </div>
                </div>

                <Separator />

                {/* ---- Section 4 : Cadre réservé à la DSU ---- */}
                {cadreDSU ? (
                  <div className="bg-[oklch(0.25_0.05_265)]/5 border border-[oklch(0.25_0.05_265)]/20 rounded-lg p-5 space-y-4">
                    <div className="flex items-center gap-2">
                      <Shield className="h-5 w-5 text-[oklch(0.25_0.05_265)]" />
                      <h3 className="font-semibold text-[oklch(0.25_0.05_265)]">
                        Cadre réservé à la Direction des Services aux Usagers (DSU)
                      </h3>
                    </div>

                    {/* Avis DSU */}
                    {cadreDSU.avisDSU && (
                      <div className="flex items-center gap-3">
                        <span className="text-sm font-medium text-muted-foreground">Avis de la DSU :</span>
                        <span className={`inline-flex items-center px-3 py-1 rounded-full text-sm font-medium border ${avisDSULabels[cadreDSU.avisDSU]?.className || 'bg-gray-100 text-gray-700'}`}>
                          {avisDSULabels[cadreDSU.avisDSU]?.label || cadreDSU.avisDSU}
                        </span>
                      </div>
                    )}

                    <div className="grid gap-2 text-sm">
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Date de réception :</span>
                        <span className="font-medium">
                          {cadreDSU.dateReception
                            ? new Date(cadreDSU.dateReception).toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })
                            : '-'}
                        </span>
                      </div>
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Date de la décision :</span>
                        <span className="font-medium">
                          {cadreDSU.dateDecision
                            ? new Date(cadreDSU.dateDecision).toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' })
                            : '-'}
                        </span>
                      </div>
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Responsable DSU :</span>
                        <span className="font-medium">{cadreDSU.responsableDSU || '-'}</span>
                      </div>
                    </div>

                    {/* Conditions particulières */}
                    {(cadreDSU.cautionRequise || cadreDSU.assuranceRequise || cadreDSU.horairesImposes || cadreDSU.conditionsParticulieres) && (
                      <>
                        <Separator />
                        <div>
                          <h4 className="text-sm font-semibold mb-3 text-[oklch(0.25_0.05_265)]">Conditions particulières</h4>
                          <div className="space-y-2 text-sm">
                            {cadreDSU.cautionRequise && (
                              <div className="flex items-center gap-2 p-2 bg-amber-50 rounded border border-amber-200">
                                <AlertTriangle className="h-4 w-4 text-amber-600 shrink-0" />
                                <span>Caution requise{cadreDSU.montantCaution ? ` : ${cadreDSU.montantCaution} €` : ''}</span>
                              </div>
                            )}
                            {cadreDSU.assuranceRequise && (
                              <div className="flex items-center gap-2 p-2 bg-blue-50 rounded border border-blue-200">
                                <Shield className="h-4 w-4 text-blue-600 shrink-0" />
                                <span>Attestation d'assurance requise</span>
                              </div>
                            )}
                            {cadreDSU.horairesImposes && (
                              <div className="flex items-center gap-2 p-2 bg-gray-50 rounded border border-gray-200">
                                <Clock className="h-4 w-4 text-gray-600 shrink-0" />
                                <span>Horaires imposés : {cadreDSU.horairesImposes}</span>
                              </div>
                            )}
                            {cadreDSU.conditionsParticulieres && (
                              <div className="p-3 bg-gray-50 rounded border border-gray-200">
                                <p className="text-muted-foreground">{cadreDSU.conditionsParticulieres}</p>
                              </div>
                            )}
                          </div>
                        </div>
                      </>
                    )}

                    {materialFinancialDecision?.financialMode && (
                      <>
                        <Separator />
                        <div className="rounded-lg border border-primary/20 bg-white/80 p-4 space-y-3">
                          <div className="flex items-center justify-between gap-3">
                            <h4 className="font-semibold">Conditions financières / convention</h4>
                            <span className={`inline-flex items-center rounded-full border px-3 py-1 text-xs font-medium ${getContractStatusBadgeClass(materialFinancialDecision.contractStatus)}`}>
                              {getContractStatusLabel(materialFinancialDecision.contractStatus)}
                            </span>
                          </div>
                          <div className="grid gap-3 md:grid-cols-2 text-sm">
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Mode financier :</span>
                              <span className="font-medium text-right max-w-[60%]">{getFinancialModeLabel(materialFinancialDecision.financialMode)}</span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Caution / dépôt :</span>
                              <span className="font-medium text-right max-w-[60%]">
                                {materialFinancialDecision.depositRequired ? formatAmount(materialFinancialDecision.depositAmountCents || 0) : 'Aucune'}
                              </span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Montant location :</span>
                              <span className="font-medium text-right max-w-[60%]">
                                {materialFinancialDecision.financialMode === 'location_payante'
                                  ? formatAmount(materialFinancialDecision.rentalAmountCents || 0)
                                  : 'Non applicable'}
                              </span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Convention générée le :</span>
                              <span className="font-medium text-right max-w-[60%]">
                                {materialFinancialDecision.contractGeneratedAt ? formatDateTime(materialFinancialDecision.contractGeneratedAt) : '-'}
                              </span>
                            </div>
                          </div>
                          {materialFinancialDecision.pricingNotes && (
                            <div className="rounded-lg border bg-muted/20 p-3">
                              <p className="text-xs uppercase tracking-wide text-muted-foreground mb-1">Clauses spécifiques</p>
                              <p className="text-sm whitespace-pre-wrap">{materialFinancialDecision.pricingNotes}</p>
                            </div>
                          )}
                          {(materialFinancialDecision.contractPdfUrl || isAdmin) && (
                            <div className="flex flex-wrap gap-3">
                              {isAdmin && request.status === 'validee' ? (
                                <Button
                                  variant="outline"
                                  size="sm"
                                  onClick={() => activeContractMutation.mutate({ id: request.id })}
                                  disabled={activeContractMutation.isPending}
                                >
                                  {activeContractMutation.isPending ? (
                                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                  ) : (
                                    <FileText className="mr-2 h-4 w-4" />
                                  )}
                                  {materialFinancialDecision.contractPdfUrl ? 'Régénérer la convention' : 'Générer la convention'}
                                </Button>
                              ) : null}
                              {materialFinancialDecision.contractPdfUrl && materialFinancialDecision.contractPdfName ? (
                                <DetailOverflowMenu label="Convention financière">
                                  <DropdownMenuItem asChild>
                                    <Link href={`/dashboard/requests/${request.id}/material-convention`}>
                                      <Download className="h-4 w-4" />
                                      Télécharger {materialFinancialDecision.contractPdfName}
                                    </Link>
                                  </DropdownMenuItem>
                                </DetailOverflowMenu>
                              ) : null}
                            </div>
                          )}
                        </div>
                      </>
                    )}

                    {isDemandeSalle && salleWorkflow && (
                      <>
                        <Separator />
                        <div className="rounded-lg border border-blue-200 bg-blue-50/70 p-4 space-y-3">
                          <div className="flex items-center justify-between gap-3">
                            <h4 className="font-semibold">Workflow devis / signature</h4>
                            <Badge variant="outline">{getSalleWorkflowQuoteStatusLabel(salleWorkflow.quoteStatus)}</Badge>
                          </div>
                          {salleWorkflowStage && (
                            <div className={`rounded-lg border px-4 py-3 ${salleWorkflowStage.className}`}>
                              <p className="text-sm font-semibold">{salleWorkflowStage.label}</p>
                              <p className="mt-1 text-sm opacity-90">{salleWorkflowStage.description}</p>
                            </div>
                          )}
                          <div className="grid gap-3 md:grid-cols-2 text-sm">
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Réponse association :</span>
                              <span className="font-medium">{getSalleWorkflowQuoteStatusLabel(salleWorkflow.quoteStatus)}</span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Signature Directrice :</span>
                              <span className="font-medium">{getSalleWorkflowDirectorStatusLabel(salleWorkflow.directorStatus)}</span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Devis envoyé le :</span>
                              <span className="font-medium">{salleWorkflow.quoteSentAt ? formatDateTime(salleWorkflow.quoteSentAt) : '-'}</span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Réponse reçue le :</span>
                              <span className="font-medium">{salleWorkflow.quoteRespondedAt ? formatDateTime(salleWorkflow.quoteRespondedAt) : '-'}</span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Transmission Directrice :</span>
                              <span className="font-medium">{salleWorkflow.directorTransmissionAt ? formatDateTime(salleWorkflow.directorTransmissionAt) : '-'}</span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Notification finale :</span>
                              <span className="font-medium">{salleWorkflow.finalNotificationSentAt ? formatDateTime(salleWorkflow.finalNotificationSentAt) : '-'}</span>
                            </div>
                          </div>
                          {materialFinancialDecision?.financialMode === "location_payante" && (
                            <div className="rounded-lg border border-violet-200 bg-violet-50/70 p-4 space-y-3">
                              <div className="flex flex-wrap items-center justify-between gap-3">
                                <div>
                                  <h5 className="font-semibold">Suivi de facturation</h5>
                                  <p className="text-sm text-muted-foreground">
                                    Le portail prépare la facture automatiquement. L’accueil met à jour ici l’état réel du règlement.
                                  </p>
                                </div>
                                <Badge
                                  variant="outline"
                                  className={salleWorkflow.paymentStatus ? sallePaymentStatusClasses[salleWorkflow.paymentStatus] : "bg-amber-100 text-amber-800 border-amber-200"}
                                >
                                  {salleWorkflow.paymentStatus ? SALLE_WORKFLOW_PAYMENT_STATUS_LABELS[salleWorkflow.paymentStatus] : "En attente de paiement"}
                                </Badge>
                              </div>
                              {sallePaymentIsLate && (
                                <div className="rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-800">
                                  Le paiement n’est pas encore validé alors que la date d’utilisation approche ou est dépassée.
                                </div>
                              )}
                              <div className="grid gap-3 md:grid-cols-2 text-sm">
                                <div className="flex justify-between py-1.5 border-b border-dashed">
                                  <span className="text-muted-foreground">Montant attendu :</span>
                                  <span className="font-medium">{formatAmount(salleWorkflow.pricing?.totalAmountCents || materialFinancialDecision.rentalAmountCents || 0)}</span>
                                </div>
                                <div className="flex justify-between py-1.5 border-b border-dashed">
                                  <span className="text-muted-foreground">Paiement attendu avant :</span>
                                  <span className="font-medium">{salleWorkflow.paymentDueDate ? formatDateFr(salleWorkflow.paymentDueDate) : "-"}</span>
                                </div>
                                <div className="flex justify-between py-1.5 border-b border-dashed">
                                  <span className="text-muted-foreground">Montant reçu :</span>
                                  <span className="font-medium">{salleWorkflow.amountReceivedCents ? formatAmount(salleWorkflow.amountReceivedCents) : "-"}</span>
                                </div>
                                <div className="flex justify-between py-1.5 border-b border-dashed">
                                  <span className="text-muted-foreground">Paiement reçu le :</span>
                                  <span className="font-medium">{salleWorkflow.paymentReceivedAt ? formatDateTime(salleWorkflow.paymentReceivedAt) : "-"}</span>
                                </div>
                                <div className="flex justify-between py-1.5 border-b border-dashed">
                                  <span className="text-muted-foreground">Paiement validé le :</span>
                                  <span className="font-medium">{salleWorkflow.paymentValidatedAt ? formatDateTime(salleWorkflow.paymentValidatedAt) : "-"}</span>
                                </div>
                                <div className="flex justify-between py-1.5 border-b border-dashed">
                                  <span className="text-muted-foreground">Référence :</span>
                                  <span className="font-medium text-right max-w-[60%]">{salleWorkflow.paymentReference || "-"}</span>
                                </div>
                              </div>
                              {salleWorkflow.paymentNotes && (
                                <div className="rounded-lg border bg-white/80 p-3 text-sm">
                                  <p className="text-xs uppercase tracking-wide text-muted-foreground mb-1">Notes facturation</p>
                                  <p className="whitespace-pre-wrap">{salleWorkflow.paymentNotes}</p>
                                </div>
                              )}
                              {canUpdateSallePaymentTracking ? (
                                <div className="grid gap-3 md:grid-cols-2">
                                  <div className="space-y-2">
                                    <Label htmlFor="sallePaymentStatus">État du paiement</Label>
                                    <Select
                                      value={sallePaymentForm.paymentStatus}
                                      onValueChange={(value: SalleWorkflowPaymentStatus) => setSallePaymentForm((prev) => ({ ...prev, paymentStatus: value }))}
                                    >
                                      <SelectTrigger id="sallePaymentStatus">
                                        <SelectValue placeholder="Choisir l’état du paiement" />
                                      </SelectTrigger>
                                      <SelectContent>
                                        {Object.entries(SALLE_WORKFLOW_PAYMENT_STATUS_LABELS).map(([value, label]) => (
                                          <SelectItem key={value} value={value}>
                                            {label}
                                          </SelectItem>
                                        ))}
                                      </SelectContent>
                                    </Select>
                                  </div>
                                  <div className="space-y-2">
                                    <Label htmlFor="sallePaymentAmount">Montant reçu (€)</Label>
                                    <Input
                                      id="sallePaymentAmount"
                                      type="number"
                                      min={0}
                                      step="0.01"
                                      value={sallePaymentForm.amountReceivedEuros}
                                      onChange={(e) => setSallePaymentForm((prev) => ({ ...prev, amountReceivedEuros: e.target.value }))}
                                      placeholder="0.00"
                                    />
                                  </div>
                                  <div className="space-y-2">
                                    <Label htmlFor="sallePaymentReceivedAt">Date de réception</Label>
                                    <Input
                                      id="sallePaymentReceivedAt"
                                      type="date"
                                      value={sallePaymentForm.paymentReceivedAt}
                                      onChange={(e) => setSallePaymentForm((prev) => ({ ...prev, paymentReceivedAt: e.target.value }))}
                                    />
                                  </div>
                                  <div className="space-y-2">
                                    <Label htmlFor="sallePaymentReference">Référence / pièce</Label>
                                    <Input
                                      id="sallePaymentReference"
                                      value={sallePaymentForm.paymentReference}
                                      onChange={(e) => setSallePaymentForm((prev) => ({ ...prev, paymentReference: e.target.value }))}
                                      placeholder="Ex. Virement, chèque, quittance..."
                                    />
                                  </div>
                                  <div className="space-y-2 md:col-span-2">
                                    <Label htmlFor="sallePaymentNotes">Observation du service facturation</Label>
                                    <Textarea
                                      id="sallePaymentNotes"
                                      value={sallePaymentForm.paymentNotes}
                                      onChange={(e) => setSallePaymentForm((prev) => ({ ...prev, paymentNotes: e.target.value }))}
                                      rows={3}
                                      placeholder="Ex. paiement reçu partiellement, justificatif en attente, accord interne..."
                                    />
                                  </div>
                                  <div className="md:col-span-2">
                                    <Button
                                      variant="outline"
                                      onClick={handleSaveSallePaymentTracking}
                                      disabled={updateSallePaymentTrackingMutation.isPending}
                                    >
                                      {updateSallePaymentTrackingMutation.isPending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
                                      Enregistrer le suivi de facturation
                                    </Button>
                                  </div>
                                </div>
                              ) : (
                                <p className="text-sm text-muted-foreground">
                                  Lecture seule pour ce profil. La Directrice peut vérifier ici si le paiement est bien reçu avant l’utilisation des lieux.
                                </p>
                              )}
                            </div>
                          )}
                          {salleWorkflow.directorReturnComment && (
                            <div className="rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm text-amber-950">
                              <p className="font-semibold">Retour de la Direction</p>
                              <p className="mt-1">{salleWorkflow.directorReturnComment}</p>
                              {salleWorkflow.directorReturnedAt && (
                                <p className="mt-2 text-xs text-amber-800">
                                  Revenu à l’accueil le {formatDateTime(salleWorkflow.directorReturnedAt)}
                                </p>
                              )}
                            </div>
                          )}
                          {salleWorkflow.directorStatus === "signee" && (
                            <div className="rounded-lg border border-emerald-200 bg-emerald-50 p-4 space-y-3">
                              <div className="flex flex-wrap items-center gap-2">
                                <Badge className="border border-emerald-300 bg-emerald-100 text-emerald-900">
                                  Documents prêts après signature
                                </Badge>
                                {salleWorkflow.invoicePdfUrl ? (
                                  <Badge className="border border-blue-300 bg-blue-100 text-blue-900">
                                    Facture générée
                                  </Badge>
                                ) : null}
                                <Badge className="border border-violet-300 bg-violet-100 text-violet-900">
                                  Prêt à envoyer à l’association
                                </Badge>
                              </div>
                              <div className="grid gap-3 md:grid-cols-3 text-sm">
                                <div className="rounded-lg border bg-white px-3 py-3">
                                  <p className="text-[11px] uppercase tracking-wide text-muted-foreground">
                                    Documents prêts
                                  </p>
                                  <p className="mt-1 font-medium">
                                    {[
                                      salleWorkflow.signedQuotePdfUrl,
                                      salleWorkflow.signedDecisionPdfUrl,
                                      salleWorkflow.signedRequestPdfUrl,
                                      salleWorkflow.invoicePdfUrl,
                                    ].filter(Boolean).length} document(s)
                                  </p>
                                </div>
                                <div className="rounded-lg border bg-white px-3 py-3">
                                  <p className="text-[11px] uppercase tracking-wide text-muted-foreground">
                                    Facture
                                  </p>
                                  <p className="mt-1 font-medium">
                                    {salleWorkflow.invoicePdfUrl ? "Déjà générée" : "Non requise ou non générée"}
                                  </p>
                                </div>
                                <div className="rounded-lg border bg-white px-3 py-3">
                                  <p className="text-[11px] uppercase tracking-wide text-muted-foreground">
                                    Prochaine action
                                  </p>
                                  <p className="mt-1 font-medium">Envoyer confirmation finale à l’association</p>
                                </div>
                              </div>
                            </div>
                          )}
                          {(salleWorkflow.quotePdfUrl
                            || salleWorkflow.administrativeDecisionPdfUrl
                            || salleWorkflow.signedQuotePdfUrl
                            || salleWorkflow.signedDecisionPdfUrl
                            || salleWorkflow.signedRequestPdfUrl
                            || salleWorkflow.invoicePdfUrl) && (
                            <div className="space-y-4">
                              <div className="space-y-1">
                                <p className="text-sm font-medium">Les documents générés</p>
                                <p className="text-sm text-muted-foreground">
                                  Gardez l’action principale sous la main et retrouvez les téléchargements complémentaires dans le menu secondaire.
                                </p>
                              </div>
                              <div className="grid gap-3 sm:grid-cols-2">
                                {salleWorkflow.quotePdfUrl && salleWorkflow.quotePdfName && (
                                  <div className="rounded-xl border border-slate-200 bg-white px-4 py-4 shadow-[0_12px_28px_-24px_rgba(15,23,42,0.22)]">
                                    <div className="space-y-1">
                                      <p className="text-sm font-semibold text-slate-950">Devis</p>
                                      <p className="text-sm text-muted-foreground break-words">
                                        {salleWorkflow.quotePdfName}
                                      </p>
                                    </div>
                                    <div className="mt-4 flex items-center gap-2">
                                      <Link
                                        className="min-w-0 flex-1"
                                        href={`/dashboard/requests/${request.id}/salle-document/devis?returnTo=${encodeURIComponent(`/dashboard/requests/${request.id}`)}`}
                                      >
                                        <Button variant="outline" size="sm" className="h-10 w-full justify-start sm:justify-center">
                                          <ExternalLink className="mr-2 h-4 w-4" />
                                          Voir le devis
                                        </Button>
                                      </Link>
                                      <DetailOverflowMenu label="Actions du devis">
                                        <DropdownMenuItem asChild>
                                          <Link href={`/dashboard/requests/${request.id}/salle-document/devis?returnTo=${encodeURIComponent(`/dashboard/requests/${request.id}`)}`}>
                                            <Download className="h-4 w-4" />
                                            Télécharger le devis
                                          </Link>
                                        </DropdownMenuItem>
                                        {salleWorkflow.signedQuotePdfUrl && salleWorkflow.signedQuotePdfName ? (
                                          <DropdownMenuItem asChild>
                                            <a href={salleWorkflow.signedQuotePdfUrl} target="_blank" rel="noopener noreferrer">
                                              <ExternalLink className="h-4 w-4" />
                                              Voir le devis signé
                                            </a>
                                          </DropdownMenuItem>
                                        ) : null}
                                      </DetailOverflowMenu>
                                    </div>
                                  </div>
                                )}
                                {salleWorkflow.administrativeDecisionPdfUrl && (
                                  <div className="rounded-xl border border-slate-200 bg-white px-4 py-4 shadow-[0_12px_28px_-24px_rgba(15,23,42,0.22)]">
                                    <div className="space-y-1">
                                      <p className="text-sm font-semibold text-slate-950">Décision administrative</p>
                                      <p className="text-sm text-muted-foreground break-words">
                                        {salleWorkflow.administrativeDecisionPdfName || "Document généré"}
                                      </p>
                                    </div>
                                    <div className="mt-4 flex items-center gap-2">
                                      <Link
                                        className="min-w-0 flex-1"
                                        href={`/dashboard/requests/${request.id}/salle-document/decision?returnTo=${encodeURIComponent(`/dashboard/requests/${request.id}`)}`}
                                      >
                                        <Button variant="outline" size="sm" className="h-10 w-full justify-start sm:justify-center">
                                          <ExternalLink className="mr-2 h-4 w-4" />
                                          Voir la décision
                                        </Button>
                                      </Link>
                                      <DetailOverflowMenu label="Actions de la décision">
                                        <DropdownMenuItem asChild>
                                          <Link href={`/dashboard/requests/${request.id}/salle-document/decision?returnTo=${encodeURIComponent(`/dashboard/requests/${request.id}`)}`}>
                                            <Download className="h-4 w-4" />
                                            Télécharger la décision
                                          </Link>
                                        </DropdownMenuItem>
                                        {salleWorkflow.signedDecisionPdfUrl && salleWorkflow.signedDecisionPdfName ? (
                                          <DropdownMenuItem asChild>
                                            <a href={salleWorkflow.signedDecisionPdfUrl} target="_blank" rel="noopener noreferrer">
                                              <ExternalLink className="h-4 w-4" />
                                              Voir la décision signée
                                            </a>
                                          </DropdownMenuItem>
                                        ) : null}
                                      </DetailOverflowMenu>
                                    </div>
                                  </div>
                                )}
                                {(salleWorkflow.signedRequestPdfUrl && salleWorkflow.signedRequestPdfName) || (salleWorkflow.invoicePdfUrl && salleWorkflow.invoicePdfName) ? (
                                  <div className="rounded-xl border border-dashed border-slate-200 bg-slate-50/80 px-4 py-4 sm:col-span-2">
                                    <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                                      <div className="space-y-1">
                                        <p className="text-sm font-semibold text-slate-950">Autres pièces finales</p>
                                        <p className="text-sm text-muted-foreground">
                                          Formulaire signé, facture et pièces de clôture restent accessibles ici.
                                        </p>
                                      </div>
                                      <DetailOverflowMenu label="Autres documents générés">
                                        {salleWorkflow.signedRequestPdfUrl && salleWorkflow.signedRequestPdfName ? (
                                          <DropdownMenuItem asChild>
                                            <a href={salleWorkflow.signedRequestPdfUrl} target="_blank" rel="noopener noreferrer">
                                              <ExternalLink className="h-4 w-4" />
                                              Voir le formulaire signé
                                            </a>
                                          </DropdownMenuItem>
                                        ) : null}
                                        {salleWorkflow.invoicePdfUrl && salleWorkflow.invoicePdfName ? (
                                          <DropdownMenuItem asChild>
                                            <a href={salleWorkflow.invoicePdfUrl} target="_blank" rel="noopener noreferrer">
                                              <ExternalLink className="h-4 w-4" />
                                              Voir la facture
                                            </a>
                                          </DropdownMenuItem>
                                        ) : null}
                                      </DetailOverflowMenu>
                                    </div>
                                  </div>
                                ) : null}
                              </div>
                            </div>
                          )}
                          {canRespondToSalleQuote && (
                            <div className="rounded-lg border border-primary/20 bg-white p-4 space-y-3">
                              <div>
                                <p className="text-sm font-semibold">Votre réponse est attendue</p>
                                <p className="mt-1 text-sm text-muted-foreground">
                                  Vous ne pouvez plus modifier cette demande. Vous pouvez maintenant valider ou refuser la proposition transmise par l’hôtesse.
                                </p>
                              </div>
                              <div className="flex flex-wrap gap-3">
                                <Button
                                  onClick={() => respondSalleQuoteMutation.mutate({ id: request.id, decision: "accepte" })}
                                  disabled={respondSalleQuoteMutation.isPending}
                                >
                                  {respondSalleQuoteMutation.isPending ? (
                                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                  ) : (
                                    <CheckCircle className="mr-2 h-4 w-4" />
                                  )}
                                  J’accepte le devis
                                </Button>
                                <Button
                                  variant="destructive"
                                  onClick={() => respondSalleQuoteMutation.mutate({ id: request.id, decision: "refuse" })}
                                  disabled={respondSalleQuoteMutation.isPending}
                                >
                                  {respondSalleQuoteMutation.isPending ? (
                                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                  ) : (
                                    <XCircle className="mr-2 h-4 w-4" />
                                  )}
                                  Je refuse le devis
                                </Button>
                              </div>
                            </div>
                          )}
                        </div>
                      </>
                    )}

                    {/* Observations DSU */}
                    {cadreDSU.observationsDSU && (
                      <>
                        <Separator />
                        <div>
                          <h4 className="text-sm font-semibold mb-2 text-[oklch(0.25_0.05_265)]">Observations de la DSU</h4>
                          <p className="text-sm text-muted-foreground bg-gray-50 p-3 rounded border">{cadreDSU.observationsDSU}</p>
                        </div>
                      </>
                    )}
                  </div>
                ) : (
                  /* Cadre DSU non rempli - placeholder */
                  <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
                    <div className="flex items-start gap-3">
                      <Shield className="h-5 w-5 text-blue-500 mt-0.5" />
                      <div className="flex-1">
                        <h3 className="font-semibold text-sm text-blue-800 mb-1">
                          Cadre réservé à la Direction des Services aux Usagers (DSU)
                        </h3>
                        <p className="text-xs text-blue-600">
                          Ce cadre sera complété par l'administration lors du traitement de votre demande.
                        </p>
                        <div className="grid gap-2 mt-3 text-sm text-blue-700">
                          <div className="flex items-center gap-2">
                            <span>Date de réception : </span>
                            <span className="border-b border-dashed border-blue-300 flex-1" />
                          </div>
                          <div className="flex items-center gap-2">
                            <span>Avis : </span>
                            <span className="border-b border-dashed border-blue-300 flex-1" />
                          </div>
                          <div className="flex items-center gap-2">
                            <span>Décision : </span>
                            <span className="border-b border-dashed border-blue-300 flex-1" />
                          </div>
                        </div>
                        {isAdmin && canProcess && (
                          <Button 
                            variant="outline" 
                            size="sm" 
                            className="mt-3 border-blue-300 text-blue-700 hover:bg-blue-100"
                            onClick={openProcessDialog}
                          >
                            <Settings className="mr-2 h-3.5 w-3.5" />
                            Remplir le cadre DSU
                          </Button>
                        )}
                      </div>
                    </div>
                  </div>
                )}
              </CardContent>
            </Card>
          )}

          {/* ============================================================ */}
          {/* DÉTAILS POUR LES DEMANDES NON-SALLE                          */}
          {/* ============================================================ */}
          {isDemandeMaterielEvenementiel && (
            <Card className="border-[#f0c94b]/70 overflow-hidden">
              <CardContent className="p-0">
                <div className="border-t-4 border-[#f0c94b]" />
                <div className="px-6 py-8 space-y-6">
                  <div className="text-center space-y-2">
                    <div className="flex justify-center">
                      <img src={ccdsLogo} alt="Logo CCDS" className="h-24 w-auto object-contain" />
                    </div>
                    <p className="text-xs uppercase tracking-[0.2em] text-muted-foreground">
                      Communauté de Communes Des Savanes
                    </p>
                    <div className="inline-flex items-center gap-3 rounded-md border border-[#f0c94b] bg-sky-100 px-6 py-3">
                      <ClipboardList className="h-5 w-5 text-primary" />
                      <h2 className="text-lg font-bold uppercase text-[oklch(0.25_0.05_265)]">
                        Demande du matériel événementiel
                      </h2>
                    </div>
                  </div>

                  <div className="rounded-sm border border-[#e6b48c] p-5 space-y-5">
                    <div className="grid gap-3 md:grid-cols-2 text-sm">
                      <DetailLine label="Commune" value={formData.commune} />
                      <DetailLine label="Direction" value={formData.direction} />
                      <DetailLine label="Service" value={formData.service} />
                      <DetailLine label="Nom et prénom du demandeur" value={formData.demandeurNomPrenom} />
                    </div>

                    <Separator />

                    <div>
                      <h3 className="font-semibold mb-3">Matériel demandé</h3>
                      <div className="grid gap-3 md:grid-cols-2">
                        {materialEventItems.map(item => {
                          const checked = Boolean(formData.materielsDemandes?.[item.key]);
                          const quantity = formData.quantitesDemandees?.[item.key];
                          if (!checked) return null;
                          return (
                            <div key={item.key} className="rounded-lg border p-3 bg-muted/30">
                              <p className="font-medium">{item.label}</p>
                              <p className="text-sm text-muted-foreground mt-1">Quantité demandée : {quantity || "-"}</p>
                              {item.key === "autres" && formData.autreMaterielPrecisions && (
                                <p className="text-sm mt-2">{formData.autreMaterielPrecisions}</p>
                              )}
                            </div>
                          );
                        })}
                      </div>
                    </div>

                    <div className="grid gap-3 md:grid-cols-2 text-sm">
                      <DetailLine label="Date de la demande" value={formatDateFr(formData.dateDemande)} />
                      <DetailLine label="Début de la manifestation" value={formatDateFr(formData.dateDebutManifestation || formData.dateManifestation)} />
                      <DetailLine label="Fin de la manifestation" value={formatDateFr(formData.dateFinManifestation || formData.dateManifestation)} />
                    </div>

                    <div>
                      <p className="text-sm font-medium mb-2">Motif de la demande</p>
                      <p className="text-sm text-muted-foreground bg-muted/30 rounded-lg border p-3 whitespace-pre-wrap">
                        {formData.motifDemande || request.description || "-"}
                      </p>
                    </div>

                    <div className="grid gap-3 md:grid-cols-2 text-sm">
                      <DetailLine label="Date de prise en charge du matériel" value={formatDateFr(formData.datePriseEnCharge)} />
                      <DetailLine label="Date de restitution" value={formatDateFr(formData.dateRestitution)} />
                    </div>
                  </div>

                  {cadreDSU ? (
                    <div className="rounded-sm border border-[#e0c46b] bg-sky-100/70 p-5 space-y-4">
                      <h3 className="text-center text-xl font-semibold underline underline-offset-4">
                        Cadre réservé à la DSU
                      </h3>
                      <div className="grid gap-3 md:grid-cols-3 text-sm">
                        <DetailLine label="Date de réception" value={formatDateFr(cadreDSU.dateReception)} />
                        <DetailLine label="Date de décision" value={formatDateFr(cadreDSU.dateDecision)} />
                        <DetailLine label="Responsable DSU" value={cadreDSU.responsableDSU} />
                      </div>
                      <div className="grid gap-3 md:grid-cols-2">
                        {materialEventItems.map(item => {
                          const requested = formData.quantitesDemandees?.[item.key];
                          const checked = Boolean(cadreDSU.materielEvent?.itemsAccordes?.[item.key]);
                          const quantity = cadreDSU.materielEvent?.quantitesAccordees?.[item.key];
                          const extra = item.key === "autres" ? cadreDSU.materielEvent?.autresPrecisions : "";
                          return (
                            <div key={item.key} className="rounded-lg border bg-white/70 p-3">
                              <p className="font-medium">{item.label}</p>
                              <p className="text-sm text-slate-700 mt-1">
                                Demandé : <span className="font-semibold">{requested || "-"}</span>
                              </p>
                              <p className="text-sm text-muted-foreground mt-1">
                                {checked ? `Accordé${quantity ? ` - Quantité : ${quantity}` : ""}` : request.status === "refusee" ? "Refusé" : "Non renseigné"}
                              </p>
                              {extra ? <p className="text-sm mt-2">{extra}</p> : null}
                            </div>
                          );
                        })}
                      </div>
                      {materialFinancialDecision?.financialMode && (
                        <div className="rounded-lg border border-primary/20 bg-white/80 p-4 space-y-3">
                          <div className="flex items-center justify-between gap-3">
                            <h4 className="font-semibold">Conditions financières / convention</h4>
                            <span className={`inline-flex items-center rounded-full border px-3 py-1 text-xs font-medium ${getContractStatusBadgeClass(materialFinancialDecision.contractStatus)}`}>
                              {getContractStatusLabel(materialFinancialDecision.contractStatus)}
                            </span>
                          </div>
                          <div className="grid gap-3 md:grid-cols-2 text-sm">
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Mode financier :</span>
                              <span className="font-medium text-right max-w-[60%]">{getFinancialModeLabel(materialFinancialDecision.financialMode)}</span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Caution / dépôt :</span>
                              <span className="font-medium text-right max-w-[60%]">
                                {materialFinancialDecision.depositRequired ? formatAmount(materialFinancialDecision.depositAmountCents || 0) : 'Aucune'}
                              </span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Montant location :</span>
                              <span className="font-medium text-right max-w-[60%]">
                                {materialFinancialDecision.financialMode === 'location_payante'
                                  ? formatAmount(materialFinancialDecision.rentalAmountCents || 0)
                                  : 'Non applicable'}
                              </span>
                            </div>
                            <div className="flex justify-between py-1.5 border-b border-dashed">
                              <span className="text-muted-foreground">Convention générée le :</span>
                              <span className="font-medium text-right max-w-[60%]">
                                {materialFinancialDecision.contractGeneratedAt ? formatDateTime(materialFinancialDecision.contractGeneratedAt) : '-'}
                              </span>
                            </div>
                          </div>
                          {materialFinancialDecision.pricingNotes && (
                            <div className="rounded-lg border bg-muted/20 p-3">
                              <p className="text-xs uppercase tracking-wide text-muted-foreground mb-1">Clauses spécifiques</p>
                              <p className="text-sm whitespace-pre-wrap">{materialFinancialDecision.pricingNotes}</p>
                            </div>
                          )}
                          {(materialFinancialDecision.contractPdfUrl || isAdmin) && (
                            <div className="flex flex-wrap gap-3">
                              {materialFinancialDecision.contractPdfUrl && materialFinancialDecision.contractPdfName ? (
                                <Link href={`/dashboard/requests/${request.id}/material-convention`}>
                                  <Button variant="outline" size="sm">
                                    <Download className="mr-2 h-4 w-4" />
                                    Télécharger {materialFinancialDecision.contractPdfName}
                                  </Button>
                                </Link>
                              ) : null}
                              {isAdmin && request.status === 'validee' && (
                                <Button
                                  variant="outline"
                                  size="sm"
                                  onClick={() => activeContractMutation.mutate({ id: request.id })}
                                  disabled={activeContractMutation.isPending}
                                >
                                  {activeContractMutation.isPending ? (
                                    <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                  ) : (
                                    <FileText className="mr-2 h-4 w-4" />
                                  )}
                                  {materialFinancialDecision.contractPdfUrl ? 'Régénérer la convention' : 'Générer la convention'}
                                </Button>
                              )}
                            </div>
                          )}
                        </div>
                      )}
                      {cadreDSU.observationsDSU && (
                        <div>
                          <p className="text-sm font-medium mb-2">Observations de la DSU</p>
                          <p className="text-sm text-muted-foreground bg-white/70 rounded-lg border p-3 whitespace-pre-wrap">{cadreDSU.observationsDSU}</p>
                        </div>
                      )}
                    </div>
                  ) : (
                    <div className="rounded-sm border border-[#e0c46b] bg-sky-100/70 p-5">
                      <h3 className="text-center text-xl font-semibold underline underline-offset-4 mb-3">
                        Cadre réservé à la DSU
                      </h3>
                      <p className="text-sm text-muted-foreground text-center">
                        Cette partie sera complétée uniquement par l'administration lors du traitement de la demande.
                      </p>
                    </div>
                  )}
                </div>
              </CardContent>
            </Card>
          )}

          {!isDemandeSalle && !isDemandeMaterielEvenementiel && (
            <>
              <Card>
                <CardHeader>
                  <CardTitle className="flex items-center gap-2">
                    <FileText className="h-5 w-5 text-primary" />
                    Détails de la demande
                  </CardTitle>
                </CardHeader>
                <CardContent className="space-y-4">
                  <div className="grid gap-2 text-sm">
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Type de demande :</span>
                      <span className="font-medium">{requestTypeLabels[request.type] || request.type}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Description :</span>
                      <span className="font-medium text-right max-w-[60%]">{request.description || '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Montant demandé :</span>
                      <span className="font-medium">{request.montantDemande ? formatAmount(request.montantDemande) : '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Montant accordé :</span>
                      <span className={`font-medium ${request.montantAccorde ? 'text-green-600' : ''}`}>
                        {request.montantAccorde ? formatAmount(request.montantAccorde) : '-'}
                      </span>
                    </div>
                    {formData.objetProjet && (
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Objet du projet :</span>
                        <span className="font-medium text-right max-w-[60%]">{formData.objetProjet}</span>
                      </div>
                    )}
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Date de début :</span>
                      <span className="font-medium">{formData.dateDebut ? formatDateFr(formData.dateDebut) : '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Date de fin :</span>
                      <span className="font-medium">{formData.dateFin ? formatDateFr(formData.dateFin) : '-'}</span>
                    </div>
                    {formData.publicVise && (
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Public visé :</span>
                        <span className="font-medium text-right max-w-[60%]">{formData.publicVise}</span>
                      </div>
                    )}
                    {formData.lieuRealisation && (
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Lieu de réalisation :</span>
                        <span className="font-medium text-right max-w-[60%]">{formData.lieuRealisation}</span>
                      </div>
                    )}
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Date de soumission :</span>
                      <span className="font-medium">{request.dateSubmission ? formatDateTime(request.dateSubmission) : '-'}</span>
                    </div>
                    <div className="flex justify-between py-1.5 border-b border-dashed">
                      <span className="text-muted-foreground">Date de traitement :</span>
                      <span className="font-medium">{request.dateTraitement ? formatDateTime(request.dateTraitement) : '-'}</span>
                    </div>
                  </div>
                </CardContent>
              </Card>

              {/* Association info - from backend data */}
              {request.associationInfo && (
                <Card className="bg-muted/50">
                  <CardHeader>
                    <CardTitle className="text-base flex items-center gap-2">
                      <Building2 className="h-5 w-5" />
                      Informations de l'association
                    </CardTitle>
                  </CardHeader>
                  <CardContent>
                    <div className="grid gap-2 text-sm">
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Nom :</span>
                        <span className="font-medium">{request.associationInfo.nomAssociation || '-'}</span>
                      </div>
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">N° SIRET :</span>
                        <span className="font-medium">{request.associationInfo.siret || '-'}</span>
                      </div>
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Adresse :</span>
                        <span className="font-medium text-right max-w-[60%]">
                          {[request.associationInfo.adresse, request.associationInfo.codePostal, request.associationInfo.ville].filter(Boolean).join(', ') || '-'}
                        </span>
                      </div>
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Représentant légal :</span>
                        <span className="font-medium">{request.associationInfo.nomRepresentant || '-'}</span>
                      </div>
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Téléphone :</span>
                        <span className="font-medium">{request.associationInfo.telephone || '-'}</span>
                      </div>
                      <div className="flex justify-between py-1.5 border-b border-dashed">
                        <span className="text-muted-foreground">Email :</span>
                        <span className="font-medium">{request.associationInfo.emailContact || '-'}</span>
                      </div>
                      {request.associationInfo.dateCreation && (
                        <div className="flex justify-between py-1.5 border-b border-dashed">
                          <span className="text-muted-foreground">Date de création :</span>
                          <span className="font-medium">{formatDateFr(request.associationInfo.dateCreation as any)}</span>
                        </div>
                      )}
                      {request.associationInfo.objetAssociation && (
                        <div className="flex justify-between py-1.5 border-b border-dashed">
                          <span className="text-muted-foreground">Objet :</span>
                          <span className="font-medium text-right max-w-[60%]">{request.associationInfo.objetAssociation}</span>
                        </div>
                      )}
                    </div>
                  </CardContent>
                </Card>
              )}
            </>
          )}

          {/* ============================================================ */}
          {/* DOCUMENTS JOINTS - Pour tous les types de demandes           */}
          {/* ============================================================ */}
          {request.attachedDocuments && request.attachedDocuments.length > 0 && (
            <Card>
              <CardHeader>
                <CardTitle className="text-base flex items-center gap-2">
                  <FileText className="h-5 w-5 text-primary" />
                  Documents joints ({request.attachedDocuments.length})
                </CardTitle>
              </CardHeader>
              <CardContent>
                <div className="space-y-2">
                  {request.attachedDocuments.map((doc: any) => (
                    <DocumentRow key={doc.id} doc={doc} />
                  ))}
                </div>
              </CardContent>
            </Card>
          )}

          {/* Timeline */}
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <Calendar className="h-5 w-5 text-primary" />
                Historique
              </CardTitle>
            </CardHeader>
            <CardContent>
              <div className="space-y-4">
                <div className="flex items-start gap-4">
                  <div className="w-2 h-2 rounded-full bg-primary mt-2" />
                  <div>
                    <p className="font-medium">Demande créée</p>
                    <p className="text-sm text-muted-foreground">{formatDateTime(request.createdAt)}</p>
                  </div>
                </div>
                {request.dateSubmission && (
                  <div className="flex items-start gap-4">
                    <div className="w-2 h-2 rounded-full bg-blue-500 mt-2" />
                    <div>
                      <p className="font-medium">Demande soumise</p>
                      <p className="text-sm text-muted-foreground">{formatDateTime(request.dateSubmission)}</p>
                    </div>
                  </div>
                )}
                {request.dateTraitement && (
                  <div className="flex items-start gap-4">
                    <div className={`w-2 h-2 rounded-full mt-2 ${request.status === 'validee' ? 'bg-green-500' : request.status === 'refusee' ? 'bg-red-500' : 'bg-yellow-500'}`} />
                    <div>
                      <p className="font-medium">
                        {request.status === 'validee' ? 'Demande validée' : request.status === 'refusee' ? 'Demande refusée' : 'Demande traitée'}
                      </p>
                      <p className="text-sm text-muted-foreground">{formatDateTime(request.dateTraitement)}</p>
                    </div>
                  </div>
                )}
              </div>
            </CardContent>
          </Card>
        </div>
      </main>

      <Dialog
        open={showSalleFinalDialog}
        onOpenChange={(open) => {
          setShowSalleFinalDialog(open);
          if (!open) {
            setSalleFinalPreview(null);
            setSalleFinalDocumentPreview(null);
          }
        }}
      >
        <DialogContent className="max-w-2xl h-[90vh] max-h-[90vh] overflow-hidden p-0 flex flex-col">
          <DialogHeader className="border-b px-6 py-5">
            <DialogTitle>Confirmation finale à l’association</DialogTitle>
            <DialogDescription>
              L’hôtesse d’accueil vérifie ici le récapitulatif, la facture et les pièces jointes avant l’envoi définitif.
            </DialogDescription>
          </DialogHeader>
          {salleFinalPreview ? (
            <div className="min-h-0 flex-1 overflow-y-auto px-6 py-5">
              {salleFinalDocumentPreview ? (
                <div className="space-y-4">
                  <div className="flex flex-wrap items-center justify-between gap-3">
                    <div>
                      <p className="text-sm font-semibold">{salleFinalDocumentPreview.title}</p>
                      <p className="text-xs text-muted-foreground">
                        Consulte le document puis reviens au récapitulatif pour finaliser l’envoi.
                      </p>
                    </div>
                    <div className="flex flex-wrap gap-2">
                      <Button
                        variant="outline"
                        onClick={() => setSalleFinalDocumentPreview(null)}
                      >
                        <ArrowLeft className="mr-2 h-4 w-4" />
                        Retour au récapitulatif
                      </Button>
                      <a href={salleFinalDocumentPreview.url} target="_blank" rel="noopener noreferrer">
                        <Button variant="outline">
                          <ExternalLink className="mr-2 h-4 w-4" />
                          Ouvrir dans un nouvel onglet
                        </Button>
                      </a>
                    </div>
                  </div>
                  <div className="rounded-lg border bg-white overflow-hidden">
                    <iframe
                      src={salleFinalDocumentPreview.url}
                      title={salleFinalDocumentPreview.title}
                      className="h-[60vh] w-full bg-white"
                    />
                  </div>
                </div>
              ) : (
                <div className="space-y-5">
                  <div className="rounded-lg border bg-muted/40 p-4 text-sm">
                    <div className="grid gap-2 md:grid-cols-2">
                      <p><span className="text-muted-foreground">Association :</span> <span className="font-medium">{salleFinalPreview.associationName}</span></p>
                      <p><span className="text-muted-foreground">Période :</span> <span className="font-medium">{salleFinalPreview.datesLabel}</span></p>
                      <p><span className="text-muted-foreground">Montant :</span> <span className="font-medium">{new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR" }).format(salleFinalPreview.pricingTotalCents / 100)}</span></p>
                      <p><span className="text-muted-foreground">Facture générée le :</span> <span className="font-medium">{salleFinalPreview.invoiceGeneratedAt ? formatDateTime(salleFinalPreview.invoiceGeneratedAt) : "-"}</span></p>
                    </div>
                  </div>

                  <div className="space-y-3">
                    <p className="text-sm font-semibold">Pièces qui partiront avec le message final</p>
                    <div className="flex flex-wrap gap-2">
                      {salleFinalPreview.quotePdfUrl && (
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => setSalleFinalDocumentPreview({
                            title: "Devis signé",
                            url: salleFinalPreview.quotePdfUrl,
                          })}
                        >
                          <ExternalLink className="mr-2 h-4 w-4" />
                          Devis signé
                        </Button>
                      )}
                      {salleFinalPreview.decisionPdfUrl && (
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => setSalleFinalDocumentPreview({
                            title: "Décision signée",
                            url: salleFinalPreview.decisionPdfUrl,
                          })}
                        >
                          <ExternalLink className="mr-2 h-4 w-4" />
                          Décision signée
                        </Button>
                      )}
                      {salleFinalPreview.requestPdfUrl && (
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => setSalleFinalDocumentPreview({
                            title: "Formulaire signé",
                            url: salleFinalPreview.requestPdfUrl,
                          })}
                        >
                          <ExternalLink className="mr-2 h-4 w-4" />
                          Formulaire signé
                        </Button>
                      )}
                      {salleFinalPreview.invoicePdfUrl && (
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => setSalleFinalDocumentPreview({
                            title: "Facture générée",
                            url: salleFinalPreview.invoicePdfUrl,
                          })}
                        >
                          <ExternalLink className="mr-2 h-4 w-4" />
                          Facture générée
                        </Button>
                      )}
                      {salleFinalPreview.ribDocumentUrl && (
                        <Button
                          variant="outline"
                          size="sm"
                          onClick={() => setSalleFinalDocumentPreview({
                            title: "RIB MJS",
                            url: salleFinalPreview.ribDocumentUrl,
                          })}
                        >
                          <ExternalLink className="mr-2 h-4 w-4" />
                          RIB MJS
                        </Button>
                      )}
                    </div>
                  </div>

                  <div className="rounded-lg border bg-white p-4">
                    <p className="text-sm font-semibold">Aperçu du message final</p>
                    <pre className="mt-3 whitespace-pre-wrap text-sm text-muted-foreground font-sans">{salleFinalPreview.mailPreview}</pre>
                  </div>
                </div>
              )}
            </div>
          ) : null}
          <DialogFooter className="border-t px-6 py-4 bg-background">
            <Button
              variant="outline"
              onClick={() => {
                if (salleFinalDocumentPreview) {
                  setSalleFinalDocumentPreview(null);
                  return;
                }
                setShowSalleFinalDialog(false);
                setSalleFinalPreview(null);
                setSalleFinalDocumentPreview(null);
              }}
            >
              {salleFinalDocumentPreview ? "Retour au récapitulatif" : "Retour"}
            </Button>
            <Button
              onClick={() => sendSalleFinalNotificationMutation.mutate({ id: request.id })}
              disabled={sendSalleFinalNotificationMutation.isPending || !salleFinalPreview || Boolean(salleFinalDocumentPreview)}
            >
              {sendSalleFinalNotificationMutation.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : (
                <Send className="mr-2 h-4 w-4" />
              )}
              Confirmer l’envoi final
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* ============================================================ */}
      {/* DIALOG DE TRAITEMENT ADMIN                                    */}
      {/* ============================================================ */}
      <Dialog open={showProcessDialog} onOpenChange={setShowProcessDialog}>
        <DialogContent className={isDemandeSalle || isDemandeMaterielEvenementiel ? "max-w-2xl max-h-[90vh] overflow-y-auto" : "max-w-md"}>
          <DialogHeader>
            <DialogTitle>Traiter la demande</DialogTitle>
            <DialogDescription>
              {request.titre}
            </DialogDescription>
          </DialogHeader>

          {/* Résumé rapide de la demande dans le dialog pour l'admin */}
          {isDemandeSalle && (
            <div className="bg-muted/50 rounded-lg p-4 text-sm space-y-1.5 border">
              <p><span className="text-muted-foreground">Association :</span> <span className="font-medium">{formData.nomAssociation || '-'}</span></p>
              <p><span className="text-muted-foreground">Salle(s) :</span> <span className="font-medium">{(formData.sallesSelectionnees as string[])?.join(', ') || '-'}</span></p>
              <p><span className="text-muted-foreground">Période :</span> <span className="font-medium">{reservationPeriodSummary}</span></p>
              <div className="rounded-lg border border-primary/20 bg-white px-3 py-2">
                <p className="text-xs text-muted-foreground">Organisation horaire demandée</p>
                <p className="text-base font-semibold">{reservationScheduleSummary}</p>
              </div>
              {reservationDailySlots.length > 0 && (
                <div className="rounded-lg border border-primary/10 bg-white px-3 py-3 space-y-2">
                  <p className="text-xs text-muted-foreground">Détail par journée</p>
                  {reservationDailySlots.map((slot: any) => (
                    <div key={slot.date} className="flex justify-between gap-3 text-sm">
                      <span className="font-medium">{formatDateFr(slot.date)}</span>
                      <span>{slot.heureDebut || '?'} — {slot.heureFin || '?'}</span>
                    </div>
                  ))}
                </div>
              )}
              <p><span className="text-muted-foreground">Motif :</span> <span className="font-medium">{formData.motifReservation || '-'}</span></p>
            </div>
          )}

          {isDemandeMaterielEvenementiel && (
            <div className="bg-muted/50 rounded-lg p-4 text-sm space-y-1.5 border">
              <p><span className="text-muted-foreground">Commune :</span> <span className="font-medium">{formData.commune || '-'}</span></p>
              <p><span className="text-muted-foreground">Direction / service :</span> <span className="font-medium">{[formData.direction, formData.service].filter(Boolean).join(' / ') || '-'}</span></p>
              <p><span className="text-muted-foreground">Demandeur :</span> <span className="font-medium">{formData.demandeurNomPrenom || '-'}</span></p>
              <p><span className="text-muted-foreground">Manifestation :</span> <span className="font-medium">{formatMaterialEventPeriod(formData)}</span></p>
              <p><span className="text-muted-foreground">Matériel :</span> <span className="font-medium">{requestedMaterialItems.map(item => item.label).join(', ') || '-'}</span></p>
            </div>
          )}

          {isDemandeMaterielEvenementiel && (
            <div className="rounded-lg border border-amber-200 bg-amber-50 p-4 space-y-3">
              <div>
                <p className="text-sm font-semibold text-amber-900">Quantités demandées</p>
                <p className="text-xs text-amber-700">Récapitulatif visible pendant le traitement de la demande</p>
              </div>
              {requestedMaterialItems.length > 0 ? (
                <div className="grid gap-3 md:grid-cols-2">
                  {requestedMaterialItems.map(item => (
                    <div key={item.key} className="rounded-lg border border-amber-200 bg-white p-4">
                      <p className="text-sm text-muted-foreground">{item.label}</p>
                      <p className="text-3xl font-bold leading-none mt-2">{formData.quantitesDemandees?.[item.key] || "-"}</p>
                      <p className="text-xs text-muted-foreground mt-2">quantité demandée</p>
                      {item.key === "autres" && formData.autreMaterielPrecisions ? (
                        <p className="text-sm mt-3 border-t pt-3">{formData.autreMaterielPrecisions}</p>
                      ) : null}
                    </div>
                  ))}
                </div>
              ) : (
                <p className="text-sm text-muted-foreground">Aucun matériel sélectionné.</p>
              )}
            </div>
          )}

          <div className="space-y-4 py-2">
            {/* Décision */}
            <div className="space-y-2">
              <Label>Décision *</Label>
              <Select
                value={processData.status}
                onValueChange={(value) => setProcessData(prev => ({ ...prev, status: value }))}
              >
                <SelectTrigger>
                  <SelectValue placeholder="Sélectionnez une décision" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="en_cours_traitement">En cours de traitement</SelectItem>
                  <SelectItem value="information_complementaire">Demander des informations</SelectItem>
                  <SelectItem value="validee">Valider</SelectItem>
                  <SelectItem value="refusee">Refuser</SelectItem>
                </SelectContent>
              </Select>
            </div>

            {processData.status === 'validee' && request.montantDemande && (
              <div className="space-y-2">
                <Label htmlFor="montantAccorde">Montant accordé (€)</Label>
                <Input
                  id="montantAccorde"
                  type="number"
                  value={processData.montantAccorde}
                  onChange={(e) => setProcessData(prev => ({ ...prev, montantAccorde: e.target.value }))}
                  placeholder={`Max: ${(request.montantDemande / 100).toFixed(0)} €`}
                />
              </div>
            )}

            {/* Cadre DSU - uniquement pour les demandes de salle */}
            {isDemandeSalle && (
              <>
                <Separator />
                <div className="bg-[oklch(0.25_0.05_265)]/5 border border-[oklch(0.25_0.05_265)]/20 rounded-lg p-4 space-y-4">
                  <div className="flex items-center gap-2">
                    <Shield className="h-5 w-5 text-[oklch(0.25_0.05_265)]" />
                    <h3 className="font-semibold text-[oklch(0.25_0.05_265)]">
                      Cadre réservé à la Direction des Services aux Usagers
                    </h3>
                  </div>

                  <div className="grid gap-4 md:grid-cols-2">
                    <div className="space-y-2">
                      <Label htmlFor="dateReception">Date de réception</Label>
                      <Input
                        id="dateReception"
                        type="date"
                        value={dsuData.dateReception}
                        onChange={(e) => setDsuData(prev => ({ ...prev, dateReception: e.target.value }))}
                      />
                    </div>
                    <div className="space-y-2">
                      <Label htmlFor="dateDecision">Date de la décision</Label>
                      <Input
                        id="dateDecision"
                        type="date"
                        value={dsuData.dateDecision}
                        onChange={(e) => setDsuData(prev => ({ ...prev, dateDecision: e.target.value }))}
                      />
                    </div>
                  </div>

                  <div className="space-y-2">
                    <Label>Avis de la DSU</Label>
                    <Select
                      value={dsuData.avisDSU}
                      onValueChange={(value) => setDsuData(prev => ({ ...prev, avisDSU: value }))}
                    >
                      <SelectTrigger>
                        <SelectValue placeholder="Sélectionnez un avis" />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="favorable">Favorable</SelectItem>
                        <SelectItem value="favorable_avec_reserves">Favorable avec réserves</SelectItem>
                        <SelectItem value="defavorable">Défavorable</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>

                  <div className="space-y-2">
                    <Label htmlFor="responsableDSU">Nom du responsable DSU *</Label>
                    <Input
                      id="responsableDSU"
                      value={dsuData.responsableDSU}
                      onChange={(e) => setDsuData(prev => ({ ...prev, responsableDSU: e.target.value }))}
                      placeholder="Nom et prénom du responsable"
                    />
                  </div>

                  <Separator />

                  <div className="rounded-lg border border-primary/20 bg-primary/5 p-4 space-y-4">
                    <div className="flex items-center gap-2">
                      <Euro className="h-5 w-5 text-primary" />
                      <div>
                        <h4 className="text-sm font-semibold">Conditions financières / location</h4>
                        <p className="text-xs text-muted-foreground">
                          Décision administrative prioritaire pour formaliser la mise à disposition ou la location avant validation.
                        </p>
                      </div>
                    </div>

                    <div className="grid gap-4 md:grid-cols-2">
                      <div className="space-y-2">
                        <Label>Type d'usage interne</Label>
                        <Select
                          value={dsuData.salleReservation.usageType}
                          onValueChange={(value: SalleUsageType) =>
                            setDsuData((prev) => ({
                              ...prev,
                              salleReservation: {
                                ...prev.salleReservation,
                                usageType: value,
                              },
                            }))
                          }
                        >
                          <SelectTrigger>
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="conventionne">Conventionné</SelectItem>
                            <SelectItem value="occasionnel">Occasionnel</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>

                      <div className="space-y-2">
                        <Label>Fréquence de tarification</Label>
                        <Select
                          value={dsuData.salleReservation.frequency}
                          onValueChange={(value: SalleReservationFrequency) =>
                            setDsuData((prev) => ({
                              ...prev,
                              salleReservation: {
                                ...prev.salleReservation,
                                frequency: value,
                              },
                            }))
                          }
                        >
                          <SelectTrigger>
                            <SelectValue />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="demi_journee">Demi-journée</SelectItem>
                            <SelectItem value="journee">Journée</SelectItem>
                            <SelectItem value="mensuel">Mensuel</SelectItem>
                          </SelectContent>
                        </Select>
                      </div>
                    </div>

                    <div className="space-y-2">
                      <Label>Mode financier</Label>
                      <Select
                        value={dsuData.materielEvent.financialDecision.financialMode}
                        onValueChange={(value: MaterialFinancialMode) =>
                          setDsuData((prev) => ({
                            ...prev,
                            cautionRequise: value === 'gratuite_avec_caution' ? true : prev.cautionRequise,
                            materielEvent: {
                              ...prev.materielEvent,
                              financialDecision: {
                                ...prev.materielEvent.financialDecision,
                                financialMode: value,
                                rentalAmountEuros: value === 'location_payante' ? prev.materielEvent.financialDecision.rentalAmountEuros : '',
                              },
                            },
                          }))
                        }
                      >
                        <SelectTrigger>
                          <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="gratuite">Mise à disposition gratuite</SelectItem>
                          <SelectItem value="gratuite_avec_caution">Gratuite avec caution</SelectItem>
                          <SelectItem value="location_payante">Location payante</SelectItem>
                        </SelectContent>
                      </Select>
                    </div>

                    <div className="rounded-md border bg-white px-3 py-2 text-sm">
                      <span className="text-muted-foreground">Mode retenu :</span>{" "}
                      <span className="font-medium">{getFinancialModeLabel(dsuData.materielEvent.financialDecision.financialMode)}</span>
                    </div>

                    <div className="rounded-lg border bg-white p-4 space-y-3">
                      <div className="flex items-center justify-between gap-3">
                        <div>
                          <h5 className="text-sm font-semibold">Décision administrative prioritaire</h5>
                          <p className="text-xs text-muted-foreground">
                            Le texte officiel est généré automatiquement à partir de la salle, des dates et des horaires demandés.
                          </p>
                        </div>
                        <Badge variant="outline">
                          {SALLE_USAGE_TYPE_LABELS[dsuData.salleReservation.usageType]} • {SALLE_FREQUENCY_LABELS[dsuData.salleReservation.frequency]}
                        </Badge>
                      </div>
                      <Textarea value={salleDecisionAdministrativeText} readOnly rows={8} className="bg-muted/20" />
                    </div>

                    <div className="rounded-lg border bg-white p-4 space-y-3">
                      <div>
                        <h5 className="text-sm font-semibold">Calcul automatique du devis</h5>
                        <p className="text-xs text-muted-foreground">
                          Le montant est calculé automatiquement selon la grille tarifaire CCDS.
                        </p>
                      </div>
                      {sallePricingPreview && sallePricingPreview.unsupportedSalles.length === 0 ? (
                        <>
                          <div className="space-y-2">
                            {sallePricingPreview.lineItems.map((line) => (
                              <div key={`${line.salleId}-${line.frequency}`} className="flex items-start justify-between gap-4 rounded-md border px-3 py-2 text-sm">
                                <div>
                                  <p className="font-medium">{line.salleNom}</p>
                                  <p className="text-muted-foreground">
                                    {line.categoryLabel} • {line.quantity} x {formatAmount(line.unitAmountCents)}
                                  </p>
                                </div>
                                <span className="font-semibold">{formatAmount(line.totalAmountCents)}</span>
                              </div>
                            ))}
                          </div>
                          <div className="flex items-center justify-between rounded-md border border-primary/20 bg-primary/5 px-3 py-2">
                            <span className="text-sm font-medium">Total estimé du devis</span>
                            <span className="text-base font-semibold text-primary">{formatAmount(sallePricingPreview.totalAmountCents)}</span>
                          </div>
                        </>
                      ) : (
                        <div className="rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900">
                          {sallePricingPreview?.unsupportedSalles?.length
                            ? `Aucune tarification automatique n'est disponible pour : ${sallePricingPreview.unsupportedSalles.map((item) => item.salleNom).join(', ')} avec cette combinaison.`
                            : "Le devis sera disponible dès qu'une combinaison salle / fréquence compatible sera choisie."}
                        </div>
                      )}
                    </div>

                    <div className="flex items-center space-x-3">
                      <Checkbox
                        id="depositRequiredSalle"
                        checked={dsuData.materielEvent.financialDecision.depositRequired}
                        onCheckedChange={(checked) =>
                          setDsuData((prev) => ({
                            ...prev,
                            cautionRequise: Boolean(checked),
                            materielEvent: {
                              ...prev.materielEvent,
                              financialDecision: {
                                ...prev.materielEvent.financialDecision,
                                depositRequired: Boolean(checked),
                                depositAmountEuros: checked ? prev.materielEvent.financialDecision.depositAmountEuros : '',
                              },
                            },
                          }))
                        }
                      />
                      <Label htmlFor="depositRequiredSalle" className="cursor-pointer">Caution / dépôt de garantie requis</Label>
                    </div>

                    <div className="grid gap-4 md:grid-cols-2">
                      <div className="space-y-2">
                        <Label htmlFor="depositAmountEurosSalle">Montant de la caution (€)</Label>
                        <Input
                          id="depositAmountEurosSalle"
                          type="number"
                          min={0}
                          step="0.01"
                          value={dsuData.materielEvent.financialDecision.depositAmountEuros}
                          onChange={(e) =>
                            setDsuData((prev) => ({
                              ...prev,
                              montantCaution: e.target.value,
                              materielEvent: {
                                ...prev.materielEvent,
                                financialDecision: {
                                  ...prev.materielEvent.financialDecision,
                                  depositAmountEuros: e.target.value,
                                },
                              },
                            }))
                          }
                          disabled={!dsuData.materielEvent.financialDecision.depositRequired}
                          placeholder="0.00"
                        />
                      </div>
                      <div className="space-y-2">
                        <Label htmlFor="rentalAmountEurosSalle">Montant de location calculé (€)</Label>
                        <Input
                          id="rentalAmountEurosSalle"
                          type="number"
                          min={0}
                          step="0.01"
                          value={dsuData.materielEvent.financialDecision.rentalAmountEuros}
                          onChange={(e) =>
                            setDsuData((prev) => ({
                              ...prev,
                              materielEvent: {
                                ...prev.materielEvent,
                                financialDecision: {
                                  ...prev.materielEvent.financialDecision,
                                  rentalAmountEuros: e.target.value,
                                },
                              },
                            }))
                          }
                          disabled
                          placeholder="0.00"
                        />
                      </div>
                    </div>

                    <div className="space-y-2">
                      <Label htmlFor="pricingNotesSalle">Clauses spécifiques / réserves</Label>
                      <Textarea
                        id="pricingNotesSalle"
                        value={dsuData.materielEvent.financialDecision.pricingNotes}
                        onChange={(e) =>
                          setDsuData((prev) => ({
                            ...prev,
                            materielEvent: {
                              ...prev.materielEvent,
                              financialDecision: {
                                ...prev.materielEvent.financialDecision,
                                pricingNotes: e.target.value,
                              },
                            },
                          }))
                        }
                        rows={3}
                        placeholder="Ex. acompte demandé avant remise des clés, attestation RC obligatoire, consignes particulières de la Directrice..."
                      />
                    </div>

                    <div className="rounded-lg border bg-white p-4 space-y-3">
                      <div>
                        <h5 className="text-sm font-semibold">Conditions financières officielles</h5>
                        <p className="text-xs text-muted-foreground">
                          Ce texte sera repris dans le dossier transmis à l'association.
                        </p>
                      </div>
                      <Textarea value={CONDITIONS_FINANCIERES_SALLE_TEXT} readOnly rows={12} className="bg-muted/20" />
                    </div>
                  </div>

                  <Separator />

                  <h4 className="text-sm font-semibold text-[oklch(0.25_0.05_265)]">Conditions particulières</h4>
                  <div className="flex items-center space-x-3">
                    <Checkbox
                      id="cautionRequise"
                      checked={dsuData.cautionRequise}
                      onCheckedChange={(checked) => setDsuData(prev => ({ ...prev, cautionRequise: !!checked }))}
                    />
                    <Label htmlFor="cautionRequise" className="cursor-pointer">Caution requise</Label>
                  </div>

                  {dsuData.cautionRequise && (
                    <div className="space-y-2 ml-6">
                      <Label htmlFor="montantCaution">Montant de la caution (€)</Label>
                      <Input
                        id="montantCaution"
                        value={dsuData.montantCaution}
                        onChange={(e) => setDsuData(prev => ({ ...prev, montantCaution: e.target.value }))}
                        placeholder="Ex: 500"
                      />
                    </div>
                  )}

                  <div className="flex items-center space-x-3">
                    <Checkbox
                      id="assuranceRequise"
                      checked={dsuData.assuranceRequise}
                      onCheckedChange={(checked) => setDsuData(prev => ({ ...prev, assuranceRequise: !!checked }))}
                    />
                    <Label htmlFor="assuranceRequise" className="cursor-pointer">Attestation d'assurance requise</Label>
                  </div>

                  <div className="space-y-2">
                    <Label htmlFor="horairesImposes">Horaires imposés</Label>
                    <Input
                      id="horairesImposes"
                      value={dsuData.horairesImposes}
                      onChange={(e) => setDsuData(prev => ({ ...prev, horairesImposes: e.target.value }))}
                      placeholder="Ex: 8h00 - 22h00"
                    />
                  </div>

                  <div className="space-y-2">
                    <Label htmlFor="conditionsParticulieres">Autres conditions particulières</Label>
                    <Textarea
                      id="conditionsParticulieres"
                      value={dsuData.conditionsParticulieres}
                      onChange={(e) => setDsuData(prev => ({ ...prev, conditionsParticulieres: e.target.value }))}
                      placeholder="Ex: Nettoyage obligatoire après utilisation, interdiction de consommation d'alcool..."
                      rows={2}
                    />
                  </div>

                  <Separator />

                  <div className="space-y-2">
                    <Label htmlFor="observationsDSU">Observations de la DSU</Label>
                      <Textarea
                        id="observationsDSU"
                        value={dsuData.observationsDSU}
                        onChange={(e) => setDsuData(prev => ({ ...prev, observationsDSU: e.target.value }))}
                        placeholder="Observations complémentaires..."
                        rows={2}
                      />
                    </div>
                  </div>
              </>
            )}

            {isDemandeMaterielEvenementiel && (
              <>
                <Separator className="my-4" />
                <div className="space-y-4">
                  <div className="flex items-center gap-2">
                    <Shield className="h-5 w-5 text-primary" />
                    <Label className="text-base font-semibold">Cadre réservé à la DSU</Label>
                  </div>

                  <div className="grid gap-4 md:grid-cols-2">
                    <div className="space-y-2">
                      <Label htmlFor="dateReceptionMateriel">Date de réception</Label>
                      <Input
                        id="dateReceptionMateriel"
                        type="date"
                        value={dsuData.dateReception}
                        onChange={(e) => setDsuData(prev => ({ ...prev, dateReception: e.target.value }))}
                      />
                    </div>
                    <div className="space-y-2">
                      <Label htmlFor="dateDecisionMateriel">Date de décision</Label>
                      <Input
                        id="dateDecisionMateriel"
                        type="date"
                        value={dsuData.dateDecision}
                        onChange={(e) => setDsuData(prev => ({ ...prev, dateDecision: e.target.value }))}
                      />
                    </div>
                  </div>

                  <div className="space-y-2">
                    <Label htmlFor="responsableDSUMateriel">Responsable DSU *</Label>
                    <Input
                      id="responsableDSUMateriel"
                      value={dsuData.responsableDSU}
                      onChange={(e) => setDsuData(prev => ({ ...prev, responsableDSU: e.target.value }))}
                    />
                  </div>

                  <div className="space-y-3 rounded-lg border bg-muted/30 p-4">
                    <div>
                      <h4 className="text-sm font-semibold">Vue de la demande</h4>
                      <p className="text-xs text-muted-foreground">
                        L'administration voit ici exactement ce qui est demandé, puis répond sur ce qu'elle peut accorder.
                      </p>
                    </div>
                    {requestedMaterialItems.length > 0 ? (
                      <div className="grid gap-4 md:grid-cols-2">
                        {requestedMaterialItems.map(item => (
                          <div key={item.key} className="rounded-lg border border-primary/20 bg-white p-4 space-y-3">
                            <div className="flex items-start justify-between gap-3">
                              <div>
                                <p className="font-medium">{item.label}</p>
                                <p className="text-xs text-muted-foreground mt-1">Matériel demandé</p>
                              </div>
                              <span className="rounded-full bg-amber-100 px-2.5 py-1 text-xs font-medium text-amber-900">
                                Demandé
                              </span>
                            </div>
                            <div className="rounded-lg border border-dashed bg-amber-50 px-4 py-3">
                              <p className="text-xs text-muted-foreground">Quantité demandée</p>
                              <p className="text-3xl font-bold mt-1">{formData.quantitesDemandees?.[item.key] || "-"}</p>
                            </div>
                            {item.key === "autres" && formData.autreMaterielPrecisions ? (
                              <div className="rounded-lg border bg-muted/30 p-3 text-sm">
                                {formData.autreMaterielPrecisions}
                              </div>
                            ) : null}
                            <div className="flex items-center gap-3 pt-1">
                              <Checkbox
                                checked={Boolean(dsuData.materielEvent.itemsAccordes[item.key])}
                                onCheckedChange={(checked) =>
                                  setDsuData(prev => ({
                                    ...prev,
                                    materielEvent: {
                                      ...prev.materielEvent,
                                      itemsAccordes: {
                                        ...prev.materielEvent.itemsAccordes,
                                        [item.key]: Boolean(checked),
                                      },
                                      quantitesAccordees: {
                                        ...prev.materielEvent.quantitesAccordees,
                                        [item.key]: checked
                                          ? (prev.materielEvent.quantitesAccordees[item.key] || getRequestedQuantityForItem(item.key))
                                          : '',
                                      },
                                    },
                                  }))
                                }
                              />
                              <span className="text-sm font-medium">Accorder ce matériel</span>
                            </div>
                            <div className="space-y-2">
                              <Label>
                                Quantité accordée
                                {formData.quantitesDemandees?.[item.key] ? ` sur ${formData.quantitesDemandees[item.key]} demandée(s)` : ''}
                              </Label>
                              <Input
                                value={dsuData.materielEvent.quantitesAccordees[item.key]}
                                onChange={(e) =>
                                  setDsuData(prev => ({
                                    ...prev,
                                    materielEvent: {
                                      ...prev.materielEvent,
                                      quantitesAccordees: {
                                        ...prev.materielEvent.quantitesAccordees,
                                        [item.key]: e.target.value,
                                      },
                                    },
                                  }))
                                }
                                disabled={!dsuData.materielEvent.itemsAccordes[item.key]}
                                placeholder="..."
                              />
                            </div>
                          </div>
                        ))}
                      </div>
                    ) : (
                      <p className="text-sm text-muted-foreground">Aucun matériel demandé sur cette fiche.</p>
                    )}
                  </div>

                  {nonRequestedMaterialItems.length > 0 && (
                    <div className="space-y-3">
                      <Label className="text-sm font-semibold">Autres matériels disponibles</Label>
                      <div className="grid gap-4 md:grid-cols-2">
                        {nonRequestedMaterialItems.map(item => (
                          <div key={item.key} className="rounded-lg border border-dashed p-4 space-y-3 opacity-80">
                            <div className="flex items-center justify-between gap-3">
                              <span className="font-medium">{item.label}</span>
                              <span className="rounded-full bg-muted px-2.5 py-1 text-xs text-muted-foreground">
                                Non demandé
                              </span>
                            </div>
                            <div className="flex items-center gap-3">
                              <Checkbox
                                checked={Boolean(dsuData.materielEvent.itemsAccordes[item.key])}
                                onCheckedChange={(checked) =>
                                  setDsuData(prev => ({
                                    ...prev,
                                    materielEvent: {
                                      ...prev.materielEvent,
                                      itemsAccordes: {
                                        ...prev.materielEvent.itemsAccordes,
                                        [item.key]: Boolean(checked),
                                      },
                                      quantitesAccordees: {
                                        ...prev.materielEvent.quantitesAccordees,
                                        [item.key]: checked
                                          ? (prev.materielEvent.quantitesAccordees[item.key] || '1')
                                          : '',
                                      },
                                    },
                                  }))
                                }
                              />
                              <span className="text-sm font-medium">Accorder malgré tout</span>
                            </div>
                            <div className="space-y-2">
                              <Label>Quantité accordée</Label>
                              <Input
                                value={dsuData.materielEvent.quantitesAccordees[item.key]}
                                onChange={(e) =>
                                  setDsuData(prev => ({
                                    ...prev,
                                    materielEvent: {
                                      ...prev.materielEvent,
                                      quantitesAccordees: {
                                        ...prev.materielEvent.quantitesAccordees,
                                        [item.key]: e.target.value,
                                      },
                                    },
                                  }))
                                }
                                disabled={!dsuData.materielEvent.itemsAccordes[item.key]}
                                placeholder="..."
                              />
                            </div>
                          </div>
                        ))}
                      </div>
                    </div>
                  )}

                  {Boolean(dsuData.materielEvent.itemsAccordes.autres) && (
                    <div className="space-y-2">
                      <Label htmlFor="autresPrecisionsDSU">Précisions sur "Autres"</Label>
                      <Textarea
                        id="autresPrecisionsDSU"
                        value={dsuData.materielEvent.autresPrecisions}
                        onChange={(e) =>
                          setDsuData(prev => ({
                            ...prev,
                            materielEvent: {
                              ...prev.materielEvent,
                              autresPrecisions: e.target.value,
                            },
                          }))
                        }
                        rows={3}
                      />
                    </div>
                  )}

                  <div className="rounded-lg border border-primary/20 bg-primary/5 p-4 space-y-4">
                    <div className="flex items-center gap-2">
                      <Euro className="h-5 w-5 text-primary" />
                      <div>
                        <h4 className="text-sm font-semibold">Conditions financières / location</h4>
                        <p className="text-xs text-muted-foreground">
                          Décision administrative prioritaire pour formaliser la mise à disposition ou la location avant validation.
                        </p>
                      </div>
                    </div>

                    <div className="space-y-2">
                      <Label>Mode financier</Label>
                      <Select
                        value={dsuData.materielEvent.financialDecision.financialMode}
                        onValueChange={(value: MaterialFinancialMode) =>
                          setDsuData((prev) => ({
                            ...prev,
                            cautionRequise: value === 'gratuite_avec_caution' ? true : prev.cautionRequise,
                            materielEvent: {
                              ...prev.materielEvent,
                              financialDecision: {
                                ...prev.materielEvent.financialDecision,
                                financialMode: value,
                                rentalAmountEuros: value === 'location_payante' ? prev.materielEvent.financialDecision.rentalAmountEuros : '',
                              },
                            },
                          }))
                        }
                      >
                        <SelectTrigger>
                          <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="gratuite">Mise à disposition gratuite</SelectItem>
                          <SelectItem value="gratuite_avec_caution">Gratuite avec caution</SelectItem>
                          <SelectItem value="location_payante">Location payante</SelectItem>
                        </SelectContent>
                      </Select>
                    </div>

                    <div className="flex items-center space-x-3">
                      <Checkbox
                        id="depositRequiredMateriel"
                        checked={dsuData.materielEvent.financialDecision.depositRequired}
                        onCheckedChange={(checked) =>
                          setDsuData((prev) => ({
                            ...prev,
                            cautionRequise: Boolean(checked),
                            materielEvent: {
                              ...prev.materielEvent,
                              financialDecision: {
                                ...prev.materielEvent.financialDecision,
                                depositRequired: Boolean(checked),
                                depositAmountEuros: checked ? prev.materielEvent.financialDecision.depositAmountEuros : '',
                              },
                            },
                          }))
                        }
                      />
                      <Label htmlFor="depositRequiredMateriel" className="cursor-pointer">Caution / dépôt de garantie requis</Label>
                    </div>

                    <div className="grid gap-4 md:grid-cols-2">
                      <div className="space-y-2">
                        <Label htmlFor="depositAmountEuros">Montant de la caution (€)</Label>
                        <Input
                          id="depositAmountEuros"
                          type="number"
                          min={0}
                          step="0.01"
                          value={dsuData.materielEvent.financialDecision.depositAmountEuros}
                          onChange={(e) =>
                            setDsuData((prev) => ({
                              ...prev,
                              montantCaution: e.target.value,
                              materielEvent: {
                                ...prev.materielEvent,
                                financialDecision: {
                                  ...prev.materielEvent.financialDecision,
                                  depositAmountEuros: e.target.value,
                                },
                              },
                            }))
                          }
                          disabled={!dsuData.materielEvent.financialDecision.depositRequired}
                          placeholder="0.00"
                        />
                      </div>
                      <div className="space-y-2">
                        <Label htmlFor="rentalAmountEuros">Montant de location (€)</Label>
                        <Input
                          id="rentalAmountEuros"
                          type="number"
                          min={0}
                          step="0.01"
                          value={dsuData.materielEvent.financialDecision.rentalAmountEuros}
                          onChange={(e) =>
                            setDsuData((prev) => ({
                              ...prev,
                              materielEvent: {
                                ...prev.materielEvent,
                                financialDecision: {
                                  ...prev.materielEvent.financialDecision,
                                  rentalAmountEuros: e.target.value,
                                },
                              },
                            }))
                          }
                          disabled={dsuData.materielEvent.financialDecision.financialMode !== 'location_payante'}
                          placeholder="0.00"
                        />
                      </div>
                    </div>

                    <div className="space-y-2">
                      <Label htmlFor="pricingNotes">Clauses spécifiques / réserves</Label>
                      <Textarea
                        id="pricingNotes"
                        value={dsuData.materielEvent.financialDecision.pricingNotes}
                        onChange={(e) =>
                          setDsuData((prev) => ({
                            ...prev,
                            materielEvent: {
                              ...prev.materielEvent,
                              financialDecision: {
                                ...prev.materielEvent.financialDecision,
                                pricingNotes: e.target.value,
                              },
                            },
                          }))
                        }
                        rows={3}
                        placeholder="Ex. remise gracieuse exceptionnelle, caution conservée jusqu'à validation de la restitution, clauses issues de l'annexe..."
                      />
                    </div>
                  </div>

                  <div className="space-y-2">
                    <Label htmlFor="observationsDSUMateriel">Observations DSU</Label>
                    <Textarea
                      id="observationsDSUMateriel"
                      value={dsuData.observationsDSU}
                      onChange={(e) => setDsuData(prev => ({ ...prev, observationsDSU: e.target.value }))}
                      rows={4}
                    />
                  </div>
                </div>
              </>
            )}

            {/* Commentaire admin */}
            <div className="space-y-2">
              <Label htmlFor="commentaire">Commentaire pour l'association</Label>
              <Textarea
                id="commentaire"
                value={processData.commentaireAdmin}
                onChange={(e) => setProcessData(prev => ({ ...prev, commentaireAdmin: e.target.value }))}
                placeholder="Ajoutez un commentaire pour l'association..."
                rows={3}
              />
            </div>

            {isDemandeMaterielEvenementiel && (
              <>
                <div className="space-y-2">
                  <Label htmlFor="recapServiceLabel">Service terrain / récupération</Label>
                  <Input
                    id="recapServiceLabel"
                    value={processData.recapServiceLabel}
                    onChange={(e) => setProcessData(prev => ({ ...prev, recapServiceLabel: e.target.value }))}
                    placeholder="Ex. Service technique, régie logistique, agent récupérateur"
                  />
                </div>

                <div className="space-y-2">
                  <Label htmlFor="recapServiceDirectory">Répertoire du service terrain</Label>
                  <Select
                    value={processData.recapServiceId}
                    onValueChange={applyOperationalRecapServiceToProcessData}
                  >
                    <SelectTrigger id="recapServiceDirectory">
                      <SelectValue placeholder="Sélectionner un service enregistré" />
                    </SelectTrigger>
                    <SelectContent>
                      {terrainOperationalRecapServices
                        .filter((service) => service.actif)
                        .map((service) => (
                          <SelectItem key={service.id} value={String(service.id)}>
                            {service.label}
                          </SelectItem>
                        ))}
                    </SelectContent>
                  </Select>
                  <p className="text-sm text-muted-foreground">
                    Sélectionne un service pour préremplir automatiquement le terrain et ses destinataires.
                  </p>
                </div>

                <div className="space-y-2">
                  <Label htmlFor="recapRecipients">Destinataires terrain</Label>
                  <Textarea
                    id="recapRecipients"
                    value={processData.recapRecipients}
                    onChange={(e) => setProcessData(prev => ({ ...prev, recapRecipients: e.target.value }))}
                    placeholder="nom.service@collectivite.fr, collegue@collectivite.fr"
                    rows={4}
                  />
                  <p className="text-sm text-muted-foreground">
                    Sépare les adresses par virgule, point-virgule ou retour à la ligne.
                  </p>
                </div>

                <Separator />

                <div className="space-y-2">
                  <Label htmlFor="supervisionServiceLabel">Service interne de contrôle</Label>
                  <Input
                    id="supervisionServiceLabel"
                    value={processData.supervisionServiceLabel}
                    onChange={(e) => setProcessData(prev => ({ ...prev, supervisionServiceLabel: e.target.value }))}
                    placeholder="Ex. DSU, cellule de suivi, secrétariat général"
                  />
                </div>

                <div className="space-y-2">
                  <Label htmlFor="supervisionServiceDirectory">Répertoire du contrôle interne</Label>
                  <Select
                    value={processData.supervisionServiceId}
                    onValueChange={applyOperationalSupervisionServiceToProcessData}
                  >
                    <SelectTrigger id="supervisionServiceDirectory">
                      <SelectValue placeholder="Sélectionner un service enregistré" />
                    </SelectTrigger>
                    <SelectContent>
                      {controlOperationalRecapServices
                        .filter((service) => service.actif)
                        .map((service) => (
                          <SelectItem key={service.id} value={String(service.id)}>
                            {service.label}
                          </SelectItem>
                        ))}
                    </SelectContent>
                  </Select>
                  <p className="text-sm text-muted-foreground">
                    Ce service reçoit les confirmations, retards et alertes de restitution.
                  </p>
                </div>

                <div className="space-y-2">
                  <Label htmlFor="supervisionRecipients">Destinataires du contrôle interne</Label>
                  <Textarea
                    id="supervisionRecipients"
                    value={processData.supervisionRecipients}
                    onChange={(e) => setProcessData(prev => ({ ...prev, supervisionRecipients: e.target.value }))}
                    placeholder="suivi@collectivite.fr, direction@collectivite.fr"
                    rows={4}
                  />
                  <p className="text-sm text-muted-foreground">
                    Sépare les adresses par virgule, point-virgule ou retour à la ligne.
                  </p>
                </div>
              </>
            )}
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setShowProcessDialog(false)}>
              Annuler
            </Button>
            {requestNeedsFinancialDecision && processData.status === 'validee' && !isDemandeSalle && (
              <Button
                variant="outline"
                onClick={() => handleProcess(true)}
                disabled={processMutation.isPending}
              >
                {processMutation.isPending ? (
                  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                ) : (
                  <FileText className="mr-2 h-4 w-4" />
                )}
                Valider et générer la convention
              </Button>
            )}
            <Button onClick={() => handleProcess(false)} disabled={processMutation.isPending}>
              {processMutation.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : processData.status === 'validee' ? (
                <CheckCircle className="mr-2 h-4 w-4" />
              ) : processData.status === 'refusee' ? (
                <XCircle className="mr-2 h-4 w-4" />
              ) : null}
              {isDemandeSalle && processData.status === 'validee' ? 'Valider et envoyer le devis' : 'Confirmer'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={showLogisticsAssignmentDialog}
        onOpenChange={(open) => {
          setShowLogisticsAssignmentDialog(open);
          if (!open) {
            setLogisticsAssignmentData({
              recapServiceId: '',
              recapRecipients: '',
              recapServiceLabel: '',
              supervisionServiceId: '',
              supervisionRecipients: '',
              supervisionServiceLabel: '',
            });
          }
        }}
      >
        <DialogContent className="max-w-xl">
          <DialogHeader>
            <DialogTitle>{materialReturnAssigned ? "Réassigner et relancer" : "Assigner le service terrain"}</DialogTitle>
            <DialogDescription>
              Attribue directement depuis le dossier le service ou l’agent chargé du retour terrain, puis renvoie un lien actif.
            </DialogDescription>
          </DialogHeader>

          <div className="space-y-4">
            <div className="rounded-lg border bg-muted/20 p-4 space-y-1">
              <p className="font-medium">{request.titre}</p>
              <p className="text-sm text-muted-foreground">{request.associationInfo?.nomAssociation || "-"}</p>
              <p className="text-sm text-muted-foreground">
                Restitution prévue le {formatDateFr(formData.dateRestitution)}
              </p>
            </div>

            <div className="space-y-2">
              <Label htmlFor="requestDetailLogisticsServiceDirectory">Répertoire du service terrain</Label>
              <select
                id="requestDetailLogisticsServiceDirectory"
                value={logisticsAssignmentData.recapServiceId}
                onChange={(event) => applyOperationalRecapServiceToAssignmentData(event.target.value)}
                className="border-input focus-visible:border-ring focus-visible:ring-ring/50 dark:bg-input/30 flex h-9 w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px]"
              >
                <option value="">Sélectionner un service enregistré</option>
                {terrainOperationalRecapServices
                  .filter((service) => service.actif)
                  .map((service) => (
                    <option key={service.id} value={String(service.id)}>
                      {service.label}
                    </option>
                  ))}
              </select>
            </div>

            <div className="space-y-2">
              <Label htmlFor="requestDetailLogisticsServiceLabel">Service terrain / récupération</Label>
              <Input
                id="requestDetailLogisticsServiceLabel"
                value={logisticsAssignmentData.recapServiceLabel}
                onChange={(event) =>
                  setLogisticsAssignmentData((prev) => ({ ...prev, recapServiceLabel: event.target.value }))
                }
                placeholder="Ex. Service technique Sinnamary"
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="requestDetailLogisticsRecipients">Destinataires terrain</Label>
              <Textarea
                id="requestDetailLogisticsRecipients"
                value={logisticsAssignmentData.recapRecipients}
                onChange={(event) =>
                  setLogisticsAssignmentData((prev) => ({ ...prev, recapRecipients: event.target.value }))
                }
                rows={4}
                placeholder="agent@collectivite.fr, service@collectivite.fr"
              />
              <p className="text-sm text-muted-foreground">
                Sépare les adresses par virgule, point-virgule ou retour à la ligne.
              </p>
            </div>

            <Separator />

            <div className="space-y-2">
              <Label htmlFor="requestDetailSupervisionServiceDirectory">Service interne de contrôle</Label>
              <select
                id="requestDetailSupervisionServiceDirectory"
                value={logisticsAssignmentData.supervisionServiceId}
                onChange={(event) => applyOperationalSupervisionServiceToAssignmentData(event.target.value)}
                className="border-input focus-visible:border-ring focus-visible:ring-ring/50 dark:bg-input/30 flex h-9 w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px]"
              >
                <option value="">Sélectionner un service interne</option>
                {controlOperationalRecapServices
                  .filter((service) => service.actif)
                  .map((service) => (
                    <option key={service.id} value={String(service.id)}>
                      {service.label}
                    </option>
                  ))}
              </select>
            </div>

            <div className="space-y-2">
              <Label htmlFor="requestDetailSupervisionServiceLabel">Libellé du service interne de contrôle</Label>
              <Input
                id="requestDetailSupervisionServiceLabel"
                value={logisticsAssignmentData.supervisionServiceLabel}
                onChange={(event) =>
                  setLogisticsAssignmentData((prev) => ({ ...prev, supervisionServiceLabel: event.target.value }))
                }
                placeholder="Ex. DSU / cellule de contrôle"
              />
            </div>

            <div className="space-y-2">
              <Label htmlFor="requestDetailSupervisionRecipients">Destinataires du contrôle interne</Label>
              <Textarea
                id="requestDetailSupervisionRecipients"
                value={logisticsAssignmentData.supervisionRecipients}
                onChange={(event) =>
                  setLogisticsAssignmentData((prev) => ({ ...prev, supervisionRecipients: event.target.value }))
                }
                rows={3}
                placeholder="dsu@collectivite.fr, controle@collectivite.fr"
              />
              <p className="text-sm text-muted-foreground">
                Ce service recevra les mails de contrôle, de clôture et les alertes de suivi.
              </p>
            </div>
          </div>

          <DialogFooter>
            <Button variant="outline" onClick={() => setShowLogisticsAssignmentDialog(false)}>
              Annuler
            </Button>
            <Button
              onClick={() => {
                const recipients = parseRecipientText(logisticsAssignmentData.recapRecipients);
                if (!logisticsAssignmentData.recapServiceLabel.trim() && !logisticsAssignmentData.recapServiceId) {
                  toast.error("Choisis un service ou renseigne un libellé de mission");
                  return;
                }
                if (recipients.length === 0) {
                  toast.error("Ajoute au moins une adresse email pour la récupération");
                  return;
                }
                const supervisionRecipients = parseRecipientText(logisticsAssignmentData.supervisionRecipients);
                assignMaterialReturnMutation.mutate({
                  requestId,
                  recapServiceId: logisticsAssignmentData.recapServiceId
                    ? parseInt(logisticsAssignmentData.recapServiceId, 10)
                    : undefined,
                  recapServiceLabel: logisticsAssignmentData.recapServiceLabel.trim() || undefined,
                  recapRecipients: recipients,
                  supervisionServiceId: logisticsAssignmentData.supervisionServiceId
                    ? parseInt(logisticsAssignmentData.supervisionServiceId, 10)
                    : undefined,
                  supervisionServiceLabel: logisticsAssignmentData.supervisionServiceLabel.trim() || undefined,
                  supervisionRecipients: supervisionRecipients.length > 0 ? supervisionRecipients : undefined,
                });
              }}
              disabled={assignMaterialReturnMutation.isPending}
            >
              {assignMaterialReturnMutation.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : (
                <Send className="mr-2 h-4 w-4" />
              )}
              {materialReturnAssigned ? "Réassigner et relancer" : "Valider l'assignation"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Dialog d'annulation */}
      <Dialog open={showCancelDialog} onOpenChange={setShowCancelDialog}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Annuler cette demande ?</DialogTitle>
            <DialogDescription>
              Vous êtes sur le point d'annuler la demande « {request.titre} ». L'administration sera notifiée de cette annulation.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-4 py-4">
            <div className="space-y-2">
              <Label htmlFor="cancelRaison">Raison de l'annulation (optionnel)</Label>
              <Textarea
                id="cancelRaison"
                value={cancelRaison}
                onChange={(e) => setCancelRaison(e.target.value)}
                placeholder="Indiquez la raison de l'annulation..."
                rows={3}
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setShowCancelDialog(false)}>
              Retour
            </Button>
            <Button
              variant="destructive"
              onClick={() => cancelMutation.mutate({ id: request.id, raison: cancelRaison || undefined })}
              disabled={cancelMutation.isPending}
            >
              {cancelMutation.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : (
                <Ban className="mr-2 h-4 w-4" />
              )}
              Confirmer l'annulation
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}
