"use client";

import { useEffect, useMemo, useState, useRef, useImperativeHandle, forwardRef } from "react";
import { supabase } from "@/lib/supabaseClient";
import Link from "next/link";
import { RefreshCw, Check, X, Settings, FileText, CheckCircle, BarChart3, Eye, ChevronDown, Trash2, FileDown, FileSignature, Euro, XCircle, BellRing, Clock, AlertCircle, Calendar } from "lucide-react";
import { toast } from "sonner";
import BulkPdfProgressModal from "./BulkPdfProgressModal";
import PdfVerificationModal from "./PdfVerificationModal";
import ContractDetailsModal from "./ContractDetailsModal";
import BulkESignProgressModal from "./BulkESignProgressModal";
import BulkESignConfirmModal from "./BulkESignConfirmModal";
import { BulkEmployeeReminderModal } from "./contracts/BulkEmployeeReminderModal";
import { EmployeeReminderModal } from "./contracts/EmployeeReminderModal";
import { SmartReminderModal, type SmartReminderContract, type ReminderAction } from "./contracts/SmartReminderModal";
import BulkPayslipModal from "./contracts/BulkPayslipModal";

// Utility function to format dates as DD/MM/YYYY
function formatDate(dateString: string | null | undefined): string {
  if (!dateString) return "—";
  try {
    const date = new Date(dateString);
    return date.toLocaleDateString('fr-FR', {
      day: '2-digit',
      month: '2-digit',
      year: 'numeric'
    });
  } catch {
    return "—";
  }
}

// Utility function to format notification date as DD/MM HH:MM
function formatNotificationDate(dateString: string | null): string {
  if (!dateString) return "—";
  try {
    const date = new Date(dateString);
    const day = String(date.getDate()).padStart(2, '0');
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    return `${day}/${month} ${hours}:${minutes}`;
  } catch {
    return "—";
  }
}

// Utility function to get notification color based on contract start date
function getNotificationColor(startDate: string | null | undefined): string {
  if (!startDate) return 'text-slate-400';
  
  const start = new Date(startDate);
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  start.setHours(0, 0, 0, 0);
  
  const diffTime = start.getTime() - today.getTime();
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  
  // Rouge si contrat démarre aujourd'hui ou dans le passé
  if (diffDays <= 0) return 'text-red-600';
  // Orange si moins de 48 heures (moins de 2 jours)
  if (diffDays < 2) return 'text-orange-600';
  // Vert si plus de 48 heures
  return 'text-green-600';
}

// Utility function to format employee name as "NOM Prénom"
// Priorité : utiliser salaries.salarie si disponible, sinon formater employee_name
function formatEmployeeName(contract: { employee_name?: string | null; salaries?: { salarie?: string | null; nom?: string | null; prenom?: string | null; } | null }): string {
  // 1. Priorité : utiliser salaries.salarie (toujours à jour)
  if (contract.salaries?.salarie) {
    return contract.salaries.salarie;
  }
  
  // 2. Construire depuis nom + prénom si disponibles
  if (contract.salaries?.nom || contract.salaries?.prenom) {
    const nom = (contract.salaries.nom || '').toUpperCase().trim();
    const prenom = (contract.salaries.prenom || '').trim();
    return [nom, prenom].filter(Boolean).join(' ');
  }
  
  // 3. Fallback : utiliser employee_name (ancien format)
  if (!contract.employee_name) return "—";
  
  const parts = contract.employee_name.trim().split(' ');
  if (parts.length < 2) return contract.employee_name;
  
  const prenom = parts[0];
  const nom = parts.slice(1).join(' ');
  
  return `${nom.toUpperCase()} ${prenom}`;
}

// Utility function to extract last name for sorting
// Priorité : utiliser salaries.nom si disponible, sinon parser employee_name
function getLastName(contract: { employee_name?: string | null; salaries?: { nom?: string | null } | null }): string {
  // 1. Priorité : utiliser salaries.nom (toujours à jour)
  if (contract.salaries?.nom) {
    return contract.salaries.nom.toUpperCase();
  }
  
  // 2. Fallback : parser employee_name
  if (!contract.employee_name) return "";
  
  const parts = contract.employee_name.trim().split(' ');
  if (parts.length < 2) return contract.employee_name;
  
  return parts.slice(1).join(' ');
}

// Utility functions to get icon and color for each state
function getEtatContratIcon(etat: string | null | undefined): { icon: React.ReactNode; tooltip: string } {
  const s = String(etat || "").toLowerCase();
  if (s.includes('receptee') || s.includes('recue') || s.includes('reçue')) {
    return { icon: <FileText className="w-5 h-5 text-sky-600" />, tooltip: "Reçue" };
  }
  if (s.includes('en cours') || s.includes('encours')) {
    return { icon: <Clock className="w-5 h-5 text-amber-600" />, tooltip: "En cours" };
  }
  if (s.includes('traitee') || s.includes('traitée')) {
    return { icon: <CheckCircle className="w-5 h-5 text-emerald-600" />, tooltip: "Traitée" };
  }
  if (s.includes('annulee') || s.includes('annulée')) {
    return { icon: <XCircle className="w-5 h-5 text-rose-600" />, tooltip: "Annulée" };
  }
  return { icon: <span className="text-slate-400">—</span>, tooltip: "Non défini" };
}

function getEtatPaieIcon(etat: string | null | undefined): { icon: React.ReactNode; tooltip: string } {
  const s = String(etat || "").toLowerCase();
  if (s.includes('à traiter') || s.includes('a traiter') || s.includes('traiter')) {
    return { icon: <AlertCircle className="w-5 h-5 text-orange-600" />, tooltip: "À traiter" };
  }
  if (s.includes('en cours') || s.includes('en_cours') || s.includes('encours') || s.includes('cours')) {
    return { icon: <Clock className="w-5 h-5 text-blue-600" />, tooltip: "En cours" };
  }
  if (s.includes('traitée') || s.includes('traitee') || s.includes('traite')) {
    return { icon: <CheckCircle className="w-5 h-5 text-green-600" />, tooltip: "Traitée" };
  }
  return { icon: <span className="text-slate-400">—</span>, tooltip: "Non défini" };
}

function getDpaeIcon(dpae: string | null | undefined): { icon: React.ReactNode; tooltip: string } {
  const d = String(dpae || "").toLowerCase();
  if (d.includes('à faire') || d.includes('a faire')) {
    return { icon: <AlertCircle className="w-5 h-5 text-orange-600" />, tooltip: "À faire" };
  }
  if (d.includes('en cours') || d.includes('encours')) {
    return { icon: <Clock className="w-5 h-5 text-blue-600" />, tooltip: "En cours" };
  }
  if (d.includes('faite') || d.includes('validée') || d.includes('validee')) {
    return { icon: <CheckCircle className="w-5 h-5 text-green-600" />, tooltip: "Faite" };
  }
  return { icon: <span className="text-slate-400">—</span>, tooltip: "Non défini" };
}

type Contract = {
  id: string;
  contract_number?: string | null;
  employee_name?: string | null;
  employee_id?: string | null;
  structure?: string | null;
  type_de_contrat?: string | null;
  profession?: string | null;
  start_date?: string | null;
  end_date?: string | null;
  created_at?: string | null;
  etat_demande?: string | null;
  etat_de_la_demande?: string | null;
  etat_de_la_paie?: string | null;
  dpae?: string | null;
  gross_pay?: number | null;
  org_id?: string | null;
  contrat_signe_par_employeur?: string | null;
  contrat_signe?: string | null;
  last_employer_notification_at?: string | null;
  last_employee_notification_at?: string | null;
  production_name?: string | null;
  analytique?: string | null;
  nombre_d_heures?: number | null;
  n_objet?: string | null;
  objet_spectacle?: string | null;
  type_salaire?: string | null;
  salaries?: {
    salarie?: string | null;
    nom?: string | null;
    prenom?: string | null;
    adresse_mail?: string | null;
    code_salarie?: string | null;
  } | null;
  organizations?: {
    organization_details?: {
      code_employeur?: string | null;
    } | null;
  } | null;
};

type NotificationInfo = {
  employerLastSent: string | null;
  employeeLastSent: string | null;
};

type ContractProgress = {
  id: string;
  contractNumber?: string;
  employeeName?: string;
  status: 'pending' | 'processing' | 'success' | 'error';
  error?: string;
  filename?: string;
};

type ContractPdf = {
  id: string;
  contractNumber?: string;
  employeeName?: string;
  pdfUrl?: string;
  hasError: boolean;
  errorMessage?: string;
};

export type ContractsGridHandle = {
  quickFilterDpaeAFaire: () => void;
  quickFilterContratsAFaireMois: () => void;
  quickFilterPaieATraiterMoisDernier: () => void;
  quickFilterPaieATraiterToutes: () => void;
  quickFilterNonSignesDateProche: () => void;
  quickFilterContratsEnCours: () => void;
  quickFilterMultiMois: () => void;
  getCountDpaeAFaire: () => number | null;
  getCountContratsAFaireMois: () => number | null;
  getCountPaieATraiterMoisDernier: () => number | null;
  getCountPaieATraiterToutes: () => number | null;
  getCountNonSignesDateProche: () => number | null;
  getCountMultiMois: () => number | null;
};

type ContractsGridProps = {
  initialData: Contract[];
  activeOrgId?: string | null;
  onFiltersReset?: () => void;
};

function ContractsGridImpl({ initialData, activeOrgId, onFiltersReset }: ContractsGridProps, ref: React.ForwardedRef<ContractsGridHandle>) {
  const [rows, setRows] = useState<Contract[]>(initialData || []);
  const [showRaw, setShowRaw] = useState(false);
  const [loading, setLoading] = useState(false);
  
  // Selection state
  const [selectedContractIds, setSelectedContractIds] = useState<Set<string>>(new Set());
  
  // Notification tracking state
  const [notificationMap, setNotificationMap] = useState<Map<string, NotificationInfo>>(new Map());
  
  // Key for localStorage
  const FILTERS_STORAGE_KEY = 'staff-contracts-filters';
  
  // Helper functions for localStorage
  const saveFiltersToStorage = (filters: any) => {
    try {
      localStorage.setItem(FILTERS_STORAGE_KEY, JSON.stringify(filters));
    } catch (error) {
      console.warn('Failed to save filters to localStorage:', error);
    }
  };
  
  const loadFiltersFromStorage = () => {
    try {
      const saved = localStorage.getItem(FILTERS_STORAGE_KEY);
      return saved ? JSON.parse(saved) : null;
    } catch (error) {
      console.warn('Failed to load filters from localStorage:', error);
      return null;
    }
  };

  // Load saved filters or use defaults
  const savedFilters = loadFiltersFromStorage();
  
  // filters / sorting / pagination - with localStorage persistence
  const [q, setQ] = useState(savedFilters?.q || "");
  const [structureFilter, setStructureFilter] = useState<string | null>(savedFilters?.structureFilter || null);
  const [typeFilter, setTypeFilter] = useState<string | null>(savedFilters?.typeFilter || null);
  const [productionFilter, setProductionFilter] = useState<string | null>(savedFilters?.productionFilter || null);
  const [etatContratFilters, setEtatContratFilters] = useState<Set<string>>(new Set(savedFilters?.etatContratFilters || []));
  const [etatPaieFilter, setEtatPaieFilter] = useState<string | null>(savedFilters?.etatPaieFilter || null);
  const [dpaeFilter, setDpaeFilter] = useState<string | null>(savedFilters?.dpaeFilter || null);
  const [signatureFilter, setSignatureFilter] = useState<string | null>(savedFilters?.signatureFilter || null);
  const [multiMoisFilter, setMultiMoisFilter] = useState<boolean>(savedFilters?.multiMoisFilter || false);
  const [startFrom, setStartFrom] = useState<string | null>(savedFilters?.startFrom || null);
  const [startTo, setStartTo] = useState<string | null>(savedFilters?.startTo || null);
  const [endFrom, setEndFrom] = useState<string | null>(savedFilters?.endFrom || null);
  const [endTo, setEndTo] = useState<string | null>(savedFilters?.endTo || null);
  const [sortField, setSortField] = useState<string>(savedFilters?.sortField || "start_date");
  const [sortOrder, setSortOrder] = useState<'asc'|'desc'>(savedFilters?.sortOrder || 'desc');
  const [page, setPage] = useState(0);
  const [limit, setLimit] = useState(10000); // Limite élevée pour récupérer tous les contrats
  const [showFilters, setShowFilters] = useState(savedFilters?.showFilters || false);
  const totalCountRef = useRef<number | null>(null);
  const [selectedId, setSelectedId] = useState<string | null>(null);

  // Selection helpers
  const selectedContracts = rows.filter(contract => selectedContractIds.has(contract.id));
  const isAllSelected = rows.length > 0 && selectedContractIds.size === rows.length;
  const isPartiallySelected = selectedContractIds.size > 0 && selectedContractIds.size < rows.length;

  // Modal states
  const [showDpaeModal, setShowDpaeModal] = useState(false);
  const [showEtatContratModal, setShowEtatContratModal] = useState(false);
  const [showEtatPaieModal, setShowEtatPaieModal] = useState(false);
  const [showAnalytiqueModal, setShowAnalytiqueModal] = useState(false);
  const [showSalaryModal, setShowSalaryModal] = useState(false);
  const [showActionMenu, setShowActionMenu] = useState(false);
  const [showESignMenu, setShowESignMenu] = useState(false);
  const [showDeleteModal, setShowDeleteModal] = useState(false);
  const [showBulkPayslipModal, setShowBulkPayslipModal] = useState(false);
  const [showJoursTechnicienModal, setShowJoursTechnicienModal] = useState(false);
  const [showSignatureDateModal, setShowSignatureDateModal] = useState(false);
  
  // Quick filter counts
  const [countDpaeAFaire, setCountDpaeAFaire] = useState<number | null>(null);
  const [countContratsAFaireMois, setCountContratsAFaireMois] = useState<number | null>(null);
  const [countPaieATraiterMoisDernier, setCountPaieATraiterMoisDernier] = useState<number | null>(null);
  const [countPaieATraiterToutes, setCountPaieATraiterToutes] = useState<number | null>(null);
  const [countContratsNonSignesDateProche, setCountContratsNonSignesDateProche] = useState<number | null>(null);
  const [countMultiMois, setCountMultiMois] = useState<number | null>(null);
  
  // PDF generation state
  const [isGeneratingPdfs, setIsGeneratingPdfs] = useState(false);
  const [showProgressModal, setShowProgressModal] = useState(false);
  const [contractsProgress, setContractsProgress] = useState<ContractProgress[]>([]);
  const [isCancelled, setIsCancelled] = useState(false);
  
  // PDF verification state
  const [showPdfVerificationModal, setShowPdfVerificationModal] = useState(false);
  const [contractsPdfs, setContractsPdfs] = useState<ContractPdf[]>([]);
  const [isLoadingPdfs, setIsLoadingPdfs] = useState(false);

  // E-Sign state
  const [isGeneratingESign, setIsGeneratingESign] = useState(false);
  const [showESignConfirmModal, setShowESignConfirmModal] = useState(false);
  const [showESignProgressModal, setShowESignProgressModal] = useState(false);
  const [contractsESignProgress, setContractsESignProgress] = useState<ContractProgress[]>([]);
  const [isESignCancelled, setIsESignCancelled] = useState(false);

  // Contract Details Modal state
  const [showDetailsModal, setShowDetailsModal] = useState(false);
  const [contractDetailsIds, setContractDetailsIds] = useState<string[]>([]);

  // Employee Reminder state
  const [showEmployeeReminderModal, setShowEmployeeReminderModal] = useState(false);
  const [selectedContractForReminder, setSelectedContractForReminder] = useState<any>(null);
  const [isLoadingReminder, setIsLoadingReminder] = useState(false);
  // Bulk reminder modal state
  const [showBulkReminderModal, setShowBulkReminderModal] = useState(false);
  const [bulkReminderContracts, setBulkReminderContracts] = useState<Array<{ id: string; reference?: string | null; contract_number?: string | null; employee_name?: string | null; employee_email?: string | null }>>([]);
  const [isLoadingReminderEmails, setIsLoadingReminderEmails] = useState(false);
  // Smart reminder modal state
  const [showSmartReminderModal, setShowSmartReminderModal] = useState(false);
  const [smartReminderContracts, setSmartReminderContracts] = useState<SmartReminderContract[]>([]);
  const [smartReminderProgress, setSmartReminderProgress] = useState<SmartReminderContract[]>([]);

  // Quick filters helpers
  const toYMD = (d: Date) => {
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    return `${y}-${m}-${day}`;
  };
  const applyQuickFilterDpaeAFaire = () => {
    const today = new Date();
    const in7 = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
    // Reset tous les filtres pour voir uniquement ce filtre rapide
    setQ(""); // Reset recherche
    setStructureFilter(null); // Reset organisation
    setTypeFilter(null); // Reset type de contrat
    setProductionFilter(null); // Reset production
    setSignatureFilter(null); // Reset signature
    setDpaeFilter('À faire');
    setEtatContratFilters(new Set()); // Reset état contrat
    setEtatPaieFilter(null); // Reset état paie
    setStartFrom(null); // inclut le passé
    setStartTo(toYMD(in7)); // jusqu'à J+7
    setEndFrom(null);
    setEndTo(null);
    setSortField('start_date');
    setSortOrder('asc');
  };

  const applyQuickFilterContratsAFaireMois = () => {
    const today = new Date();
    const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
    const lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);
    // Reset tous les filtres pour voir uniquement ce filtre rapide
    setQ(""); // Reset recherche
    setStructureFilter(null); // Reset organisation
    setTypeFilter(null); // Reset type de contrat
    setProductionFilter(null); // Reset production
    setSignatureFilter(null); // Reset signature
    setEtatContratFilters(new Set(['Reçue', 'En cours'])); // Multiple selections
    setDpaeFilter(null); // Reset DPAE
    setEtatPaieFilter(null); // Reset état paie
    setStartFrom(toYMD(firstDay));
    setStartTo(toYMD(lastDay));
    setEndFrom(null);
    setEndTo(null);
    setSortField('start_date');
    setSortOrder('asc');
  };

  const applyQuickFilterPaieATraiterMoisDernier = () => {
    const today = new Date();
    // Premier jour du mois courant
    const firstDayThisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
    // Avant le premier jour du mois courant = fin du mois dernier
    const lastDayLastMonth = new Date(firstDayThisMonth.getFullYear(), firstDayThisMonth.getMonth(), 0);
    // Premier jour du mois dernier
    const firstDayLastMonth = new Date(lastDayLastMonth.getFullYear(), lastDayLastMonth.getMonth(), 1);
    
    // Reset tous les filtres pour voir uniquement ce filtre rapide
    setQ(""); // Reset recherche
    setStructureFilter(null); // Reset organisation
    setTypeFilter(null); // Reset type de contrat
    setProductionFilter(null); // Reset production
    setSignatureFilter(null); // Reset signature
    setEtatPaieFilter('À traiter');
    setDpaeFilter(null); // Reset DPAE
    setEtatContratFilters(new Set()); // Reset état contrat
    // Fin du contrat doit être dans le mois dernier (du 1er au dernier jour)
    setStartFrom(null);
    setStartTo(null);
    setEndFrom(toYMD(firstDayLastMonth));
    setEndTo(toYMD(lastDayLastMonth));
    setSortField('end_date');
    setSortOrder('asc');
  };

  const applyQuickFilterPaieATraiterToutes = () => {
    // Reset tous les filtres pour voir uniquement ce filtre rapide
    setQ(""); // Reset recherche
    setStructureFilter(null); // Reset organisation
    setTypeFilter(null); // Reset type de contrat
    setProductionFilter(null); // Reset production
    setSignatureFilter(null); // Reset signature
    setEtatPaieFilter('À traiter');
    setDpaeFilter(null); // Reset DPAE
    setEtatContratFilters(new Set(['Traitée'])); // Ajouter le filtre "Traitée"
    // Date de fin aujourd'hui ou passée
    const today = new Date();
    const y = today.getFullYear();
    const m = String(today.getMonth() + 1).padStart(2, '0');
    const day = String(today.getDate()).padStart(2, '0');
    const todayStr = `${y}-${m}-${day}`;
    setStartFrom(null);
    setStartTo(null);
    setEndFrom(null);
    setEndTo(todayStr);
    setSortField('end_date');
    setSortOrder('asc');
  };

  const applyQuickFilterNonSignesDateProche = () => {
    // Contrats non signés avec date de début dans le passé, aujourd'hui ou demain
    const today = new Date();
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);
    
    // Reset tous les filtres pour voir uniquement ce filtre rapide
    setQ(""); // Reset recherche
    setStructureFilter(null); // Reset organisation
    setTypeFilter(null); // Reset type de contrat
    setProductionFilter(null); // Reset production
    setSignatureFilter('non_signe'); // Filtre pour les contrats non complètement signés
    setEtatPaieFilter(null); // Reset état paie
    setEtatContratFilters(new Set()); // Reset état contrat
    setDpaeFilter(null); // Reset DPAE
    setStartFrom(null); // Inclut le passé
    setStartTo(toYMD(tomorrow)); // Jusqu'à demain
    setEndFrom(null);
    setEndTo(null);
    setSortField('start_date');
    setSortOrder('asc');
  };

  const applyQuickFilterContratsEnCours = () => {
    // Contrats en cours : date de début passée et date de fin future
    const today = new Date();
    const todayStr = toYMD(today);
    
    // Reset tous les filtres pour voir uniquement ce filtre rapide
    setQ(""); // Reset recherche
    setStructureFilter(null); // Reset organisation
    setTypeFilter(null); // Reset type de contrat
    setProductionFilter(null); // Reset production
    setSignatureFilter(null); // Tous les contrats
    setEtatPaieFilter(null); // Reset état paie
    setEtatContratFilters(new Set()); // Reset état contrat
    setDpaeFilter(null); // Reset DPAE
    setStartFrom(null); // Date de début dans le passé
    setStartTo(todayStr); // Jusqu'à aujourd'hui
    setEndFrom(todayStr); // Date de fin future (à partir d'aujourd'hui)
    setEndTo(null);
    setSortField('end_date');
    setSortOrder('asc');
  };

  const applyQuickFilterMultiMois = () => {
    // Contrats multi-mois : CDDU dont la date de début et la date de fin ne sont pas sur le même mois calendaire
    // Reset tous les filtres pour voir uniquement ce filtre rapide
    setQ(""); // Reset recherche
    setStructureFilter(null); // Reset organisation
    setTypeFilter('CDDU'); // Uniquement les CDDU
    setProductionFilter(null); // Reset production
    setSignatureFilter(null); // Tous les contrats
    setEtatPaieFilter(null); // Reset état paie
    setEtatContratFilters(new Set()); // Reset état contrat
    setDpaeFilter(null); // Reset DPAE
    setMultiMoisFilter(true); // Activer le filtre multi-mois
    setStartFrom(null);
    setStartTo(null);
    setEndFrom(null);
    setEndTo(null);
    setSortField('start_date');
    setSortOrder('desc');
  };

  // Expose imperative handlers to parent wrappers
  useImperativeHandle(ref, () => ({
    quickFilterDpaeAFaire: applyQuickFilterDpaeAFaire,
    quickFilterContratsAFaireMois: applyQuickFilterContratsAFaireMois,
    quickFilterPaieATraiterMoisDernier: applyQuickFilterPaieATraiterMoisDernier,
    quickFilterPaieATraiterToutes: applyQuickFilterPaieATraiterToutes,
    quickFilterNonSignesDateProche: applyQuickFilterNonSignesDateProche,
    quickFilterContratsEnCours: applyQuickFilterContratsEnCours,
    quickFilterMultiMois: applyQuickFilterMultiMois,
    getCountDpaeAFaire: () => countDpaeAFaire,
    getCountContratsAFaireMois: () => countContratsAFaireMois,
    getCountPaieATraiterMoisDernier: () => countPaieATraiterMoisDernier,
    getCountPaieATraiterToutes: () => countPaieATraiterToutes,
    getCountNonSignesDateProche: () => countContratsNonSignesDateProche,
    getCountMultiMois: () => countMultiMois,
  }), [applyQuickFilterDpaeAFaire, applyQuickFilterContratsAFaireMois, applyQuickFilterPaieATraiterMoisDernier, applyQuickFilterPaieATraiterToutes, applyQuickFilterNonSignesDateProche, applyQuickFilterContratsEnCours, applyQuickFilterMultiMois, countDpaeAFaire, countContratsAFaireMois, countPaieATraiterMoisDernier, countPaieATraiterToutes, countContratsNonSignesDateProche, countMultiMois]);

  // Save filters to localStorage whenever they change
  useEffect(() => {
    const filters = {
      q,
      structureFilter,
      typeFilter,
      productionFilter,
      etatContratFilters: Array.from(etatContratFilters),
      etatPaieFilter,
      dpaeFilter,
      signatureFilter,
      multiMoisFilter,
      startFrom,
      startTo,
      endFrom,
      endTo,
      sortField,
      sortOrder,
      showFilters
    };
    saveFiltersToStorage(filters);
  }, [q, structureFilter, typeFilter, productionFilter, etatContratFilters, etatPaieFilter, dpaeFilter, signatureFilter, multiMoisFilter, startFrom, startTo, endFrom, endTo, sortField, sortOrder, showFilters]);

  // Réinitialiser le filtre de production quand la structure change
  useEffect(() => {
    // Si une structure est sélectionnée et que le filtre de production actuel n'existe pas dans la nouvelle liste
    if (structureFilter && productionFilter) {
      const availableProductions = (initialData || [])
        .filter(r => r.structure === structureFilter)
        .map(r => r.production_name)
        .filter(Boolean);
      
      if (!availableProductions.includes(productionFilter)) {
        setProductionFilter(null);
      }
    }
    // Si aucune structure n'est sélectionnée, réinitialiser le filtre de production
    if (!structureFilter && productionFilter) {
      setProductionFilter(null);
    }
  }, [structureFilter, initialData, productionFilter]);

  // optimistic update helper
  const selectedRow = useMemo(() => rows.find((r) => r.id === selectedId) ?? null, [rows, selectedId]);

  // Realtime subscription: listen to INSERT / UPDATE / DELETE on contracts
  useEffect(() => {
    // Debug: log incoming initialData when component mounts/hydrates
    try {
      console.log("ContractsGrid initialData (client):", Array.isArray(initialData) ? initialData.length : typeof initialData, initialData?.slice?.(0, 5));
    } catch (err) {
      console.log("ContractsGrid initialData (client) - could not log:", err);
    }

    let channel: any = null;
    let mounted = true;

    (async () => {
      try {
  channel = supabase.channel("public:cddu_contracts");
        channel.on(
          "postgres_changes",
          { event: "*", schema: "public", table: "cddu_contracts" },
          (payload: any) => {
            try {
              const event = payload.event || payload.eventType || payload.type;
              const record = payload.new ?? payload.record ?? payload.payload ?? payload;

              if (event === "INSERT") {
                const newRec = record as Contract;
                setRows((rs) => {
                  if (rs.find((r) => r.id === newRec.id)) return rs;
                  return [newRec, ...rs];
                });
              } else if (event === "UPDATE") {
                setRows((rs) => rs.map((r) => (r.id === record.id ? { ...r, ...(record as Contract) } : r)));
              } else if (event === "DELETE") {
                const id = record?.id ?? payload.old?.id;
                if (id) setRows((rs) => rs.filter((r) => r.id !== id));
              }
            } catch (err) {
              console.error("Realtime handler error", err);
            }
          }
        );

        // subscribe and await result (some SDKs return a promise)
        const sub = await channel.subscribe();
        // If subscribe returned an object with error info, warn and stop
        if (!mounted) return;
        if (sub && (sub.status === "timed_out" || sub.status === "closed" || sub?.error)) {
          console.warn("Realtime subscribe returned unexpected status", sub);
        }
      } catch (err: any) {
  // Common cause: table not published for realtime / not in schema cache
  console.warn("Realtime subscription failed for public.cddu_contracts — falling back to polling.", err?.message ?? err);
      }
    })();

    return () => {
      mounted = false;
      try {
        if (channel) {
          // supabase.removeChannel exists in v2
          // @ts-ignore
          if (supabase.removeChannel) supabase.removeChannel(channel);
          else channel.unsubscribe && channel.unsubscribe();
        }
      } catch (err) {
        console.warn("Error unsubscribing realtime channel", err);
      }
    };
  }, []);

  // Fetch server-side data if filters are active on mount
  useEffect(() => {
    const hasActiveFilters = q || structureFilter || typeFilter || etatContratFilters.size > 0 || etatPaieFilter || dpaeFilter || signatureFilter || startFrom || startTo || endFrom || endTo;
    
    if (hasActiveFilters) {
      // Si des filtres sont actifs au chargement (depuis localStorage), fetch les données filtrées
      fetchServer(0);
    }
  }, []); // eslint-disable-line react-hooks/exhaustive-deps
  // Note: On veut que cela s'exécute uniquement au montage, pas quand les filtres changent

  // Helper: count contracts for a specific filter
  async function countContractsForFilter(filterParams: URLSearchParams) {
    try {
      const res = await fetch(`/api/staff/contracts/search?${filterParams.toString()}`);
      if (!res.ok) throw new Error('Count failed');
      const j = await res.json();
      return j.count ?? 0;
    } catch (err) {
      console.error('Count error', err);
      return 0;
    }
  }

  // Helper: fetch server-side with current filters
  async function fetchServer(pageIndex = 0) {
    setLoading(true);
    try {
      const params = new URLSearchParams();
      if (q) params.set('q', q);
      if (structureFilter) params.set('structure', structureFilter);
      if (typeFilter) params.set('type_de_contrat', typeFilter);
      if (productionFilter) params.set('production_name', productionFilter);
      // Handle multiple etat_de_la_demande filters
      if (etatContratFilters.size > 0) {
        params.set('etat_de_la_demande', Array.from(etatContratFilters).join(','));
      }
      if (etatPaieFilter) params.set('etat_de_la_paie', etatPaieFilter);
      if (dpaeFilter) params.set('dpae', dpaeFilter);
      if (signatureFilter) params.set('signature_state', signatureFilter);
      if (startFrom) params.set('start_from', startFrom);
      if (startTo) params.set('start_to', startTo);
      if (endFrom) params.set('end_from', endFrom);
      if (endTo) params.set('end_to', endTo);
      params.set('sort', sortField);
      params.set('order', sortOrder === 'asc' ? 'asc' : 'desc');
      params.set('limit', String(limit));
      params.set('offset', String(pageIndex * limit));

      const res = await fetch(`/api/staff/contracts/search?${params.toString()}`);
      if (!res.ok) throw new Error('Search failed');
      const j = await res.json();
      totalCountRef.current = j.count ?? (j.rows ? j.rows.length : 0);
      setRows(j.rows ?? []);
      setPage(pageIndex);
    } catch (err) {
      console.error('Search error', err);
    } finally {
      setLoading(false);
    }
  }

  // Manual refresh function for the refresh button
  const handleRefresh = () => {
    fetchServer(0);
  };

  // Note: Removed auto-reset of selection when data changes to preserve selection after bulk actions

  // Client-side sorting function
  const sortContractsLocally = (contracts: Contract[], field: string, order: 'asc' | 'desc'): Contract[] => {
    return [...contracts].sort((a, b) => {
      let valueA: any;
      let valueB: any;

      switch (field) {
        case 'employee_name':
          // Tri par nom de famille
          valueA = getLastName(a);
          valueB = getLastName(b);
          break;
        case 'production_name':
          valueA = a.production_name || '';
          valueB = b.production_name || '';
          break;
        case 'code_employeur':
          valueA = a.organizations?.organization_details?.code_employeur || '';
          valueB = b.organizations?.organization_details?.code_employeur || '';
          break;
        case 'start_date':
        case 'end_date':
        case 'created_at':
          valueA = a[field as keyof Contract] ? new Date(a[field as keyof Contract] as string) : new Date(0);
          valueB = b[field as keyof Contract] ? new Date(b[field as keyof Contract] as string) : new Date(0);
          break;
        default:
          valueA = a[field as keyof Contract] || '';
          valueB = b[field as keyof Contract] || '';
      }

      if (typeof valueA === 'string') valueA = valueA.toLowerCase();
      if (typeof valueB === 'string') valueB = valueB.toLowerCase();

      if (valueA < valueB) return order === 'asc' ? -1 : 1;
      if (valueA > valueB) return order === 'asc' ? 1 : -1;
      return 0;
    });
  };

  // Apply local sorting when using initial data
  const sortedRows = useMemo(() => {
    const noFilters = !q && !structureFilter && !typeFilter && !productionFilter && etatContratFilters.size === 0 && !etatPaieFilter && !dpaeFilter && !signatureFilter && !startFrom && !startTo && !endFrom && !endTo && !multiMoisFilter;
    
    let filteredRows = rows;
    
    // Appliquer le filtre multi-mois côté client si activé
    if (multiMoisFilter) {
      filteredRows = rows.filter(contract => {
        if (!contract.start_date || !contract.end_date) return false;
        
        const startDate = new Date(contract.start_date);
        const endDate = new Date(contract.end_date);
        
        // Vérifier si les mois ou les années sont différents
        return startDate.getMonth() !== endDate.getMonth() || 
               startDate.getFullYear() !== endDate.getFullYear();
      });
    }
    
    if (noFilters) {
      // Utiliser le tri local pour les données initiales
      return sortContractsLocally(filteredRows, sortField, sortOrder);
    }
    
    // Pour les données filtrées, utiliser les données telles qu'elles viennent du serveur
    // mais appliquer le tri local car nous avons potentiellement filtré côté client
    if (multiMoisFilter) {
      return sortContractsLocally(filteredRows, sortField, sortOrder);
    }
    
    return filteredRows;
  }, [rows, sortField, sortOrder, q, structureFilter, typeFilter, productionFilter, etatContratFilters, etatPaieFilter, dpaeFilter, signatureFilter, startFrom, startTo, endFrom, endTo, multiMoisFilter]);

  // Selection functions (updated to use sortedRows for selection)
  const toggleSelectAll = () => {
    if (isAllSelected) {
      setSelectedContractIds(new Set());
    } else {
      setSelectedContractIds(new Set(sortedRows.map(r => r.id)));
    }
  };

  const toggleSelectContract = (contractId: string) => {
    setSelectedContractIds(prev => {
      const newSet = new Set(prev);
      if (newSet.has(contractId)) {
        newSet.delete(contractId);
      } else {
        newSet.add(contractId);
      }
      return newSet;
    });
  };

  // Function to generate PDFs for selected contracts individually
  const generateBatchPdfs = async () => {
    if (selectedContractIds.size === 0) {
      toast.error("Aucun contrat sélectionné");
      return;
    }

    const contractIds = Array.from(selectedContractIds);
    
    // Initialiser les contrats avec leurs informations
    const initialProgress: ContractProgress[] = contractIds.map(id => {
      const contract = rows.find(r => r.id === id);
      return {
        id,
        contractNumber: contract?.contract_number || undefined,
        employeeName: contract?.employee_name || undefined,
        status: 'pending' as const
      };
    });

    // Ouvrir le modal et initialiser les états
    setContractsProgress(initialProgress);
    setShowProgressModal(true);
    setIsGeneratingPdfs(true);
    setIsCancelled(false);

    let successCount = 0;
    let errorCount = 0;

    try {
      // Traiter chaque contrat individuellement
      for (let i = 0; i < contractIds.length; i++) {
        if (isCancelled) {
          // Si annulé, marquer tous les contrats restants comme "en attente"
          break;
        }

        const contractId = contractIds[i];
        
        // Marquer le contrat comme "en cours"
        setContractsProgress(prev => 
          prev.map(c => 
            c.id === contractId 
              ? { ...c, status: 'processing' as const }
              : c
          )
        );

        try {
          // Appeler l'endpoint individuel existant
          const response = await fetch(`/api/contrats/${contractId}/generate-pdf`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
          });

          if (response.ok) {
            const result = await response.json();
            successCount++;
            
            // Marquer comme succès
            setContractsProgress(prev => 
              prev.map(c => 
                c.id === contractId 
                  ? { 
                      ...c, 
                      status: 'success' as const,
                      filename: result.filename 
                    }
                  : c
              )
            );
          } else {
            const errorData = await response.json();
            errorCount++;
            
            // Marquer comme erreur
            setContractsProgress(prev => 
              prev.map(c => 
                c.id === contractId 
                  ? { 
                      ...c, 
                      status: 'error' as const,
                      error: errorData.error || `Erreur ${response.status}`
                    }
                  : c
              )
            );
          }
        } catch (error) {
          errorCount++;
          
          // Marquer comme erreur
          setContractsProgress(prev => 
            prev.map(c => 
              c.id === contractId 
                ? { 
                    ...c, 
                    status: 'error' as const,
                    error: error instanceof Error ? error.message : 'Erreur de réseau'
                  }
                : c
            )
          );
        }

        // Petit délai entre chaque contrat pour éviter la surcharge
        if (i < contractIds.length - 1 && !isCancelled) {
          await new Promise(resolve => setTimeout(resolve, 500));
        }
      }

      // Message final si non annulé
      if (!isCancelled) {
        if (successCount > 0) {
          toast.success(`${successCount} PDF${successCount > 1 ? 's' : ''} créé${successCount > 1 ? 's' : ''} avec succès !`);
        }
        if (errorCount > 0) {
          toast.error(`${errorCount} erreur${errorCount > 1 ? 's' : ''} lors de la génération`);
        }
        
        // Déselectionner les contrats
        setSelectedContractIds(new Set());
        
        // Rafraîchir après un délai
        setTimeout(() => {
          window.location.reload();
        }, 3000);
      }

    } catch (error) {
      console.error("Erreur lors de la génération des PDFs:", error);
      toast.error("Erreur lors de la génération des PDFs");
    } finally {
      setIsGeneratingPdfs(false);
    }
  };

  // Fonction pour annuler la génération
  const cancelPdfGeneration = () => {
    setIsCancelled(true);
    setIsGeneratingPdfs(false);
    toast.info("Génération annulée");
  };

  // Fonction pour fermer le modal
  const closeProgressModal = () => {
    setShowProgressModal(false);
    setContractsProgress([]);
    setIsCancelled(false);
  };

  // Fonction pour vérifier les PDFs des contrats sélectionnés
  const verifySelectedPdfs = async () => {
    if (selectedContractIds.size === 0) {
      toast.error("Aucun contrat sélectionné");
      return;
    }

    const contractIds = Array.from(selectedContractIds);
    
    // Ouvrir le modal et commencer le chargement
    setShowPdfVerificationModal(true);
    setIsLoadingPdfs(true);
    setContractsPdfs([]);

    try {
      // Récupérer les URLs des PDFs pour chaque contrat
      const pdfPromises = contractIds.map(async (contractId) => {
        const contract = rows.find(r => r.id === contractId);
        
        try {
          const response = await fetch(`/api/contrats/${contractId}/pdf-url`);
          
          if (response.ok) {
            const result = await response.json();
            return {
              id: contractId,
              contractNumber: contract?.contract_number || undefined,
              employeeName: contract?.employee_name || undefined,
              pdfUrl: result.pdfUrl,
              hasError: false
            } as ContractPdf;
          } else {
            const errorData = await response.json();
            return {
              id: contractId,
              contractNumber: contract?.contract_number || undefined,
              employeeName: contract?.employee_name || undefined,
              pdfUrl: undefined,
              hasError: true,
              errorMessage: errorData.error || 'PDF non trouvé'
            } as ContractPdf;
          }
        } catch (error) {
          return {
            id: contractId,
            contractNumber: contract?.contract_number || undefined,
            employeeName: contract?.employee_name || undefined,
            pdfUrl: undefined,
            hasError: true,
            errorMessage: 'Erreur de réseau'
          } as ContractPdf;
        }
      });

      const pdfs = await Promise.all(pdfPromises);
      setContractsPdfs(pdfs);
      
      const successCount = pdfs.filter(pdf => !pdf.hasError).length;
      const errorCount = pdfs.filter(pdf => pdf.hasError).length;
      
      if (successCount > 0) {
        toast.success(`${successCount} PDF${successCount > 1 ? 's' : ''} chargé${successCount > 1 ? 's' : ''}`);
      }
      if (errorCount > 0) {
        toast.warning(`${errorCount} PDF${errorCount > 1 ? 's' : ''} non disponible${errorCount > 1 ? 's' : ''}`);
      }

    } catch (error) {
      console.error("Erreur lors du chargement des PDFs:", error);
      toast.error("Erreur lors du chargement des PDFs");
    } finally {
      setIsLoadingPdfs(false);
    }
  };

  // Fonction pour fermer le modal de vérification PDF
  const closePdfVerificationModal = () => {
    setShowPdfVerificationModal(false);
    setContractsPdfs([]);
    setIsLoadingPdfs(false);
  };

  // Fonction pour ouvrir le modal de détails des contrats
  const viewSelectedDetails = () => {
    if (selectedContractIds.size === 0) {
      toast.error("Aucun contrat sélectionné");
      return;
    }

    const contractIds = Array.from(selectedContractIds);
    setContractDetailsIds(contractIds);
    setShowDetailsModal(true);
    setShowActionMenu(false);
  };

  // Fonction pour exporter les contrats sélectionnés en TSV (format sPAIEctacle)
  const exportSelectedToTSV = async () => {
    if (selectedContractIds.size === 0) {
      toast.error("Aucun contrat sélectionné");
      return;
    }

    const selectedRows = rows.filter(contract => selectedContractIds.has(contract.id));
    
    // Charger les fichiers JSON de professions pour la correspondance
    let professionsMap = new Map<string, string>();
    try {
      const [artistesRes, techniciensRes] = await Promise.all([
        fetch('/data/professions-feminisations.json'),
        fetch('/data/professions-techniciens.json')
      ]);
      
      const artistes = await artistesRes.json();
      const techniciens = await techniciensRes.json();
      
      // Construire une map label -> code pour les artistes
      artistes.forEach((prof: any) => {
        if (prof.profession_label && prof.profession_code) {
          professionsMap.set(prof.profession_label.toLowerCase(), prof.profession_code);
        }
        if (prof.profession_feminine && prof.profession_code) {
          professionsMap.set(prof.profession_feminine.toLowerCase(), prof.profession_code);
        }
      });
      
      // Construire une map label -> code pour les techniciens
      techniciens.forEach((prof: any) => {
        if (prof.label && prof.code) {
          professionsMap.set(prof.label.toLowerCase(), prof.code);
        }
      });
    } catch (error) {
      console.error("Erreur lors du chargement des professions:", error);
      toast.error("Erreur lors du chargement des professions");
      return;
    }
    
    // En-têtes TSV (format sPAIEctacle)
    const headers = [
      "Code societe",
      "Code contrat",
      "Matricule",
      "Categorie salariale",
      "Code profession",
      "Type de contrat",
      "Debut de contrat",
      "Fin de contrat",
      "Code rubrique",
      "Quantite rubrique",
      "Base rubrique",
      "Cout employeur",
      "Compte analytique",
      "Compte analytique multiple",
      "Repartition analytique multiple",
      "Numero d'objet",
      "Date travaillee debut",
      "Date travaillee fin",
      "Contrat"
    ];

    // Fonction pour formater une date en DD/MM/YYYY
    const formatDateForTSV = (dateString: string | null | undefined): string => {
      if (!dateString) return "";
      try {
        const date = new Date(dateString);
        const day = String(date.getDate()).padStart(2, '0');
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const year = date.getFullYear();
        return `${day}/${month}/${year}`;
      } catch {
        return "";
      }
    };

    // Fonction pour obtenir le code profession depuis le label
    const getProfessionCode = (professionLabel: string | null | undefined): string => {
      if (!professionLabel) return "";
      const code = professionsMap.get(professionLabel.toLowerCase());
      return code || "";
    };

    // Construire les lignes de données
    const dataRows = selectedRows.map(contract => {
      const codeEmployeur = contract.organizations?.organization_details?.code_employeur || "";
      const contractNumber = contract.contract_number || "";
      const matricule = contract.salaries?.code_salarie || contract.employee_id || "";
      const categorieSalariale = "Cas General"; // Fixe
      const codeProfession = getProfessionCode(contract.profession);
      const typeContrat = "Intermittent"; // Fixe pour CDDU
      const dateDebut = formatDateForTSV(contract.start_date);
      const dateFin = formatDateForTSV(contract.end_date);
      const codeRubrique = "He"; // Fixe
      const quantiteRubrique = contract.nombre_d_heures ? contract.nombre_d_heures.toString() : ""; // Heures de travail au total
      const baseRubrique = ""; // Vide
      const coutEmployeur = contract.gross_pay ? contract.gross_pay.toFixed(2).replace('.', ',') : "";
      const compteAnalytique = "COURSCLEMENT"; // Fixe pour l'instant
      const compteAnalytiqueMultiple = ""; // Vide
      const repartitionAnalytiqueMultiple = ""; // Vide
      const numeroObjet = contract.n_objet || contract.objet_spectacle || ""; // Numéro d'objet de la production
      const dateTravailleeDebut = ""; // Vide
      const dateTravailleeFin = ""; // Vide
      const contrat = contractNumber;

      return [
        codeEmployeur,
        contractNumber,
        matricule,
        categorieSalariale,
        codeProfession,
        typeContrat,
        dateDebut,
        dateFin,
        codeRubrique,
        quantiteRubrique,
        baseRubrique,
        coutEmployeur,
        compteAnalytique,
        compteAnalytiqueMultiple,
        repartitionAnalytiqueMultiple,
        numeroObjet,
        dateTravailleeDebut,
        dateTravailleeFin,
        contrat
      ];
    });

    // Construire le contenu TSV
    const tsvContent = [
      headers.join('\t'),
      ...dataRows.map(row => row.join('\t'))
    ].join('\n');

    // Créer et télécharger le fichier
    const blob = new Blob([tsvContent], { type: 'text/tab-separated-values;charset=utf-8;' });
    const link = document.createElement('a');
    const url = URL.createObjectURL(blob);
    
    // Générer un nom de fichier avec la date
    const now = new Date();
    const dateStr = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`;
    const filename = `export_contrats_spaiectacle_${dateStr}.tsv`;
    
    link.setAttribute('href', url);
    link.setAttribute('download', filename);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);

    toast.success(`${selectedRows.length} contrat(s) exporté(s) en TSV`);
    setShowActionMenu(false);
  };

  // Fonction pour ouvrir le modal de confirmation
  const handleBulkESignClick = () => {
    if (selectedContractIds.size === 0) {
      toast.error("Aucun contrat sélectionné");
      return;
    }
    setShowESignConfirmModal(true);
  };

  // Fonction pour générer les e-signatures en masse (après confirmation)
  const generateBatchESign = async (sendNotification: boolean) => {
    // Fermer le modal de confirmation
    setShowESignConfirmModal(false);

    const contractIds = Array.from(selectedContractIds);
    
    // Initialiser les contrats avec leurs informations
    const initialProgress: ContractProgress[] = contractIds.map(id => {
      const contract = rows.find(r => r.id === id);
      return {
        id,
        contractNumber: contract?.contract_number || undefined,
        employeeName: contract?.employee_name || undefined,
        status: 'pending' as const
      };
    });

    // Ouvrir le modal et initialiser les états
    setContractsESignProgress(initialProgress);
    setShowESignProgressModal(true);
    setIsGeneratingESign(true);
    setIsESignCancelled(false);

    let successCount = 0;
    let errorCount = 0;
    const successfulContracts: any[] = [];

    try {
      // Traiter chaque contrat individuellement
      for (let i = 0; i < contractIds.length; i++) {
        if (isESignCancelled) {
          break;
        }

        const contractId = contractIds[i];
        
        // Marquer le contrat comme "en cours"
        setContractsESignProgress(prev => 
          prev.map(c => 
            c.id === contractId 
              ? { ...c, status: 'processing' as const }
              : c
          )
        );

        try {
          // Appeler l'endpoint de signature individuel via l'API bulk
          const response = await fetch(`/api/staff/contracts/bulk-esign`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
            },
            body: JSON.stringify({ contractIds: [contractId] }),
          });

          if (response.ok) {
            const result = await response.json();
            const contractResult = result.results?.[0];
            
            if (contractResult?.success) {
              successCount++;
              // Utiliser les données du résultat de l'API qui contient org_id
              const contract = rows.find(r => r.id === contractId);
              successfulContracts.push({
                ...contract,
                org_id: contractResult.org_id // Utiliser l'org_id de la réponse API
              });
              
              // Marquer comme succès
              setContractsESignProgress(prev => 
                prev.map(c => 
                  c.id === contractId 
                    ? { 
                        ...c, 
                        status: 'success' as const,
                        filename: contractResult.submissionId 
                      }
                    : c
                )
              );
            } else {
              errorCount++;
              
              // Marquer comme erreur
              setContractsESignProgress(prev => 
                prev.map(c => 
                  c.id === contractId 
                    ? { 
                        ...c, 
                        status: 'error' as const,
                        error: contractResult?.error || 'Erreur inconnue'
                      }
                    : c
                )
              );
            }
          } else {
            const errorData = await response.json();
            errorCount++;
            
            // Marquer comme erreur
            setContractsESignProgress(prev => 
              prev.map(c => 
                c.id === contractId 
                  ? { 
                      ...c, 
                      status: 'error' as const,
                      error: errorData.error || `Erreur ${response.status}`
                    }
                  : c
              )
            );
          }
        } catch (error) {
          errorCount++;
          
          // Marquer comme erreur
          setContractsESignProgress(prev => 
            prev.map(c => 
              c.id === contractId 
                ? { 
                    ...c, 
                    status: 'error' as const,
                    error: error instanceof Error ? error.message : 'Erreur de réseau'
                  }
                : c
            )
          );
        }

        // Petit délai entre chaque contrat
        if (i < contractIds.length - 1 && !isESignCancelled) {
          await new Promise(resolve => setTimeout(resolve, 1000));
        }
      }

      // Message final et envoi du mail récapitulatif si non annulé
      if (!isESignCancelled) {
        if (successCount > 0) {
          toast.success(`${successCount} signature${successCount > 1 ? 's' : ''} électronique${successCount > 1 ? 's' : ''} créée${successCount > 1 ? 's' : ''} !`);
          
          // Envoyer un mail récapitulatif au client (email_notifs + CC) si demandé
          if (sendNotification && successfulContracts.length > 0) {
            try {
              console.log('📧 [E-SIGN] Début envoi emails récapitulatifs...');
              console.log('📧 [E-SIGN] successfulContracts:', successfulContracts);
              
              // Regrouper les contrats par organisation
              const contractsByOrg = successfulContracts.reduce((acc: any, contract: any) => {
                const orgId = contract.org_id;
                console.log('📧 [E-SIGN] Contract:', contract.id, 'org_id:', orgId);
                if (!acc[orgId]) {
                  acc[orgId] = [];
                }
                acc[orgId].push(contract);
                return acc;
              }, {});

              console.log('📧 [E-SIGN] Contrats groupés par organisation:', Object.keys(contractsByOrg).length);

              // Envoyer un email récapitulatif pour chaque organisation
              for (const [orgId, contracts] of Object.entries(contractsByOrg)) {
                const count = (contracts as any[]).length;
                
                console.log(`📧 [E-SIGN] Envoi email pour org ${orgId}, ${count} contrats`);
                
                const response = await fetch('/api/staff/contracts/send-esign-notification', {
                  method: 'POST',
                  headers: {
                    'Content-Type': 'application/json',
                  },
                  body: JSON.stringify({
                    organizationId: orgId,
                    contractCount: count
                  }),
                });

                if (!response.ok) {
                  const errorData = await response.json();
                  console.error('❌ [E-SIGN] Erreur envoi email:', errorData);
                  throw new Error(errorData.error || `Erreur ${response.status}`);
                }

                const result = await response.json();
                console.log('✅ [E-SIGN] Email envoyé:', result);
              }
              
              toast.success('Email récapitulatif envoyé au client');
            } catch (emailError) {
              console.error("Erreur lors de l'envoi du mail récapitulatif:", emailError);
              toast.warning("Signatures créées mais erreur lors de l'envoi de l'email récapitulatif");
            }
          } else if (!sendNotification) {
            console.log('📧 [E-SIGN] Email récapitulatif désactivé par l\'utilisateur');
          }
        }
        if (errorCount > 0) {
          toast.error(`${errorCount} erreur${errorCount > 1 ? 's' : ''} lors de la création des signatures`);
        }
        
        // Note: Preserving selection after e-signature generation to allow further bulk actions
      }

    } catch (error) {
      console.error("Erreur lors de la génération des e-signatures:", error);
      toast.error("Erreur lors de la génération des e-signatures");
    } finally {
      setIsGeneratingESign(false);
    }
  };

  // Fonction pour annuler la génération e-sign
  const cancelESignGeneration = () => {
    setIsESignCancelled(true);
    setIsGeneratingESign(false);
    toast.info("Génération annulée");
  };

  // Fonction pour fermer le modal e-sign
  const closeESignProgressModal = () => {
    setShowESignProgressModal(false);
    setContractsESignProgress([]);
    setIsESignCancelled(false);
  };

  // Fonction pour créer les paies en masse
  const handleBulkPayslipSubmit = async (payslips: any[]) => {
    try {
      const response = await fetch('/api/staff/payslips/bulk-create', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ payslips }),
      });

      if (!response.ok) {
        throw new Error('Erreur lors de la création des paies');
      }

      const result = await response.json();
      
      toast.success(`${result.created || payslips.length} paie(s) créée(s) avec succès`);
      
      // Rafraîchir les données
      handleRefresh();
      
      // Désélectionner les contrats
      setSelectedContractIds(new Set());
    } catch (error) {
      console.error('Erreur création paies:', error);
      throw error;
    }
  };

  // Fonction pour extraire les notifications directement des données de contrats
  // Plus besoin d'appel API séparé, les timestamps sont maintenant dans cddu_contracts
  const updateNotificationsFromRows = (contracts: Contract[]) => {
    const map = new Map<string, NotificationInfo>();
    
    contracts.forEach(contract => {
      const info: NotificationInfo = {
        employerLastSent: contract.last_employer_notification_at || null,
        employeeLastSent: contract.last_employee_notification_at || null,
      };
      
      // N'ajouter à la map que si au moins une notification existe
      if (info.employerLastSent || info.employeeLastSent) {
        map.set(contract.id, info);
      }
    });

    setNotificationMap(map);
  };

  // Debounce searches when filters change
  useEffect(() => {
    // if no filters applied, prefer initial data
    const noFilters = !q && !structureFilter && !typeFilter && !productionFilter && etatContratFilters.size === 0 && !etatPaieFilter && !dpaeFilter && !signatureFilter && !startFrom && !startTo && !endFrom && !endTo && sortField === 'start_date' && sortOrder === 'desc';
    if (noFilters) {
      setRows(initialData || []);
      return;
    }

    const t = setTimeout(() => fetchServer(0), 300);
    return () => clearTimeout(t);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [q, structureFilter, typeFilter, productionFilter, etatContratFilters, etatPaieFilter, dpaeFilter, signatureFilter, startFrom, startTo, endFrom, endTo, sortField, sortOrder, limit]);

  // Récupérer les notifications quand les données changent
  useEffect(() => {
    if (rows.length > 0) {
      updateNotificationsFromRows(rows);
    }
  }, [rows]);

  // Calculate counts for quick filters
  useEffect(() => {
    const calculateCounts = async () => {
      // DPAE à faire
      const paramsDpae = new URLSearchParams();
      paramsDpae.set('dpae', 'À faire');
      const today = new Date();
      const in7 = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
      const y = in7.getFullYear();
      const m = String(in7.getMonth() + 1).padStart(2, '0');
      const day = String(in7.getDate()).padStart(2, '0');
      paramsDpae.set('start_to', `${y}-${m}-${day}`);
      paramsDpae.set('limit', '1');
      const countDpae = await countContractsForFilter(paramsDpae);
      setCountDpaeAFaire(countDpae);

      // Contrats à faire mois
      const paramsContrats = new URLSearchParams();
      paramsContrats.set('etat_de_la_demande', 'Reçue,En cours');
      const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
      const lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);
      const y1 = firstDay.getFullYear();
      const m1 = String(firstDay.getMonth() + 1).padStart(2, '0');
      const day1 = String(firstDay.getDate()).padStart(2, '0');
      const y2 = lastDay.getFullYear();
      const m2 = String(lastDay.getMonth() + 1).padStart(2, '0');
      const day2 = String(lastDay.getDate()).padStart(2, '0');
      paramsContrats.set('start_from', `${y1}-${m1}-${day1}`);
      paramsContrats.set('start_to', `${y2}-${m2}-${day2}`);
      paramsContrats.set('limit', '1');
      const countContrats = await countContractsForFilter(paramsContrats);
      setCountContratsAFaireMois(countContrats);

      // Paies à traiter mois dernier
      const paramsPaieMois = new URLSearchParams();
      paramsPaieMois.set('etat_de_la_paie', 'À traiter');
      const firstDayThisMonth = new Date(today.getFullYear(), today.getMonth(), 1);
      const lastDayLastMonth = new Date(firstDayThisMonth.getFullYear(), firstDayThisMonth.getMonth(), 0);
      const firstDayLastMonth = new Date(lastDayLastMonth.getFullYear(), lastDayLastMonth.getMonth(), 1);
      const y3 = firstDayLastMonth.getFullYear();
      const m3 = String(firstDayLastMonth.getMonth() + 1).padStart(2, '0');
      const day3 = String(firstDayLastMonth.getDate()).padStart(2, '0');
      const y4 = lastDayLastMonth.getFullYear();
      const m4 = String(lastDayLastMonth.getMonth() + 1).padStart(2, '0');
      const day4 = String(lastDayLastMonth.getDate()).padStart(2, '0');
      paramsPaieMois.set('end_from', `${y3}-${m3}-${day3}`);
      paramsPaieMois.set('end_to', `${y4}-${m4}-${day4}`);
      paramsPaieMois.set('limit', '1');
      const countPaieMois = await countContractsForFilter(paramsPaieMois);
      setCountPaieATraiterMoisDernier(countPaieMois);

      // Paies à traiter toutes périodes
      const paramsPaieToutes = new URLSearchParams();
      paramsPaieToutes.set('etat_de_la_paie', 'À traiter');
      paramsPaieToutes.set('etat_de_la_demande', 'Traitée');
      const y5 = today.getFullYear();
      const m5 = String(today.getMonth() + 1).padStart(2, '0');
      const day5 = String(today.getDate()).padStart(2, '0');
      paramsPaieToutes.set('end_to', `${y5}-${m5}-${day5}`);
      paramsPaieToutes.set('limit', '1');
      const countPaieToutes = await countContractsForFilter(paramsPaieToutes);
      setCountPaieATraiterToutes(countPaieToutes);

      // Contrats non signés avec date de début proche (passé, aujourd'hui, demain)
      const paramsNonSignes = new URLSearchParams();
      paramsNonSignes.set('signature_state', 'non_signe');
      const tomorrow = new Date(today);
      tomorrow.setDate(tomorrow.getDate() + 1);
      const y6 = tomorrow.getFullYear();
      const m6 = String(tomorrow.getMonth() + 1).padStart(2, '0');
      const day6 = String(tomorrow.getDate()).padStart(2, '0');
      paramsNonSignes.set('start_to', `${y6}-${m6}-${day6}`);
      paramsNonSignes.set('limit', '1');
      const countNonSignes = await countContractsForFilter(paramsNonSignes);
      setCountContratsNonSignesDateProche(countNonSignes);
    };

    calculateCounts();
  }, []);

  // Calculate multi-mois count from client-side data (separate useEffect)
  useEffect(() => {
    const cdduContracts = rows.filter(contract => 
      contract.type_de_contrat === 'CDDU' || contract.type_de_contrat === 'CDDU_MONO' || contract.type_de_contrat === 'CDDU_MULTI'
    );
    
    const multiMoisCount = cdduContracts.filter(contract => {
      if (!contract.start_date || !contract.end_date) return false;
      
      const startDate = new Date(contract.start_date);
      const endDate = new Date(contract.end_date);
      
      // Vérifier si les mois ou les années sont différents
      return startDate.getMonth() !== endDate.getMonth() || 
             startDate.getFullYear() !== endDate.getFullYear();
    }).length;
    
    setCountMultiMois(multiMoisCount);
  }, [rows]);

  // Fonction pour relancer un salarié spécifique
  const handleReminderClick = async (contract: any) => {
    setSelectedContractForReminder(contract);
    
    // Récupérer l'email du salarié depuis la base de données
    try {
      const response = await fetch(`/api/staff/contrats/${contract.id}/employee-email`);
      if (response.ok) {
        const result = await response.json();
        setSelectedContractForReminder({
          ...contract,
          employee_email: result.employee_email
        });
      }
    } catch (error) {
      console.error('Erreur récupération email:', error);
    }

    setShowEmployeeReminderModal(true);
  };

  // Fonction pour envoyer la relance au salarié
  const sendEmployeeReminder = async () => {
    if (!selectedContractForReminder) return;

    setIsLoadingReminder(true);

    try {
      const response = await fetch('/api/staff/contrats/relance-salarie', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ contractId: selectedContractForReminder.id }),
      });

      const result = await response.json();

      if (response.ok) {
        toast.success(`Email de relance envoyé avec succès à ${selectedContractForReminder.employee_name}`);
        setShowEmployeeReminderModal(false);
        setSelectedContractForReminder(null);
      } else {
        toast.error(result.error || result.message || 'Erreur lors de l\'envoi de la relance');
      }
    } catch (error: any) {
      console.error('Erreur relance salarié:', error);
      toast.error(error.message || 'Erreur lors de l\'envoi de la relance');
    } finally {
      setIsLoadingReminder(false);
    }
  };

  // Fonction pour analyser intelligemment les contrats et déterminer qui relancer
  const handleSmartReminderClick = async () => {
    if (selectedContractIds.size === 0) {
      toast.error("Aucun contrat sélectionné");
      return;
    }

    setIsLoadingReminderEmails(true);

    try {
      // Récupérer les contrats sélectionnés
      const selectedContracts = rows.filter(r => selectedContractIds.has(r.id));

      // Récupérer les emails employeurs depuis l'API
      const orgIds = [...new Set(selectedContracts.map(c => c.org_id).filter(Boolean))];
      const employerEmailsMap = new Map<string, string>();
      
      try {
        const response = await fetch('/api/staff/organizations/emails', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ org_ids: orgIds }),
        });
        
        if (response.ok) {
          const data = await response.json();
          // data devrait être un array de { org_id, email_signature }
          data.forEach((org: any) => {
            if (org.org_id && org.email_signature) {
              employerEmailsMap.set(org.org_id, org.email_signature);
            }
          });
        }
      } catch (error) {
        console.error('Erreur lors de la récupération des emails employeurs:', error);
      }

      // Fonction pour vérifier si une relance a été envoyée il y a moins de 24h
      const wasRecentlySent = (timestamp: string | null | undefined): boolean => {
        if (!timestamp) return false;
        const sentDate = new Date(timestamp);
        const now = new Date();
        const hoursDiff = (now.getTime() - sentDate.getTime()) / (1000 * 60 * 60);
        return hoursDiff < 24;
      };

      // Analyser chaque contrat pour déterminer l'action appropriée
      const analyzedContracts: SmartReminderContract[] = selectedContracts.map(contract => {
        const employerSigned = contract.contrat_signe_par_employeur === 'Oui';
        const employeeSigned = contract.contrat_signe === 'Oui';
        const contractProcessed = String(contract.etat_de_la_demande || contract.etat_demande || "").toLowerCase().includes('traité') || 
                                   String(contract.etat_de_la_demande || contract.etat_demande || "").toLowerCase().includes('traitée');
        
        const employerRecentlySent = wasRecentlySent(contract.last_employer_notification_at);
        const employeeRecentlySent = wasRecentlySent(contract.last_employee_notification_at);
        
        let action: ReminderAction;
        let reason: string;
        let forcedAction: ReminderAction | undefined; // Action qui sera utilisée si forceResend = true

        // Logique de décision
        if (employerSigned && employeeSigned) {
          action = 'already-signed';
          reason = 'Contrat entièrement signé';
        } else if (!contractProcessed) {
          action = 'skip';
          reason = 'Contrat non traité (e-signature non envoyée)';
        } else if (!employerSigned) {
          if (employerRecentlySent) {
            action = 'skip';
            reason = 'Relance employeur envoyée il y a moins de 24h';
            forcedAction = 'employer'; // Forcer vers employeur si demandé
          } else {
            action = 'employer';
            reason = 'Employeur n\'a pas encore signé';
          }
        } else if (employerSigned && !employeeSigned) {
          if (employeeRecentlySent) {
            action = 'skip';
            reason = 'Relance salarié envoyée il y a moins de 24h';
            forcedAction = 'employee'; // Forcer vers salarié si demandé
          } else {
            action = 'employee';
            reason = 'Salarié n\'a pas encore signé';
          }
        } else {
          action = 'skip';
          reason = 'État indéterminé';
        }

        const employerEmail = contract.org_id ? employerEmailsMap.get(contract.org_id) : undefined;
        
        return {
          id: contract.id,
          reference: (contract as any).reference as string | null | undefined,
          contract_number: contract.contract_number,
          employee_name: formatEmployeeName(contract as any),
          employee_email: (contract as any)?.salaries?.adresse_mail || undefined,
          employer_email: employerEmail,
          employer_signed: employerSigned,
          employee_signed: employeeSigned,
          contract_processed: contractProcessed,
          action,
          reason,
          status: 'pending' as const,
          forcedAction // Stocker l'action forcée pour usage ultérieur
        } as SmartReminderContract & { forcedAction?: ReminderAction };
      });

      // Trier par action pour une meilleure lisibilité
      const sorted = analyzedContracts.sort((a, b) => {
        const order = { 'employer': 0, 'employee': 1, 'skip': 2, 'already-signed': 3 };
        return order[a.action] - order[b.action];
      });

      setSmartReminderContracts(sorted);
      setShowSmartReminderModal(true);
    } finally {
      setIsLoadingReminderEmails(false);
    }
  };

  // Fonction pour relancer en masse tous les salariés sélectionnés (ancienne version - conservée pour compatibilité)
  const handleBulkReminderClick = async () => {
    if (selectedContractIds.size === 0) {
      toast.error("Aucun contrat sélectionné");
      return;
    }

    // Prépare et affiche le modal de confirmation avec les emails
    setIsLoadingReminderEmails(true);
    const contracts = rows.filter(r => selectedContractIds.has(r.id)).map(r => ({
      id: r.id,
      reference: (r as any).reference as string | null | undefined,
      contract_number: r.contract_number,
      employee_name: formatEmployeeName(r as any),
      employee_email: (r as any)?.salaries?.adresse_mail || undefined,
    }));
    setBulkReminderContracts(contracts);
    setShowBulkReminderModal(true);

    // Récupérer les emails manquants via l'API dédiée
    const fetchEmail = async (id: string) => {
      try {
        const resp = await fetch(`/api/staff/contrats/${id}/employee-email`);
        if (resp.ok) {
          const j = await resp.json();
          return j.employee_email as string | undefined;
        }
      } catch {}
      return undefined;
    };

    try {
      const results = await Promise.all(contracts.map(async (c) => ({ id: c.id, email: c.employee_email || await fetchEmail(c.id) })));
      setBulkReminderContracts(prev => prev.map(p => {
        const found = results.find(r => r.id === p.id);
        return { ...p, employee_email: found?.email || p.employee_email };
      }));
    } finally {
      setIsLoadingReminderEmails(false);
    }
  };

  // Envoi des relances intelligentes après confirmation
  const confirmSendSmartReminders = async (forceResend: boolean = false) => {
    setIsLoadingReminder(true);
    
    // Si forceResend est activé, inclure aussi les contrats en cooldown qui ont une forcedAction
    const contractsToProcess = forceResend 
      ? smartReminderContracts.map(c => {
          const extended = c as SmartReminderContract & { forcedAction?: ReminderAction };
          if (extended.forcedAction) {
            return { ...c, action: extended.forcedAction };
          }
          return c;
        })
      : smartReminderContracts;
    
    const toSend = contractsToProcess.filter(c => c.action === 'employer' || c.action === 'employee');
    
    // Initialiser le state de progression avec tous les contrats (avec les actions forcées si nécessaire)
    setSmartReminderProgress([...contractsToProcess]);
    
    let successCount = 0;
    let errorCount = 0;
    
    try {
      for (const contract of toSend) {
        // Mettre à jour le statut à "sending"
        setSmartReminderProgress(prev => 
          prev.map(c => c.id === contract.id ? { ...c, status: 'sending' as const } : c)
        );
        
        try {
          if (contract.action === 'employer') {
            // Relancer l'employeur
            const response = await fetch(`/api/staff/contrats/${contract.id}/remind-employer`, {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
            });
            
            if (response.ok) {
              successCount++;
              setSmartReminderProgress(prev => 
                prev.map(c => c.id === contract.id ? { ...c, status: 'success' as const } : c)
              );
            } else {
              errorCount++;
              setSmartReminderProgress(prev => 
                prev.map(c => c.id === contract.id ? { ...c, status: 'error' as const } : c)
              );
            }
          } else if (contract.action === 'employee') {
            // Relancer le salarié
            const response = await fetch('/api/staff/contrats/relance-salarie', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({ contractId: contract.id }),
            });
            
            if (response.ok) {
              successCount++;
              setSmartReminderProgress(prev => 
                prev.map(c => c.id === contract.id ? { ...c, status: 'success' as const } : c)
              );
            } else {
              errorCount++;
              setSmartReminderProgress(prev => 
                prev.map(c => c.id === contract.id ? { ...c, status: 'error' as const } : c)
              );
            }
          }
        } catch {
          errorCount++;
          setSmartReminderProgress(prev => 
            prev.map(c => c.id === contract.id ? { ...c, status: 'error' as const } : c)
          );
        }
      }
      
      if (successCount > 0) {
        toast.success(`${successCount} relance${successCount > 1 ? 's' : ''} envoyée${successCount > 1 ? 's' : ''} avec succès`);
      }
      if (errorCount > 0) {
        toast.error(`${errorCount} erreur${errorCount > 1 ? 's' : ''} lors de l'envoi`);
      }
      
      // Rafraîchir les données des contrats pour récupérer les nouveaux timestamps
      // Les notifications seront automatiquement mises à jour via l'effet useEffect sur rows
      setTimeout(() => fetchServer(page), 1000);
    } finally {
      setIsLoadingReminder(false);
      // Ne pas fermer le modal automatiquement pour permettre de voir le résumé
      // setShowSmartReminderModal(false);
    }
  };

  // Envoi des relances après confirmation dans le modal (ancienne version)
  const confirmSendBulkReminders = async () => {
    setIsLoadingReminder(true);
    const ids = bulkReminderContracts.map(c => c.id);
    let successCount = 0;
    let errorCount = 0;
    try {
      for (const contractId of ids) {
        try {
          const response = await fetch('/api/staff/contrats/relance-salarie', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ contractId }),
          });
          if (response.ok) successCount++; else errorCount++;
        } catch {
          errorCount++;
        }
      }
      if (successCount > 0) toast.success(`${successCount} email${successCount > 1 ? 's' : ''} de relance envoyé${successCount > 1 ? 's' : ''}`);
      if (errorCount > 0) toast.error(`${errorCount} erreur${errorCount > 1 ? 's' : ''} lors de l'envoi`);
    } finally {
      setIsLoadingReminder(false);
      setShowBulkReminderModal(false);
    }
  };

  // derive options from initialData for simple selects
  const structures = useMemo(() => {
    const uniqueStructures = Array.from(new Set((initialData || []).map((r) => r.structure).filter(Boolean) as string[]));
    return uniqueStructures.sort((a, b) => a.localeCompare(b, 'fr')).slice(0, 50);
  }, [initialData]);
  const types = useMemo(() => Array.from(new Set((initialData || []).map((r) => r.type_de_contrat).filter(Boolean) as string[])).slice(0,50), [initialData]);
  // Filtrer les productions par structure sélectionnée
  const productions = useMemo(() => {
    let filteredData = initialData || [];
    
    // Si une structure est sélectionnée, filtrer les contrats par cette structure
    if (structureFilter) {
      filteredData = filteredData.filter(r => r.structure === structureFilter);
    }
    
    const uniqueProductions = Array.from(new Set(filteredData.map((r) => r.production_name).filter(Boolean) as string[]));
    return uniqueProductions.sort((a, b) => a.localeCompare(b, 'fr')).slice(0, 50);
  }, [initialData, structureFilter]);
  const etatsContrat = useMemo(() => Array.from(new Set((initialData || []).map((r) => r.etat_de_la_demande).filter(Boolean) as string[])).slice(0,50), [initialData]);
  const etatsPaie = useMemo(() => Array.from(new Set((initialData || []).map((r) => r.etat_de_la_paie).filter(Boolean) as string[])).slice(0,50), [initialData]);
  const etatsDpae = useMemo(() => Array.from(new Set((initialData || []).map((r) => r.dpae).filter(Boolean) as string[])).slice(0,50), [initialData]);

  return (
    <div className="relative">
      {/* Filters */}
      <div className="mb-3">
        {/* Ligne du haut: recherche + bouton filtres */}
        <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-3">
          <div className="flex-1">
            <input 
              value={q} 
              onChange={(e) => setQ(e.target.value)} 
              placeholder="Recherche (n° contrat, salarié)" 
              className="w-full rounded border px-2 py-1 text-sm" 
            />
          </div>
          <div className="flex items-center gap-2">
            {/* Filtres rapides toujours visibles */}
            <select 
              value={structureFilter ?? ""} 
              onChange={(e) => {
                const value = e.target.value || null;
                setStructureFilter(value);
                // Note: structureFilter est un nom de structure (string), pas un UUID
                // On ne synchronise pas avec le store global ici car il attend des UUIDs
              }} 
              className="rounded border px-2 py-1 text-sm max-w-[200px]"
              title={structureFilter || "Toutes structures"}
            >
              <option value="">Toutes structures</option>
              {structures.map((s) => (<option key={s} value={s}>{s}</option>))}
            </select>
            <select value={typeFilter ?? ""} onChange={(e) => setTypeFilter(e.target.value || null)} className="rounded border px-2 py-1 text-sm">
              <option value="">Tous types</option>
              <option value="CDD d'usage">CDDU</option>
              <option value="RG">RG (CDD/CDI droit commun)</option>
              {types.filter(t => t !== "CDD d'usage" && t !== "CDD de droit commun" && t !== "CDI").map((t) => (<option key={t} value={t}>{t}</option>))}
            </select>
            {/* Afficher le dropdown de production uniquement si une structure est sélectionnée */}
            {structureFilter && (
              <select 
                value={productionFilter ?? ""} 
                onChange={(e) => setProductionFilter(e.target.value || null)} 
                className="rounded border px-2 py-1 text-sm max-w-[200px]"
                title={productionFilter || "Toutes productions"}
              >
                <option value="">Toutes productions</option>
                {productions.map((p) => (<option key={p} value={p}>{p}</option>))}
              </select>
            )}
            <button 
              onClick={() => setShowFilters(!showFilters)}
              className="inline-flex items-center gap-1 text-sm text-blue-600 hover:text-blue-800 px-2 py-1 rounded border"
            >
              {showFilters ? "Masquer" : "Plus de"} filtres
            </button>
            
            <button 
              onClick={handleRefresh}
              disabled={loading}
              className="inline-flex items-center gap-1 text-sm text-emerald-600 hover:text-emerald-800 px-2 py-1 rounded border disabled:opacity-50 disabled:cursor-not-allowed"
              title="Actualiser les données"
            >
              <RefreshCw className={`w-3 h-3 ${loading ? 'animate-spin' : ''}`} />
              Actualiser
            </button>
            
            <button 
              className="rounded border px-3 py-1 text-sm" 
              onClick={() => { 
                setQ(''); 
                setStructureFilter(null); 
                setTypeFilter(null);
                setProductionFilter(null);
                setEtatContratFilters(new Set());
                setEtatPaieFilter(null);
                setDpaeFilter(null);
                setSignatureFilter(null);
                setMultiMoisFilter(false);
                setStartFrom(null); 
                setStartTo(null); 
                setEndFrom(null);
                setEndTo(null);
                setSortField('start_date'); 
                setSortOrder('desc'); 
                setRows(initialData || []); 
                // Notifier le parent que les filtres ont été réinitialisés
                onFiltersReset?.();
              }}
            >
              Réinitialiser
            </button>
          </div>
        </div>

        {/* Filtres contrats (masquables) */}
        {showFilters && (
          <div className="border rounded-lg p-4 bg-slate-50">
            <div className="grid grid-cols-1 md:grid-cols-6 gap-4">
              {/* Filtre État contrat - Dropdown with multiple checkboxes */}
              <div className="relative group">
                <label className="block text-sm font-medium text-slate-700 mb-2">
                  État contrat
                </label>
                <button className="w-full px-3 py-2 border rounded-lg bg-white text-sm text-left flex items-center justify-between hover:border-slate-400">
                  <span className={etatContratFilters.size === 0 ? "text-slate-500" : "text-slate-900"}>
                    {etatContratFilters.size === 0 ? "Tous les états" : `${etatContratFilters.size} sélectionné${etatContratFilters.size > 1 ? 's' : ''}`}
                  </span>
                  <svg className="w-4 h-4 text-slate-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                  </svg>
                </button>
                <div className="absolute top-full left-0 mt-1 w-full bg-white border rounded-lg shadow-lg z-10 hidden group-hover:block">
                  <div className="p-2 space-y-2 max-h-48 overflow-y-auto">
                    <div className="flex items-center px-2 py-1">
                      <input
                        type="checkbox"
                        id="etat-all"
                        checked={etatContratFilters.size === 0}
                        onChange={() => setEtatContratFilters(new Set())}
                        className="rounded border-gray-300"
                      />
                      <label htmlFor="etat-all" className="ml-2 text-sm text-slate-700 cursor-pointer font-medium">
                        Tous les états
                      </label>
                    </div>
                    <div className="border-t"></div>
                    {etatsContrat.map((etat) => (
                      <div key={etat} className="flex items-center px-2 py-1">
                        <input
                          type="checkbox"
                          id={`etat-${etat}`}
                          checked={etatContratFilters.has(etat)}
                          onChange={(e) => {
                            const newSet = new Set(etatContratFilters);
                            if (e.target.checked) {
                              newSet.add(etat);
                            } else {
                              newSet.delete(etat);
                            }
                            setEtatContratFilters(newSet);
                          }}
                          className="rounded border-gray-300"
                        />
                        <label htmlFor={`etat-${etat}`} className="ml-2 text-sm text-slate-700 cursor-pointer">
                          {etat}
                        </label>
                      </div>
                    ))}
                  </div>
                </div>
              </div>

              {/* Filtre État paie */}
              <div>
                <label className="block text-sm font-medium text-slate-700 mb-2">
                  État paie
                </label>
                <select
                  value={etatPaieFilter ?? ""}
                  onChange={(e) => setEtatPaieFilter(e.target.value || null)}
                  className="w-full px-3 py-2 border rounded-lg bg-white text-sm"
                >
                  <option value="">Tous les états</option>
                  {etatsPaie.map((etat) => (
                    <option key={etat} value={etat}>{etat}</option>
                  ))}
                </select>
              </div>

              {/* Filtre DPAE */}
              <div>
                <label className="block text-sm font-medium text-slate-700 mb-2">
                  DPAE
                </label>
                <select
                  value={dpaeFilter ?? ""}
                  onChange={(e) => setDpaeFilter(e.target.value || null)}
                  className="w-full px-3 py-2 border rounded-lg bg-white text-sm"
                >
                  <option value="">Tous les états</option>
                  <option value="À faire">À faire</option>
                  <option value="Faite">Faite</option>
                </select>
              </div>

              {/* Filtre Signature */}
              <div>
                <label className="block text-sm font-medium text-slate-700 mb-2">
                  État signature
                </label>
                <select
                  value={signatureFilter ?? ""}
                  onChange={(e) => setSignatureFilter(e.target.value || null)}
                  className="w-full px-3 py-2 border rounded-lg bg-white text-sm"
                >
                  <option value="">Tous les états</option>
                  <option value="non_signe">Non signé</option>
                  <option value="employeur_seulement">Signé employeur seulement</option>
                  <option value="signe_complet">Complètement signé</option>
                </select>
              </div>

              {/* Filtre date de début */}
              <div>
                <label className="block text-sm font-medium text-slate-700 mb-2">
                  Date début - De
                </label>
                <input
                  type="date"
                  value={startFrom ?? ""}
                  onChange={(e) => setStartFrom(e.target.value || null)}
                  className="w-full px-3 py-2 border rounded-lg bg-white text-sm"
                />
              </div>

              {/* Filtre date de fin */}
              <div>
                <label className="block text-sm font-medium text-slate-700 mb-2">
                  Date début - À
                </label>
                <input
                  type="date"
                  value={startTo ?? ""}
                  onChange={(e) => setStartTo(e.target.value || null)}
                  className="w-full px-3 py-2 border rounded-lg bg-white text-sm"
                />
              </div>
            </div>
          </div>
        )}
      </div>

      {/* Boutons d'actions groupées */}
      {selectedContractIds.size > 0 && (
        <div className="mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg">
          <div className="flex items-center justify-between">
            <span className="text-sm text-blue-800 font-medium">
              {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''} sélectionné{selectedContractIds.size > 1 ? 's' : ''}
            </span>
            <div className="flex gap-2">
              {/* Menu dropdown Actions contrat */}
              <div className="relative">
                <button
                  onClick={() => setShowActionMenu(!showActionMenu)}
                  className="px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors flex items-center gap-1"
                >
                  <Settings className="w-4 h-4" />
                  Actions contrat
                  <ChevronDown className="w-4 h-4" />
                </button>
                
                {showActionMenu && (
                  <>
                    <div 
                      className="fixed inset-0 z-10" 
                      onClick={() => setShowActionMenu(false)}
                    />
                    <div className="absolute right-0 mt-1 w-48 bg-white rounded-md shadow-lg z-20 border border-gray-200">
                      <div className="py-1">
                        <button
                          onClick={() => {
                            setShowBulkPayslipModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <Euro className="w-4 h-4" />
                          Ajout de paie
                        </button>
                        <div className="border-t border-gray-200 my-1"></div>
                        <button
                          onClick={() => {
                            setShowDpaeModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <FileText className="w-4 h-4" />
                          Modifier DPAE
                        </button>
                        <button
                          onClick={() => {
                            setShowEtatContratModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <CheckCircle className="w-4 h-4" />
                          Modifier État Contrat
                        </button>
                        <button
                          onClick={() => {
                            setShowEtatPaieModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <BarChart3 className="w-4 h-4" />
                          Modifier État Paie
                        </button>
                        <button
                          onClick={() => {
                            setShowAnalytiqueModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <FileText className="w-4 h-4" />
                          Modifier Analytique
                        </button>
                        <button
                          onClick={() => {
                            viewSelectedDetails();
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <Eye className="w-4 h-4" />
                          Voir les détails
                        </button>
                        <button
                          onClick={() => {
                            exportSelectedToTSV();
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <FileDown className="w-4 h-4" />
                          Exporter TSV (sPAIEctacle)
                        </button>
                        <button
                          onClick={() => {
                            setShowJoursTechnicienModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <Calendar className="w-4 h-4" />
                          Jours technicien
                        </button>
                        <button
                          onClick={() => {
                            setShowSignatureDateModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors flex items-center gap-2"
                        >
                          <FileSignature className="w-4 h-4" />
                          Modifier date de signature
                        </button>
                        <div className="border-t border-gray-200 my-1"></div>
                        <button
                          onClick={() => {
                            setShowDeleteModal(true);
                            setShowActionMenu(false);
                          }}
                          className="w-full text-left px-4 py-2 text-sm text-red-600 hover:bg-red-50 transition-colors flex items-center gap-2"
                        >
                          <Trash2 className="w-4 h-4" />
                          Supprimer les contrats
                        </button>
                      </div>
                    </div>
                  </>
                )}
              </div>

              {/* Menu dropdown E-signature */}
              <div className="relative">
                <button
                  onClick={() => setShowESignMenu(!showESignMenu)}
                  className="px-3 py-1 text-sm bg-indigo-600 text-white rounded hover:bg-indigo-700 transition-colors flex items-center gap-1"
                >
                  <FileSignature className="w-4 h-4" />
                  E-signature
                  <ChevronDown className="w-4 h-4" />
                </button>
                
                {showESignMenu && (
                  <>
                    <div 
                      className="fixed inset-0 z-10" 
                      onClick={() => setShowESignMenu(false)}
                    />
                    <div className="absolute right-0 mt-1 w-48 bg-white rounded-md shadow-lg z-20 border border-gray-200">
                      <div className="py-1">
                        <button
                          onClick={() => {
                            generateBatchPdfs();
                            setShowESignMenu(false);
                          }}
                          disabled={isGeneratingPdfs}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors disabled:text-gray-400 disabled:hover:bg-white flex items-center gap-2"
                        >
                          <FileDown className="w-4 h-4" />
                          {isGeneratingPdfs ? "Génération..." : "Créer les PDF"}
                        </button>
                        <button
                          onClick={() => {
                            verifySelectedPdfs();
                            setShowESignMenu(false);
                          }}
                          disabled={isLoadingPdfs}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors disabled:text-gray-400 disabled:hover:bg-white flex items-center gap-2"
                        >
                          <Eye className="w-4 h-4" />
                          {isLoadingPdfs ? "Chargement..." : "Vérifier PDFs"}
                        </button>
                        <button
                          onClick={() => {
                            handleBulkESignClick();
                            setShowESignMenu(false);
                          }}
                          disabled={isGeneratingESign}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors disabled:text-gray-400 disabled:hover:bg-white flex items-center gap-2"
                        >
                          <FileSignature className="w-4 h-4" />
                          {isGeneratingESign ? "Envoi..." : "Envoyer e-sign"}
                        </button>
                        <div className="border-t border-gray-200 my-1"></div>
                        <button
                          onClick={() => {
                            setShowESignMenu(false);
                            handleSmartReminderClick();
                          }}
                          disabled={isLoadingReminder}
                          className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition-colors disabled:text-gray-400 disabled:hover:bg-white flex items-center gap-2"
                        >
                          <BellRing className="w-4 h-4" />
                          {isLoadingReminder ? "Analyse..." : "Relances intelligentes"}
                        </button>
                      </div>
                    </div>
                  </>
                )}
              </div>
              
              <button
                onClick={() => setShowSalaryModal(true)}
                className="px-3 py-1 text-sm bg-green-600 text-white rounded hover:bg-green-700 transition-colors flex items-center gap-1"
              >
                <Euro className="w-4 h-4" />
                Saisir brut
              </button>
              <button
                onClick={() => setSelectedContractIds(new Set())}
                className="px-3 py-1 text-sm bg-gray-500 text-white rounded hover:bg-gray-600 transition-colors flex items-center gap-1"
              >
                <XCircle className="w-4 h-4" />
                Désélectionner tout
              </button>
            </div>
          </div>
        </div>
      )}

      <div className="overflow-auto">
        <table className="w-full text-sm">
          <thead className="bg-slate-50 text-slate-600">
            <tr>
              <th className="text-left px-3 py-2 w-12">
                <input
                  type="checkbox"
                  checked={isAllSelected}
                  ref={(el) => {
                    if (el) el.indeterminate = isPartiallySelected;
                  }}
                  onChange={toggleSelectAll}
                  className="rounded border-gray-300"
                />
              </th>
              <th className="text-left px-3 py-2" title="État Contrat">C</th>
              <th className="text-left px-3 py-2" title="État Paie">P</th>
              <th className="text-left px-3 py-2" title="DPAE">D</th>
              <th className="text-left px-3 py-2">Signé</th>
              <th className="text-left px-3 py-2">N° contrat</th>
              <th className="text-left px-3 py-2 cursor-pointer" onClick={() => { setSortField('employee_name'); setSortOrder((o) => o === 'asc' ? 'desc' : 'asc'); }}>
                Salarié {sortField === 'employee_name' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
              </th>
              <th className="text-left px-3 py-2 cursor-pointer" onClick={() => { setSortField('code_employeur'); setSortOrder((o) => o === 'asc' ? 'desc' : 'asc'); }}>
                Structure {sortField === 'code_employeur' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
              </th>
              <th className="text-left px-3 py-2 cursor-pointer" onClick={() => { setSortField('production_name'); setSortOrder((o) => o === 'asc' ? 'desc' : 'asc'); }}>
                Production {sortField === 'production_name' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
              </th>
              <th className="text-left px-3 py-2">Type</th>
              <th className="text-left px-3 py-2">Profession</th>
              <th className="text-left px-3 py-2" title="Type de salaire demandé">Type salaire</th>
              <th className="text-left px-3 py-2 cursor-pointer" onClick={() => { setSortField('start_date'); setSortOrder((o) => o === 'asc' ? 'desc' : 'asc'); }}>
                Date début {sortField === 'start_date' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
              </th>
              <th className="text-left px-3 py-2 cursor-pointer" onClick={() => { setSortField('end_date'); setSortOrder((o) => o === 'asc' ? 'desc' : 'asc'); }}>
                Date fin {sortField === 'end_date' ? (sortOrder === 'asc' ? '▲' : '▼') : ''}
              </th>
              <th className="text-left px-3 py-2" title="Dernières notifications de signature électronique">Notif.</th>
            </tr>
          </thead>
          <tbody>
            {sortedRows.map((r) => (
              <tr key={r.id} className={`border-t ${selectedContractIds.has(r.id) ? 'bg-blue-50' : ''}`}>
                <td className="px-3 py-2">
                  <input
                    type="checkbox"
                    checked={selectedContractIds.has(r.id)}
                    onChange={() => toggleSelectContract(r.id)}
                    className="rounded border-gray-300"
                  />
                </td>
                <td className="px-3 py-2">
                  {(() => {
                    const { icon, tooltip } = getEtatContratIcon(r.etat_de_la_demande || r.etat_demande);
                    return (<div title={tooltip}>{icon}</div>);
                  })()}
                </td>

                <td className="px-3 py-2">
                  {(() => {
                    const { icon, tooltip } = getEtatPaieIcon(r.etat_de_la_paie);
                    return (<div title={tooltip}>{icon}</div>);
                  })()}
                </td>

                <td className="px-3 py-2">
                  {(() => {
                    const { icon, tooltip } = getDpaeIcon(r.dpae);
                    return (<div title={tooltip}>{icon}</div>);
                  })()}
                </td>

                <td className="px-3 py-2">
                  <div className="flex items-center gap-3">
                    <div className="flex flex-col items-center gap-1">
                      <div className="text-xs font-semibold text-slate-600">E</div>
                      {r.contrat_signe_par_employeur === "Oui" ? (
                        <Check className="size-4 text-green-600" strokeWidth={3} />
                      ) : r.contrat_signe_par_employeur === "Non" ? (
                        <X className="size-4 text-red-600" strokeWidth={3} />
                      ) : (
                        <span className="text-xs text-slate-400">—</span>
                      )}
                    </div>
                    <div className="flex flex-col items-center gap-1">
                      <div className="text-xs font-semibold text-slate-600">S</div>
                      {r.contrat_signe === "Oui" ? (
                        <Check className="size-4 text-green-600" strokeWidth={3} />
                      ) : r.contrat_signe === "Non" ? (
                        <X className="size-4 text-red-600" strokeWidth={3} />
                      ) : (
                        <span className="text-xs text-slate-400">—</span>
                      )}
                    </div>
                  </div>
                </td>

                <td className="px-3 py-2">
                  <Link href={`/staff/contrats/${r.id}`}>{r.contract_number || "—"}</Link>
                </td>

                <td className="px-3 py-2">{formatEmployeeName(r)}</td>
                <td className="px-3 py-2">{r.organizations?.organization_details?.code_employeur || r.structure || "—"}</td>
                <td className="px-3 py-2">{r.production_name || "—"}</td>
                <td className="px-3 py-2">{
                  r.type_de_contrat === "CDD d'usage" ? "CDDU" : (r.type_de_contrat || "—")
                }</td>
                <td className="px-3 py-2">{r.profession || "—"}</td>
                <td className="px-3 py-2" title={r.type_salaire || "—"}>{
                  (() => {
                    const type = r.type_salaire || "—";
                    if (type.includes("Brut")) return "Brut";
                    if (type.includes("Net")) return "Net";
                    if (type.includes("Coût") || type.includes("CTE")) return "CTE";
                    if (type.includes("Minimum") || type.includes("Min")) return "Min";
                    return type;
                  })()
                }</td>
                <td className="px-3 py-2">{formatDate(r.start_date)}</td>
                <td className="px-3 py-2">{formatDate(r.end_date)}</td>
                <td className="px-3 py-2">
                  {(() => {
                    // Lire directement depuis le contrat au lieu de la map pour éviter les problèmes de timing
                    const employerLastSent = r.last_employer_notification_at;
                    const employeeLastSent = r.last_employee_notification_at;
                    const color = getNotificationColor(r.start_date);
                    
                    if (!employerLastSent && !employeeLastSent) {
                      return <span className="text-xs text-slate-400">—</span>;
                    }
                    
                    return (
                      <div className={`flex flex-col gap-1 text-xs ${color}`} title={`E: Employeur • S: Salarié\nCouleur basée sur la date de début du contrat`}>
                        {employerLastSent && (
                          <div className="flex items-center gap-1">
                            <span className="font-semibold">E:</span>
                            <span>{formatNotificationDate(employerLastSent)}</span>
                          </div>
                        )}
                        {employeeLastSent && (
                          <div className="flex items-center gap-1">
                            <span className="font-semibold">S:</span>
                            <span>{formatNotificationDate(employeeLastSent)}</span>
                          </div>
                        )}
                      </div>
                    );
                  })()}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        {sortedRows.length === 0 && (
          <div className="p-4 text-sm text-slate-600">
            <div>Aucun contrat trouvé.</div>
            <div className="mt-2">
              <button
                className="text-xs underline"
                onClick={() => setShowRaw((s) => !s)}
              >
                {showRaw ? "Cacher le payload" : "Voir le payload reçu"}
              </button>
            </div>
            {showRaw && (
              <pre className="mt-2 max-h-48 overflow-auto text-xs bg-slate-50 p-2 rounded border">{JSON.stringify(initialData, null, 2)}</pre>
            )}
          </div>
        )}
      </div>

      {/* Pagination / info */}
      <div className="mt-3 flex items-center justify-between text-xs text-slate-600">
        <div>{loading ? 'Chargement…' : `Affichage ${sortedRows.length}${totalCountRef.current ? ` / ${totalCountRef.current}` : ''}`}</div>
        <div className="flex items-center gap-2">
          <button className="text-xs px-2 py-1 rounded border" onClick={() => { if (page > 0) fetchServer(page - 1); }}>Préc</button>
          <button className="text-xs px-2 py-1 rounded border" onClick={() => { fetchServer(page + 1); }}>Suiv</button>
        </div>
      </div>

      {/* slide removed: navigation now goes to /staff/contrats/[id] */}

      {/* Modal Action groupée DPAE */}
      {showDpaeModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-md">
            <h3 className="text-lg font-semibold mb-4">Action groupée - DPAE</h3>
            <p className="text-sm text-gray-600 mb-4">
              Modifier l'état DPAE pour {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''}
            </p>
            <DpaeActionModal
              selectedContracts={selectedContracts}
              onClose={() => setShowDpaeModal(false)}
              onSuccess={(updatedContracts) => {
                // Mettre à jour les contrats dans la liste
                setRows(prev => prev.map(row => {
                  const updated = updatedContracts.find(u => u.id === row.id);
                  return updated ? { ...row, dpae: updated.dpae } : row;
                }));
                setShowDpaeModal(false);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal Action groupée État Contrat */}
      {showEtatContratModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-md">
            <h3 className="text-lg font-semibold mb-4">Action groupée - État Contrat</h3>
            <p className="text-sm text-gray-600 mb-4">
              Modifier l'état du contrat pour {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''}
            </p>
            <EtatContratActionModal
              selectedContracts={selectedContracts}
              onClose={() => setShowEtatContratModal(false)}
              onSuccess={(updatedContracts) => {
                // Mettre à jour les contrats dans la liste
                setRows(prev => prev.map(row => {
                  const updated = updatedContracts.find(u => u.id === row.id);
                  return updated ? { ...row, etat_de_la_demande: updated.etat_de_la_demande } : row;
                }));
                setShowEtatContratModal(false);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal Action groupée État Paie */}
      {showEtatPaieModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-md">
            <h3 className="text-lg font-semibold mb-4">Action groupée - État Paie</h3>
            <p className="text-sm text-gray-600 mb-4">
              Modifier l'état de la paie pour {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''}
            </p>
            <EtatPaieActionModal
              selectedContracts={selectedContracts}
              onClose={() => setShowEtatPaieModal(false)}
              onSuccess={(updatedContracts) => {
                // Mettre à jour les contrats dans la liste
                setRows(prev => prev.map(row => {
                  const updated = updatedContracts.find(u => u.id === row.id);
                  return updated ? { ...row, etat_de_la_paie: updated.etat_de_la_paie } : row;
                }));
                setShowEtatPaieModal(false);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal Action groupée Analytique */}
      {showAnalytiqueModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-md">
            <h3 className="text-lg font-semibold mb-4">Action groupée - Analytique</h3>
            <p className="text-sm text-gray-600 mb-4">
              Modifier l'analytique pour {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''}
            </p>
            <AnalytiqueActionModal
              selectedContracts={selectedContracts}
              onClose={() => setShowAnalytiqueModal(false)}
              onSuccess={(updatedContracts) => {
                // Mettre à jour les contrats dans la liste
                setRows(prev => prev.map(row => {
                  const updated = updatedContracts.find(u => u.id === row.id);
                  return updated ? { ...row, analytique: updated.analytique, production_name: updated.analytique } : row;
                }));
                setShowAnalytiqueModal(false);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal Action groupée Jours Technicien */}
      {showJoursTechnicienModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-2xl">
            <h3 className="text-lg font-semibold mb-4">Action groupée - Jours Technicien</h3>
            <p className="text-sm text-gray-600 mb-4">
              Modifier les jours de travail pour {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''}
            </p>
            <JoursTechnicienModal
              selectedContracts={selectedContracts}
              onClose={() => setShowJoursTechnicienModal(false)}
              onSuccess={(updatedContracts) => {
                // Mettre à jour les contrats dans la liste
                setRows(prev => prev.map(row => {
                  const updated = updatedContracts.find(u => u.id === row.id);
                  return updated ? { ...row, jours_travail: updated.jours_travail, jours_travail_non_artiste: updated.jours_travail_non_artiste } : row;
                }));
                setShowJoursTechnicienModal(false);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal Action groupée - Modifier date de signature */}
      {showSignatureDateModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-md">
            <h3 className="text-lg font-semibold mb-4">Action groupée - Date de signature</h3>
            <p className="text-sm text-gray-600 mb-4">
              Modifier la date de signature pour {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''}
            </p>
            <SignatureDateModal
              selectedContracts={selectedContracts}
              onClose={() => setShowSignatureDateModal(false)}
              onSuccess={(updatedContracts) => {
                setRows(prev => prev.map(row => {
                  const updated = updatedContracts.find(u => u.id === row.id);
                  return updated ? { ...row, date_signature: updated.date_signature } : row;
                }));
                setShowSignatureDateModal(false);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal Saisir brut */}
      {showSalaryModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-2xl max-h-[80vh] overflow-y-auto">
            <h3 className="text-lg font-semibold mb-4">Saisir brut</h3>
            <p className="text-sm text-gray-600 mb-4">
              Saisir le salaire brut pour {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''}
            </p>
            <SalaryInputModal
              selectedContracts={selectedContracts}
              onClose={() => setShowSalaryModal(false)}
              onSuccess={(updatedContracts) => {
                // Mettre à jour les contrats dans la liste
                setRows(prev => prev.map(row => {
                  const updated = updatedContracts.find(u => u.id === row.id);
                  return updated ? { ...row, gross_pay: updated.gross_pay } : row;
                }));
                setShowSalaryModal(false);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal de progression pour la génération des PDFs */}
      <BulkPdfProgressModal
        isOpen={showProgressModal}
        onClose={closeProgressModal}
        contracts={contractsProgress}
        onCancel={isGeneratingPdfs ? cancelPdfGeneration : undefined}
        isProcessing={isGeneratingPdfs}
        totalCount={contractsProgress.length}
        completedCount={contractsProgress.filter(c => c.status === 'success' || c.status === 'error').length}
        successCount={contractsProgress.filter(c => c.status === 'success').length}
        errorCount={contractsProgress.filter(c => c.status === 'error').length}
      />

      {/* Modal de vérification des PDFs */}
      <PdfVerificationModal
        isOpen={showPdfVerificationModal}
        onClose={closePdfVerificationModal}
        contracts={contractsPdfs}
        isLoading={isLoadingPdfs}
      />

      {/* Modal de détails des contrats */}
      <ContractDetailsModal
        isOpen={showDetailsModal}
        onClose={() => setShowDetailsModal(false)}
        contractIds={contractDetailsIds}
        contracts={rows}
      />

      {/* Modal de confirmation pour l'envoi des e-signatures */}
      <BulkESignConfirmModal
        isOpen={showESignConfirmModal}
        onClose={() => setShowESignConfirmModal(false)}
        onConfirm={generateBatchESign}
        contractCount={selectedContractIds.size}
        selectedContracts={selectedContracts}
      />

      {/* Modal de confirmation pour la relance des salariés (bulk) */}
      <BulkEmployeeReminderModal
        isOpen={showBulkReminderModal}
        onClose={() => setShowBulkReminderModal(false)}
        onConfirm={confirmSendBulkReminders}
        isLoading={isLoadingReminder}
        isLoadingEmails={isLoadingReminderEmails}
        contracts={bulkReminderContracts}
      />

      {/* Modal intelligent pour les relances */}
      <SmartReminderModal
        isOpen={showSmartReminderModal}
        onClose={() => setShowSmartReminderModal(false)}
        onConfirm={confirmSendSmartReminders}
        isLoading={isLoadingReminder}
        contracts={smartReminderContracts}
        progressContracts={smartReminderProgress.length > 0 ? smartReminderProgress : undefined}
      />

      {/* Modal d'ajout de paie en masse */}
      <BulkPayslipModal
        isOpen={showBulkPayslipModal}
        onClose={() => setShowBulkPayslipModal(false)}
        contracts={selectedContracts}
        onSubmit={handleBulkPayslipSubmit}
      />

      {/* Modal de progression pour l'envoi des e-signatures */}
      <BulkESignProgressModal
        isOpen={showESignProgressModal}
        onClose={closeESignProgressModal}
        contracts={contractsESignProgress}
        onCancel={isGeneratingESign ? cancelESignGeneration : undefined}
        isProcessing={isGeneratingESign}
        totalCount={contractsESignProgress.length}
        completedCount={contractsESignProgress.filter(c => c.status === 'success' || c.status === 'error').length}
        successCount={contractsESignProgress.filter(c => c.status === 'success').length}
        errorCount={contractsESignProgress.filter(c => c.status === 'error').length}
      />

      {/* Modal de confirmation de suppression */}
      {showDeleteModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 w-full max-w-md">
            <h3 className="text-lg font-semibold mb-4 text-red-600">Confirmation de suppression</h3>
            <p className="text-sm text-gray-600 mb-4">
              Êtes-vous sûr de vouloir supprimer {selectedContractIds.size} contrat{selectedContractIds.size > 1 ? 's' : ''} ?
            </p>
            <DeleteConfirmModal
              selectedContracts={selectedContracts}
              onClose={() => setShowDeleteModal(false)}
              onSuccess={(deletedIds) => {
                // Retirer les contrats supprimés de la liste
                setRows(prev => prev.filter(row => !deletedIds.includes(row.id)));
                setShowDeleteModal(false);
                setSelectedContractIds(new Set());
                toast.success(`${deletedIds.length} contrat${deletedIds.length > 1 ? 's' : ''} supprimé${deletedIds.length > 1 ? 's' : ''}`);
              }}
            />
          </div>
        </div>
      )}

      {/* Modal de relance salarié */}
      <EmployeeReminderModal
        isOpen={showEmployeeReminderModal}
        onClose={() => {
          setShowEmployeeReminderModal(false);
          setSelectedContractForReminder(null);
        }}
        onConfirm={sendEmployeeReminder}
        isLoading={isLoadingReminder}
        contractData={{
          reference: selectedContractForReminder?.reference || selectedContractForReminder?.contract_number,
          employee_name: selectedContractForReminder?.employee_name,
          employee_email: selectedContractForReminder?.employee_email
        }}
      />
    </div>
  );
}

const ContractsGrid = forwardRef(ContractsGridImpl);
export default ContractsGrid;

// Modal pour l'action groupée DPAE
function DpaeActionModal({ 
  selectedContracts, 
  onClose, 
  onSuccess 
}: { 
  selectedContracts: Contract[]; 
  onClose: () => void; 
  onSuccess: (contracts: { id: string; dpae: string }[]) => void; 
}) {
  const [newDpaeStatus, setNewDpaeStatus] = useState<string>('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async () => {
    if (!newDpaeStatus) return;
    
    setLoading(true);
    try {
      const response = await fetch('/api/staff/contracts/bulk-update-dpae', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          contractIds: selectedContracts.map(c => c.id),
          dpaeStatus: newDpaeStatus
        })
      });

      if (!response.ok) throw new Error('Erreur lors de la mise à jour');
      
      const result = await response.json();
      onSuccess(result.contracts);
    } catch (error) {
      console.error('Erreur:', error);
      alert('Erreur lors de la mise à jour des contrats');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">
            Nouvel état DPAE
          </label>
          <select
            value={newDpaeStatus}
            onChange={(e) => setNewDpaeStatus(e.target.value)}
            className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="">Sélectionner un état</option>
            <option value="À faire">À faire</option>
            <option value="Faite">Faite</option>
          </select>
        </div>

        <div className="border rounded-lg p-3 max-h-40 overflow-y-auto">
          <p className="text-sm font-medium text-gray-700 mb-2">Contrats sélectionnés :</p>
          {selectedContracts.map(contract => (
            <div key={contract.id} className="text-sm text-gray-600 py-1">
              {contract.contract_number || contract.id} - {formatEmployeeName(contract)}
            </div>
          ))}
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={!newDpaeStatus || loading}
          className="px-4 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Mise à jour...' : 'Appliquer'}
        </button>
      </div>
    </>
  );
}

// Modal pour l'état du contrat
function EtatContratActionModal({ 
  selectedContracts, 
  onClose, 
  onSuccess 
}: { 
  selectedContracts: Contract[]; 
  onClose: () => void; 
  onSuccess: (contracts: { id: string; etat_de_la_demande: string }[]) => void; 
}) {
  const [newEtatContrat, setNewEtatContrat] = useState<string>('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async () => {
    if (!newEtatContrat) return;
    
    setLoading(true);
    try {
      const response = await fetch('/api/staff/contracts/bulk-update-etat-contrat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          contractIds: selectedContracts.map(c => c.id),
          etatContrat: newEtatContrat
        })
      });

      if (!response.ok) throw new Error('Erreur lors de la mise à jour');
      
      const result = await response.json();
      onSuccess(result.contracts);
    } catch (error) {
      console.error('Erreur:', error);
      alert('Erreur lors de la mise à jour des contrats');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">
            Nouvel état du contrat
          </label>
          <select
            value={newEtatContrat}
            onChange={(e) => setNewEtatContrat(e.target.value)}
            className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="">Sélectionner un état</option>
            <option value="Reçue">Reçue</option>
            <option value="En cours">En cours</option>
            <option value="Traitée">Traitée</option>
            <option value="Refusée">Refusée</option>
          </select>
        </div>

        <div className="border rounded-lg p-3 max-h-40 overflow-y-auto">
          <p className="text-sm font-medium text-gray-700 mb-2">Contrats sélectionnés :</p>
          {selectedContracts.map(contract => (
            <div key={contract.id} className="text-sm text-gray-600 py-1">
              {contract.contract_number || contract.id} - {formatEmployeeName(contract)}
            </div>
          ))}
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={!newEtatContrat || loading}
          className="px-4 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Mise à jour...' : 'Appliquer'}
        </button>
      </div>
    </>
  );
}

// Modal pour l'état de la paie
function EtatPaieActionModal({ 
  selectedContracts, 
  onClose, 
  onSuccess 
}: { 
  selectedContracts: Contract[]; 
  onClose: () => void; 
  onSuccess: (contracts: { id: string; etat_de_la_paie: string }[]) => void; 
}) {
  const [newEtatPaie, setNewEtatPaie] = useState<string>('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async () => {
    if (!newEtatPaie) return;
    
    setLoading(true);
    try {
      const response = await fetch('/api/staff/contracts/bulk-update-etat-paie', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          contractIds: selectedContracts.map(c => c.id),
          etatPaie: newEtatPaie
        })
      });

      if (!response.ok) throw new Error('Erreur lors de la mise à jour');
      
      const result = await response.json();
      onSuccess(result.contracts);
    } catch (error) {
      console.error('Erreur:', error);
      alert('Erreur lors de la mise à jour des contrats');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">
            Nouvel état de la paie
          </label>
          <select
            value={newEtatPaie}
            onChange={(e) => setNewEtatPaie(e.target.value)}
            className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            <option value="">Sélectionner un état</option>
            <option value="À traiter">À traiter</option>
            <option value="En cours">En cours</option>
            <option value="Traitée">Traitée</option>
          </select>
        </div>

        <div className="border rounded-lg p-3 max-h-40 overflow-y-auto">
          <p className="text-sm font-medium text-gray-700 mb-2">Contrats sélectionnés :</p>
          {selectedContracts.map(contract => (
            <div key={contract.id} className="text-sm text-gray-600 py-1">
              {contract.contract_number || contract.id} - {formatEmployeeName(contract)}
            </div>
          ))}
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={!newEtatPaie || loading}
          className="px-4 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Mise à jour...' : 'Appliquer'}
        </button>
      </div>
    </>
  );
}

// Modal pour l'analytique
function AnalytiqueActionModal({ 
  selectedContracts, 
  onClose, 
  onSuccess 
}: { 
  selectedContracts: Contract[]; 
  onClose: () => void; 
  onSuccess: (contracts: { id: string; analytique: string }[]) => void; 
}) {
  const [newAnalytique, setNewAnalytique] = useState<string>('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async () => {
    if (!newAnalytique.trim()) {
      toast.error("Veuillez saisir un code analytique");
      return;
    }
    
    setLoading(true);
    try {
      const response = await fetch('/api/staff/contracts/bulk-update-analytique', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          contractIds: selectedContracts.map(c => c.id),
          analytique: newAnalytique.trim()
        })
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.error || 'Erreur lors de la mise à jour');
      }
      
      const result = await response.json();
      toast.success(`${result.count} contrat(s) mis à jour`);
      onSuccess(result.contracts);
    } catch (error: any) {
      console.error('Erreur:', error);
      toast.error(error.message || 'Erreur lors de la mise à jour des contrats');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">
            Nouveau code analytique
          </label>
          <input
            type="text"
            value={newAnalytique}
            onChange={(e) => setNewAnalytique(e.target.value)}
            placeholder="Ex: Production 2025"
            className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            autoFocus
          />
          <p className="text-xs text-gray-500 mt-1">
            Ce code sera appliqué au champ "Analytique" de tous les contrats sélectionnés
          </p>
        </div>

        <div className="border rounded-lg p-3 max-h-40 overflow-y-auto">
          <p className="text-sm font-medium text-gray-700 mb-2">Contrats sélectionnés :</p>
          {selectedContracts.map(contract => (
            <div key={contract.id} className="text-sm text-gray-600 py-1">
              {contract.contract_number || contract.id} - {formatEmployeeName(contract)}
              {contract.analytique && (
                <span className="text-xs text-gray-400 ml-2">
                  (actuel: {contract.analytique})
                </span>
              )}
            </div>
          ))}
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={!newAnalytique.trim() || loading}
          className="px-4 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Mise à jour...' : 'Appliquer'}
        </button>
      </div>
    </>
  );
}

// Modal pour saisir le brut
function SalaryInputModal({ 
  selectedContracts, 
  onClose, 
  onSuccess 
}: { 
  selectedContracts: Contract[]; 
  onClose: () => void; 
  onSuccess: (contracts: { id: string; gross_pay: number }[]) => void; 
}) {
  const [salaries, setSalaries] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(false);

  const handleSalaryChange = (contractId: string, value: string) => {
    setSalaries(prev => ({ ...prev, [contractId]: value }));
  };

  const handleSubmit = async () => {
    const updates = Object.entries(salaries)
      .filter(([_, value]) => value.trim() !== '')
      .map(([contractId, value]) => ({
        contractId,
        grossPay: parseFloat(value.replace(',', '.'))
      }))
      .filter(update => !isNaN(update.grossPay));

    if (updates.length === 0) {
      alert('Veuillez saisir au moins un montant valide');
      return;
    }

    setLoading(true);
    try {
      const response = await fetch('/api/staff/contracts/bulk-update-salary', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ updates })
      });

      if (!response.ok) throw new Error('Erreur lors de la mise à jour');
      
      const result = await response.json();
      onSuccess(result.contracts);
    } catch (error) {
      console.error('Erreur:', error);
      alert('Erreur lors de la mise à jour des salaires');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div className="space-y-3">
          {selectedContracts.map(contract => (
            <div key={contract.id} className="flex items-center gap-3 p-3 border rounded-lg">
              <div className="flex-1">
                <div className="font-medium text-sm">
                  {contract.contract_number || contract.id}
                </div>
                <div className="text-sm text-gray-600">
                  {formatEmployeeName(contract)}
                </div>
              </div>
              <div className="w-32">
                <input
                  type="number"
                  step="0.01"
                  placeholder="0.00"
                  value={salaries[contract.id] || ''}
                  onChange={(e) => handleSalaryChange(contract.id, e.target.value)}
                  className="w-full px-2 py-1 text-sm border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-green-500"
                />
              </div>
              <div className="text-sm text-gray-500">€</div>
            </div>
          ))}
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={loading}
          className="px-4 py-2 text-sm bg-green-600 text-white rounded hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Mise à jour...' : 'Enregistrer'}
        </button>
      </div>
    </>
  );
}

// Modal pour confirmer la suppression des contrats
function DeleteConfirmModal({ 
  selectedContracts, 
  onClose, 
  onSuccess 
}: { 
  selectedContracts: Contract[]; 
  onClose: () => void; 
  onSuccess: (deletedIds: string[]) => void; 
}) {
  const [loading, setLoading] = useState(false);
  const [confirmText, setConfirmText] = useState('');

  const handleSubmit = async () => {
    if (confirmText.toLowerCase() !== 'supprimer') {
      toast.error('Veuillez taper "supprimer" pour confirmer');
      return;
    }
    
    setLoading(true);
    try {
      const response = await fetch('/api/staff/contracts/bulk-delete', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          contractIds: selectedContracts.map(c => c.id)
        })
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.error || 'Erreur lors de la suppression');
      }
      
      const result = await response.json();
      onSuccess(result.deletedIds);
    } catch (error) {
      console.error('Erreur:', error);
      toast.error(error instanceof Error ? error.message : 'Erreur lors de la suppression des contrats');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div className="bg-red-50 border border-red-200 rounded-lg p-4">
          <p className="text-sm text-red-800 font-medium">
            ⚠️ Attention : Cette action est irréversible !
          </p>
          <p className="text-xs text-red-700 mt-2">
            Les contrats suivants seront définitivement supprimés de la base de données.
          </p>
        </div>

        <div className="border rounded-lg p-3 max-h-40 overflow-y-auto">
          <p className="text-sm font-medium text-gray-700 mb-2">Contrats à supprimer :</p>
          {selectedContracts.map(contract => (
            <div key={contract.id} className="text-sm text-gray-600 py-1">
              • {contract.contract_number || contract.id} - {formatEmployeeName(contract)}
            </div>
          ))}
        </div>

        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">
            Pour confirmer, tapez <span className="font-bold text-red-600">supprimer</span>
          </label>
          <input
            type="text"
            value={confirmText}
            onChange={(e) => setConfirmText(e.target.value)}
            placeholder="supprimer"
            className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-red-500"
          />
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={confirmText.toLowerCase() !== 'supprimer' || loading}
          className="px-4 py-2 text-sm bg-red-600 text-white rounded hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Suppression...' : 'Supprimer définitivement'}
        </button>
      </div>
    </>
  );
}

// Modal pour les jours technicien
function JoursTechnicienModal({
  selectedContracts,
  onClose,
  onSuccess
}: {
  selectedContracts: Contract[];
  onClose: () => void;
  onSuccess: (contracts: { id: string; jours_travail: string; jours_travail_non_artiste: string }[]) => void;
}) {
  const [joursTravailList, setJoursTravailList] = useState<string[]>(
    selectedContracts.map(() => '')
  );
  const [loading, setLoading] = useState(false);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
    e.preventDefault();
    const pastedText = e.clipboardData.getData('text');
    const lines = pastedText.split('\n').filter(line => line.trim() !== '');
    
    // Distribuer les lignes collées aux contrats sélectionnés
    const newList = [...joursTravailList];
    lines.forEach((line, index) => {
      if (index < newList.length) {
        newList[index] = line.trim();
      }
    });
    
    setJoursTravailList(newList);
  };

  const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const lines = e.target.value.split('\n');
    const newList = lines.map(line => line.trim());
    
    // Ajuster la taille du tableau pour correspondre au nombre de contrats
    while (newList.length < selectedContracts.length) {
      newList.push('');
    }
    
    setJoursTravailList(newList.slice(0, selectedContracts.length));
  };

  const handleSubmit = async () => {
    setLoading(true);
    try {
      const updates = selectedContracts.map((contract, index) => ({
        id: contract.id,
        joursTravail: joursTravailList[index] || ''
      }));

      const response = await fetch('/api/staff/contracts/bulk-update-jours-technicien', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ updates })
      });

      if (!response.ok) throw new Error('Erreur lors de la mise à jour');
      
      const result = await response.json();
      onSuccess(result.contracts);
    } catch (error) {
      console.error('Erreur:', error);
      alert('Erreur lors de la mise à jour des contrats');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">
            Jours de travail (un par ligne)
          </label>
          <p className="text-xs text-gray-500 mb-2">
            Collez les dates ligne par ligne. Chaque ligne correspond à un contrat dans l'ordre ci-dessous.
          </p>
          <textarea
            ref={textareaRef}
            value={joursTravailList.join('\n')}
            onChange={handleTextareaChange}
            onPaste={handlePaste}
            placeholder="Exemple:&#10;01/01/2025, 02/01/2025&#10;03/01/2025, 04/01/2025&#10;..."
            rows={Math.min(selectedContracts.length, 10)}
            className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm"
          />
        </div>

        <div className="border rounded-lg p-3 max-h-60 overflow-y-auto">
          <p className="text-sm font-medium text-gray-700 mb-2">Contrats sélectionnés :</p>
          {selectedContracts.map((contract, index) => (
            <div key={contract.id} className="text-sm text-gray-600 py-1 flex items-start gap-2">
              <span className="text-gray-400 min-w-[30px]">{index + 1}.</span>
              <div className="flex-1">
                <div className="font-medium">{contract.contract_number || contract.id} - {formatEmployeeName(contract)}</div>
                {joursTravailList[index] && (
                  <div className="text-xs text-green-600 mt-1">
                    {joursTravailList[index]}
                  </div>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={loading || joursTravailList.every(j => !j)}
          className="px-4 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Mise à jour...' : 'Appliquer'}
        </button>
      </div>
    </>
  );
}

// Modal pour modifier la date de signature en masse
function SignatureDateModal({
  selectedContracts,
  onClose,
  onSuccess
}: {
  selectedContracts: Contract[];
  onClose: () => void;
  onSuccess: (contracts: { id: string; date_signature: string | null }[]) => void;
}) {
  const [lines, setLines] = useState<string[]>(selectedContracts.map(() => ''));
  const [applyDate, setApplyDate] = useState<string>('');
  const [loading, setLoading] = useState(false);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    // Resize initial lines to match contracts
    setLines(prev => {
      const copy = [...prev];
      while (copy.length < selectedContracts.length) copy.push('');
      return copy.slice(0, selectedContracts.length);
    });
  }, [selectedContracts.length]);

  const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => {
    e.preventDefault();
    const pasted = e.clipboardData.getData('text');
    const pastedLines = pasted.split('\n').map(l => l.trim()).filter(Boolean);
    const newLines = [...lines];
    pastedLines.forEach((l, i) => {
      if (i < newLines.length) newLines[i] = l;
    });
    setLines(newLines);
  };

  const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const vals = e.target.value.split('\n').map(l => l.trim());
    while (vals.length < selectedContracts.length) vals.push('');
    setLines(vals.slice(0, selectedContracts.length));
  };

  const handleApplyDateToAll = (d: string) => {
    setApplyDate(d);
    if (d) {
      setLines(selectedContracts.map(() => d));
    }
  };

  const handleSubmit = async () => {
    setLoading(true);
    try {
      const updates = selectedContracts.map((c, idx) => ({ id: c.id, date: lines[idx] ? new Date(lines[idx]).toISOString().split('T')[0] : null }));

      const res = await fetch('/api/staff/contracts/bulk-update-signature-date', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ updates })
      });

      if (!res.ok) throw new Error('Erreur lors de la mise à jour');
      const json = await res.json();
      onSuccess(json.contracts || []);
    } catch (err) {
      console.error(err);
      toast.error('Erreur lors de la mise à jour des dates de signature');
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <div className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">Date de signature</label>
          <p className="text-xs text-gray-500 mb-2">Vous pouvez coller une liste de dates (une par ligne) ; chaque ligne correspond à un contrat dans l'ordre ci-dessous. Format recommandé : YYYY-MM-DD ou JJ/MM/YYYY.</p>
          <div className="flex gap-2 mb-2">
            <input
              type="date"
              value={applyDate}
              onChange={e => handleApplyDateToAll(e.target.value)}
              className="px-3 py-2 border border-gray-300 rounded-md"
            />
            <div className="text-xs text-slate-500 self-center">ou collez ci-dessous</div>
          </div>
          <textarea
            ref={textareaRef}
            value={lines.join('\n')}
            onChange={handleChange}
            onPaste={handlePaste}
            rows={Math.min(selectedContracts.length, 10)}
            placeholder={`2025-01-01\n2025-02-03\n...`}
            className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm"
          />
        </div>

        <div className="border rounded-lg p-3 max-h-60 overflow-y-auto">
          <p className="text-sm font-medium text-gray-700 mb-2">Contrats sélectionnés :</p>
          {selectedContracts.map((c, idx) => (
            <div key={c.id} className="text-sm text-gray-600 py-1 flex items-start gap-2">
              <span className="text-gray-400 min-w-[30px]">{idx + 1}.</span>
              <div className="flex-1">
                <div className="font-medium">{c.contract_number || c.id} - {formatEmployeeName(c)}</div>
                {lines[idx] && (
                  <div className="text-xs text-green-600 mt-1">{lines[idx]}</div>
                )}
              </div>
            </div>
          ))}
        </div>
      </div>

      <div className="flex justify-end gap-2 mt-6">
        <button
          onClick={onClose}
          className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded hover:bg-gray-50"
          disabled={loading}
        >
          Annuler
        </button>
        <button
          onClick={handleSubmit}
          disabled={loading || lines.every(l => !l)}
          className="px-4 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {loading ? 'Mise à jour...' : 'Appliquer'}
        </button>
      </div>
    </>
  );
}
