import { NextRequest, NextResponse } from 'next/server';
import { createClient, SupabaseClient, PostgrestError } from '@supabase/supabase-js';
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { v4 as uuidv4 } from 'uuid';
import { sendContractNotifications } from '@/lib/emailService';
import { resolveActiveOrg } from '@/lib/resolveActiveOrg';

type QueryResult<T> = { data: T | null; error: PostgrestError | null };

type EmployeeRow = {
  id: string;
  code_salarie: string;
  nom: string;
  prenom: string;
  adresse_mail: string | null;
  employer_id?: string | null;
};

type OrganizationRow = {
  name: string;
  organization_details?: {
    email_notifs?: string | null;
    email_notifs_cc?: string | null;
    prenom_contact?: string | null;
    code_employeur?: string | null;
  } | null;
};

type ProductionRow = {
  id: string;
  name: string;
  reference: string | null;
  org_id?: string | null;
};

type NoteInsert = {
  contract_id: string;
  organization_id: string;
  content: string;
  source: string;
};

export async function POST(request: NextRequest) {
  const supabase = createRouteHandlerClient({ cookies });
  const { data: { user } } = await supabase.auth.getUser();
  if (!user) return NextResponse.json({ error: "Non authentifié." }, { status: 401 });

  try {
    const body = await request.json();

    console.log("Body reçu pour création CDDU:", body);
    console.log("🔍 [API] body.salaires_par_date:", body.salaires_par_date);

    // Générer un identifiant unique pour le contrat
    const contractId = uuidv4();
    const providedReference = typeof body.reference === "string" ? body.reference.trim().toUpperCase() : "";
    const contractNumber = providedReference || generateContractReference();

    // Détecter si l'utilisateur est staff et préparer un client service_role si disponible
    let isStaff = false;
    console.log('🔍 [DEBUG] Début détection staff pour user:', user.id);
    
    try {
      const { data: staffRow } = await supabase
        .from('staff_users')
        .select('is_staff')
        .eq('user_id', user.id)
        .maybeSingle();
      console.log('🔍 [DEBUG] Résultat query staff_users:', staffRow);
      isStaff = !!staffRow?.is_staff;
      console.log('🔍 [DEBUG] isStaff depuis DB:', isStaff);
    } catch (err) {
      console.log('🔍 [DEBUG] Erreur query staff_users, fallback metadata:', err);
      const userMeta = user.user_metadata || {};
      const appMeta = user.app_metadata || {};
      console.log('🔍 [DEBUG] user_metadata:', userMeta);
      console.log('🔍 [DEBUG] app_metadata:', appMeta);
      isStaff = Boolean(
        userMeta.is_staff === true ||
        userMeta.role === 'staff' ||
        (Array.isArray(appMeta?.roles) && appMeta.roles.includes('staff'))
      );
      console.log('🔍 [DEBUG] isStaff depuis metadata:', isStaff);
    }

    const serviceSupabase: SupabaseClient | null =
      process.env.NEXT_PUBLIC_SUPABASE_URL && process.env.SUPABASE_SERVICE_ROLE_KEY
        ? createClient(process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.SUPABASE_SERVICE_ROLE_KEY, {
            auth: { autoRefreshToken: false, persistSession: false },
          })
        : null;

    if (isStaff && !serviceSupabase) {
      console.error('Service role non configuré : impossible de traiter une création staff.');
      return NextResponse.json(
        { error: 'Configuration Supabase incomplète pour le mode staff' },
        { status: 500 }
      );
    }

    const clients: SupabaseClient[] = [];
    if (isStaff && serviceSupabase) {
      clients.push(serviceSupabase);
    }
    clients.push(supabase);
    if (!isStaff && serviceSupabase) {
      clients.push(serviceSupabase);
    }

    const runOnClients = async <T>(fn: (client: SupabaseClient, index: number) => Promise<QueryResult<T>>): Promise<QueryResult<T>> => {
      let lastResult: QueryResult<T> = { data: null, error: null };
      console.log(`🔍 [DEBUG] runOnClients démarré avec ${clients.length} clients`);
      
      for (let i = 0; i < clients.length; i++) {
        const client = clients[i];
        console.log(`🔍 [DEBUG] Essai avec client ${i + 1}/${clients.length}`);
        const result = await fn(client, i);
        lastResult = result;
        console.log(`🔍 [DEBUG] Client ${i + 1} résultat:`, { hasData: !!result.data, error: result.error });
        
        if (result.data) {
          console.log(`✅ [DEBUG] Données trouvées avec client ${i + 1}`);
          return result;
        }
        if (result.error) {
          const code = result.error.code;
          console.log(`🔍 [DEBUG] Client ${i + 1} erreur code:`, code);
          if (code && code !== 'PGRST116' && code !== 'PGRST108') {
            console.log(`❌ [DEBUG] Erreur bloquante avec client ${i + 1}, arrêt`);
            return result;
          }
        }
      }
      console.log(`❌ [DEBUG] Aucun client n'a trouvé de données`);
      return lastResult;
    };

    // ✅ SÉCURITÉ : Récupérer l'organisation de l'utilisateur connecté (TOUJOURS depuis la session)
    // Pour les clients : on force leur organisation (pas de confiance au body.org_id)
    // Pour les staffs : on accepte l'org_id du body si fourni, sinon on résout via resolveActiveOrg
    let orgId: string | null = null;
    let orgName: string | null = null;

    console.log('🔍 [DEBUG] isStaff:', isStaff);
    console.log('🔍 [DEBUG] org_id depuis body:', body.org_id);

    if (isStaff) {
      // Staff : peut spécifier une organisation dans le body
      const requestedOrgId = typeof body.org_id === 'string' && body.org_id.trim().length > 0 ? body.org_id.trim() : null;
      
      if (requestedOrgId) {
        console.log('🔍 [DEBUG] Staff - org_id fourni dans body:', requestedOrgId);
        orgId = requestedOrgId;
      } else {
        console.log('🔍 [DEBUG] Staff - pas d\'org_id, utilisation de resolveActiveOrg...');
        orgId = await resolveActiveOrg(supabase);
        console.log('🔍 [DEBUG] Staff - Organisation résolue:', orgId);
      }
    } else {
      // ✅ CLIENT : Ignorer body.org_id et forcer l'organisation de l'utilisateur
      console.log('🔍 [DEBUG] Client - résolution automatique de l\'organisation (ignorer body.org_id)');
      
      // Résoudre via resolveActiveOrg (qui lit organization_members)
      orgId = await resolveActiveOrg(supabase);
      
      if (!orgId) {
        // Fallback : essayer via organization_members directement
        const { data: member } = await supabase
          .from('organization_members')
          .select('org_id')
          .eq('user_id', user.id)
          .single();
        
        orgId = member?.org_id || null;
      }
      
      console.log('🔍 [DEBUG] Client - Organisation finale:', orgId);
      
      // ⚠️ Si un client essaie de forcer un org_id différent, on l'ignore et on log
      if (body.org_id && body.org_id !== orgId) {
        console.warn('⚠️ [SÉCURITÉ] Tentative de forcer org_id par un client:', {
          userId: user.id,
          userEmail: user.email,
          requestedOrgId: body.org_id,
          actualOrgId: orgId
        });
      }
    }

    if (!orgId) {
      console.error("❌ [DEBUG] Aucune organisation trouvée pour l'utilisateur:", user.id);
      return NextResponse.json({ error: 'Organisation non trouvée' }, { status: 400 });
    }

    console.log('✅ [DEBUG] Organisation finale:', orgId);

    const salarieMatricule = (body.salarie_matricule ?? '').toString().trim();
    console.log('🔍 [DEBUG] Body original salarie_matricule:', body.salarie_matricule);
    console.log('🔍 [DEBUG] Matricule après trim:', salarieMatricule);
    console.log('🔍 [DEBUG] Type de matricule:', typeof salarieMatricule);
    console.log('🔍 [DEBUG] Longueur matricule:', salarieMatricule.length);
    console.log('🔍 [DEBUG] Staff user:', isStaff);
    console.log('🔍 [DEBUG] OrgId à utiliser:', orgId);
    console.log('🔍 [DEBUG] Nombre de clients Supabase:', clients.length);
    console.log('🔍 [DEBUG] Service role disponible:', !!serviceSupabase);

    if (!salarieMatricule) {
      console.error('❌ [DEBUG] Matricule vide après trim');
      return NextResponse.json({ error: 'Matricule salarié manquant' }, { status: 400 });
    }

    console.log('🔍 [DEBUG] Début recherche employé...');
    const { data: employee, error: empError } = await runOnClients<EmployeeRow>(async (client, index) => {
      console.log(`🔍 [DEBUG] Essai client ${index + 1}/${clients.length}`);
      const isServiceRole = client === serviceSupabase;
      console.log(`🔍 [DEBUG] Client service role: ${isServiceRole}`);
      
      const { data, error } = await client
        .from('salaries')
        .select('id, code_salarie, nom, prenom, adresse_mail, employer_id')
        .eq('code_salarie', salarieMatricule)
        .eq('employer_id', orgId)
        .maybeSingle();
      
      console.log(`🔍 [DEBUG] Client ${index + 1} - Data:`, data);
      console.log(`🔍 [DEBUG] Client ${index + 1} - Error:`, error);
      
      return { data: (data as EmployeeRow | null), error };
    });

    console.log('🔍 [DEBUG] Résultat final recherche employé:', { employee, empError });

    if (empError || !employee) {
      console.log('❌ [DEBUG] Employé non trouvé, recherche d\'exemples...');
      
      // Essayer avec chaque client pour voir ce qui est disponible
      for (let i = 0; i < clients.length; i++) {
        const client = clients[i];
        const isServiceRole = client === serviceSupabase;
        console.log(`🔍 [DEBUG] Recherche exemples avec client ${i + 1} (service role: ${isServiceRole})`);
        
        // Tous les employés de cette org
        const { data: allEmployeesInOrg, error: allEmpError } = await client
          .from('salaries')
          .select('code_salarie, nom, prenom, employer_id')
          .eq('employer_id', orgId)
          .limit(10);
        console.log(`🔍 [DEBUG] Client ${i + 1} - Employés dans org ${orgId}:`, allEmployeesInOrg);
        console.log(`🔍 [DEBUG] Client ${i + 1} - Erreur:`, allEmpError);
        
        // Recherche par matricule sans filtrer par org
        const { data: globalSearch, error: globalError } = await client
          .from('salaries')
          .select('code_salarie, nom, prenom, employer_id')
          .eq('code_salarie', salarieMatricule)
          .limit(5);
        console.log(`🔍 [DEBUG] Client ${i + 1} - Recherche globale matricule ${salarieMatricule}:`, globalSearch);
        console.log(`🔍 [DEBUG] Client ${i + 1} - Erreur recherche globale:`, globalError);
        
        // Premier employé de n'importe quelle org pour voir la structure
        const { data: firstEmployee, error: firstError } = await client
          .from('salaries')
          .select('code_salarie, nom, prenom, employer_id')
          .limit(1)
          .maybeSingle();
        console.log(`🔍 [DEBUG] Client ${i + 1} - Premier employé (structure):`, firstEmployee);
        console.log(`🔍 [DEBUG] Client ${i + 1} - Erreur premier employé:`, firstError);
      }

      return NextResponse.json({ error: 'Employé non trouvé' }, { status: 404 });
    }

    const { data: organization, error: orgError } = await runOnClients<OrganizationRow>(async (client) => {
      const { data, error } = await client
        .from('organizations')
        .select(`
          name,
          organization_details!inner(
            email_notifs,
            email_notifs_cc,
            prenom_contact,
            code_employeur
          )
        `)
        .eq('id', orgId)
        .maybeSingle();
      return { data: (data as OrganizationRow | null), error };
    });

    if (orgError || !organization) {
      console.error('Erreur récupération organisation:', orgError);
      return NextResponse.json({ error: 'Informations organisation non trouvées' }, { status: 404 });
    }

    orgName = organization.name;

  // Récupérer les informations de la production
  let production: ProductionRow | null = null;
  let prodError: PostgrestError | null = null;

    if (body.production_id) {
      // Si un ID de production est fourni, récupérer par ID (production existante)
      console.log('Recherche production par ID:', body.production_id);
      const result = await runOnClients<ProductionRow>(async (client) => {
        const { data, error } = await client
          .from('productions')
          .select('id, name, reference, org_id')
          .eq('id', body.production_id)
          .eq('org_id', orgId)
          .maybeSingle();
        return { data: (data as ProductionRow | null), error };
      });
      
      production = result.data;
      prodError = result.error;
      console.log('Résultat recherche production par ID:', { production, prodError });
    } else if (body.spectacle) {
      // Sinon, rechercher par nom (pour créer une nouvelle production)
      console.log('Recherche production par nom:', body.spectacle);
      const result = await runOnClients<ProductionRow>(async (client) => {
        const { data, error } = await client
          .from('productions')
          .select('id, name, reference, org_id')
          .eq('org_id', orgId)
          .eq('name', body.spectacle)
          .maybeSingle();
        return { data: (data as ProductionRow | null), error };
      });
      
      production = result.data;
      prodError = result.error;
      console.log('Résultat recherche production par nom:', { production, prodError });
    }

    // Si un ID de production était fourni mais que la production n'existe pas, retourner une erreur
    if (body.production_id && (prodError || !production)) {
      console.error('Production non trouvée avec ID:', body.production_id, prodError);
      return NextResponse.json({ error: 'Production introuvable' }, { status: 404 });
    }

    if (!body.production_id && (!production || prodError)) {
      if (!body.spectacle) {
        return NextResponse.json({ error: 'Nom du spectacle requis' }, { status: 400 });
      }

      console.log('Production non trouvée, création automatique...');
      
      const newProductionData = {
        id: uuidv4(),
        org_id: orgId, // Utiliser l'organisation du contrat
        name: body.spectacle,
        reference: body.numero_objet || null, // Ne pas générer de faux numéro
        declaration_date: null, // À remplir manuellement après déclaration à France Travail
        sent_date: null,
        declared_fts: false, // Par défaut non déclarée
        prod_type: 'Spectacle vivant', // Valeur par défaut
        director: null,
        created_at: new Date().toISOString()
      };
      
      console.log('Données de la nouvelle production:', newProductionData);
      
      const writeClient: SupabaseClient = serviceSupabase ?? supabase;

      let creationResult = await writeClient
        .from('productions')
        .insert(newProductionData)
        .select('id, name, reference, org_id')
        .single();
        
      if (creationResult.error && serviceSupabase && writeClient !== serviceSupabase) {
        console.error('Erreur création nouvelle production:', creationResult.error);
        creationResult = await serviceSupabase
          .from('productions')
          .insert(newProductionData)
          .select('id, name, reference, org_id')
          .single();
      }
      
      if (creationResult.error || !creationResult.data) {
        console.error('Erreur création production avec service_role:', creationResult.error);
        return NextResponse.json({ error: 'Impossible de créer la production' }, { status: 500 });
      }
      
      production = creationResult.data as ProductionRow;
      console.log('Production créée avec succès:', production);
    }

    if (!production) {
      console.error('Production introuvable après résolution/creation.');
      return NextResponse.json({ error: 'Production introuvable' }, { status: 500 });
    }

    // Préparer les données du contrat selon la structure réelle de cddu_contracts
  const isTechnicienCategorie = typeof body.categorie === 'string' && body.categorie.toLowerCase().includes('tech');

  const contractData = {
      id: contractId,
      org_id: orgId,
      employee_id: employee.id,
      production_id: production.id,
      contract_number: contractNumber,
      employee_matricule: employee.code_salarie,
      employee_name: `${employee.prenom} ${employee.nom}`.trim(),
      production_name: production.name,
      role: body.profession_label || body.profession,
      start_date: body.date_debut,
      end_date: body.date_fin,
      hours: body.heures_total ? parseFloat(body.heures_total.toString()) : null,
      gross_pay: body.montant ? parseFloat(body.montant.toString()) : null,
      net_pay: null,
      contract_pdf_s3_key: null,
      payslips_count: 0,
      notes: body.notes || null,
      created_at: new Date().toISOString(),
      reference: contractNumber,
      
      // Champs obligatoires basés sur la structure existante
      structure: orgName, // Utiliser le nom de l'organisation récupéré
      etat_de_la_demande: "Reçue",
      contrat_signe: "Non",
      dpae: "À faire",
      etat_de_la_paie: "À traiter",
      aem: "À traiter",
      matricule: employee.code_salarie,
      salaries: `${employee.prenom} ${employee.nom}`.trim(),
      nom_du_spectacle: production.name,
      profession: body.profession_label || body.profession,
      categorie_pro: body.categorie || "Artiste",
      debut_contrat: body.date_debut,
      fin_contrat: body.date_fin,
      salaire: body.montant ? parseFloat(body.montant.toString()) : null,
      type_salaire: body.type_salaire || "Brut",
      // Utiliser les valeurs passées dans body si elles existent (pour RG), sinon valeurs par défaut CDDU
      type_de_contrat: body.type_de_contrat || "CDD d'usage",
      type_d_embauche: body.type_d_embauche || "Intermittent du spectacle",
      date_de_reception_de_la_demande: new Date().toLocaleDateString('fr-FR'),
      brut: body.montant ? parseFloat(body.montant.toString()) : null,
      fin_reelle: body.date_fin,
      motif_fin_contrat: "Fin de CDD",
      contrat_signe_par_employeur: "Non",
      multi_mois: body.multi_mois ? "Oui" : "Non",
      virement_effectue: "Non",
      analytique: production.name,
      paniers_repas: body.panier_repas || "Non",
      indemnite_hebergement: "Non",
      mineur_entre_16_et_18: "Non",
      heure_traitement_demande: new Date().toLocaleTimeString('fr-FR', { hour12: false }),
      
      // Salaires par date (JSONB)
      salaires_par_date: body.salaires_par_date || null,
      
      // Champs numériques avec valeurs par défaut
      cachets_representations: body.nb_representations ? body.nb_representations.toString() : "0",
      services_repetitions: body.nb_services_repetition ? body.nb_services_repetition.toString() : "0",
      nombre_d_heures: body.heures_total ? parseFloat(body.heures_total.toString()) : null,
      nombre_paniers_repas: body.panier_repas === "Oui" ? "1.0" : "0.0",
      
      // Champs texte optionnels
      jours_representations: body.dates_representations || null,
      jours_repetitions: body.dates_repetitions || null,
  jours_travail: body.jours_travail || null,
  // Pour les techniciens, dupliquer aussi dans jours_travail_non_artiste
  jours_travail_non_artiste: isTechnicienCategorie ? (body.jours_travail || null) : null,
      n_objet: production.reference || body.numero_objet || null,
      objet_spectacle: production.reference || body.numero_objet || null,
      heures_annexe_8: body.nb_heures_annexes ? parseFloat(body.nb_heures_annexes.toString()) : null
    };

    console.log("Données du contrat préparées:", contractData);
    console.log("🔍 [API] contractData.salaires_par_date:", contractData.salaires_par_date);

    // TEMPORAIRE : Utiliser directement service_role pour supporter salaires_par_date
    // TODO: Mettre à jour la fonction RPC create_cddu_contract pour inclure ce champ
    console.log('💡 [API] Insertion directe via service_role pour supporter salaires_par_date...');
    
    if (!serviceSupabase) {
      console.error('❌ [API] Service role non configuré');
      return NextResponse.json({ error: 'Configuration Supabase incomplète' }, { status: 500 });
    }
    
    const { data: contract, error } = await serviceSupabase
      .from('cddu_contracts')
      .insert(contractData)
      .select()
      .single();

    let finalContract = contract;

    if (error) {
      console.error('❌ [API] Erreur insertion contrat via service_role:', error);
      return NextResponse.json({ error: error.message }, { status: 500 });
    }
    
    console.log('✅ [API] Contrat inséré avec succès, ID:', finalContract?.id);

    /* ANCIEN CODE avec RPC - désactivé temporairement
    // Essayer d'abord la fonction RPC pour contourner les politiques RLS
    const { data: contract, error } = await supabase
      .rpc('create_cddu_contract', { contract_data: contractData });

    let finalContract = contract;

    if (error) {
      console.error('Erreur insertion contrat via RPC:', error);
      
      // Si la RPC échoue à cause des politiques RLS, essayer avec le client service_role
      console.log('Tentative avec le client service_role...');
      
      const serviceSupabase = createClient(
        process.env.NEXT_PUBLIC_SUPABASE_URL!,
        process.env.SUPABASE_SERVICE_ROLE_KEY!
      );
      
      const { data: serviceContract, error: serviceError } = await serviceSupabase
        .from('cddu_contracts')
        .insert(contractData)
        .select()
        .single();
        
      if (serviceError) {
        console.error('Erreur avec service_role également:', serviceError);
        return NextResponse.json({ error: serviceError.message }, { status: 500 });
      }
      
      finalContract = serviceContract;
    }
    */

    // Créer une note système automatique pour tracer la création du contrat
    try {
      const now = new Date();
      const dateStr = now.toLocaleDateString('fr-FR');
      const timeStr = now.toLocaleTimeString('fr-FR');
      
      // Récupérer le prénom et le rôle de l'utilisateur
      const userFirstName = user.user_metadata?.first_name || user.user_metadata?.display_name?.split(' ')[0] || 'Utilisateur';
      
      let userRole = null;
      if (!isStaff) {
        // Pour les clients, récupérer leur rôle dans l'organisation
        try {
          const { data: memberData } = await supabase
            .from('organization_members')
            .select('role')
            .eq('org_id', orgId)
            .eq('user_id', user.id)
            .eq('revoked', false)
            .maybeSingle();
          userRole = memberData?.role || null;
        } catch (err) {
          console.warn('Erreur récupération rôle membre:', err);
        }
      }
      
      const systemNoteContent = isStaff 
        ? `Demande créée par le Staff Odentas le ${dateStr} à ${timeStr}`
        : `Demande créée via l'Espace Paie par ${userFirstName}${userRole ? ` (${userRole})` : ''} le ${dateStr} à ${timeStr}`;

      const systemNotePayload: NoteInsert = {
        contract_id: contractId,
        organization_id: orgId,
        content: systemNoteContent,
        source: 'Système',
      };

      const { error: systemNoteError } = await supabase
        .from('notes')
        .insert([systemNotePayload]);

      if (systemNoteError) {
        console.warn('Erreur insertion note système avec client standard, tentative service_role:', systemNoteError);
        const serviceSupabase = createClient(
          process.env.NEXT_PUBLIC_SUPABASE_URL!,
          process.env.SUPABASE_SERVICE_ROLE_KEY!
        );
        const { error: srSystemNoteError } = await serviceSupabase
          .from('notes')
          .insert([systemNotePayload]);
        if (srSystemNoteError) {
          console.error('Échec insertion note système même avec service_role:', srSystemNoteError);
        }
      }
    } catch (systemNoteCatchErr) {
      console.error('Exception lors de la création de la note système:', systemNoteCatchErr);
    }

    // Si une note a été fournie lors de la création, créer également une entrée dans la table `notes`
    try {
      const rawNote = typeof body.notes === 'string' ? body.notes.trim() : '';
      if (rawNote) {
        const notePayload: NoteInsert = {
          contract_id: contractId,
          organization_id: orgId,
          content: rawNote,
          source: 'Client',
        };
        const { error: noteError } = await supabase
          .from('notes')
          .insert([notePayload]);

        if (noteError) {
          console.warn('Erreur insertion note avec client standard, tentative service_role:', noteError);
          const serviceSupabase = createClient(
            process.env.NEXT_PUBLIC_SUPABASE_URL!,
            process.env.SUPABASE_SERVICE_ROLE_KEY!
          );
          const { error: srNoteError } = await serviceSupabase
            .from('notes')
            .insert([notePayload]);
          if (srNoteError) {
            console.error('Échec insertion note même avec service_role:', srNoteError);
          }
        }
      }
    } catch (noteCatchErr) {
      console.error('Exception lors de la création de la note liée au contrat:', noteCatchErr);
    }

    // Créer une note spécifique pour les paniers repas si fournie
    try {
      const panierRepasNote = typeof body.panier_repas_note === 'string' ? body.panier_repas_note.trim() : '';
      if (panierRepasNote) {
        const panierNotePayload: NoteInsert = {
          contract_id: contractId,
          organization_id: orgId,
          content: panierRepasNote,
          source: 'Système',
        };
        const { error: panierNoteError } = await supabase
          .from('notes')
          .insert([panierNotePayload]);

        if (panierNoteError) {
          console.warn('Erreur insertion note paniers repas avec client standard, tentative service_role:', panierNoteError);
          const serviceSupabase = createClient(
            process.env.NEXT_PUBLIC_SUPABASE_URL!,
            process.env.SUPABASE_SERVICE_ROLE_KEY!
          );
          const { error: srPanierNoteError } = await serviceSupabase
            .from('notes')
            .insert([panierNotePayload]);
          if (srPanierNoteError) {
            console.error('Échec insertion note paniers repas même avec service_role:', srPanierNoteError);
          }
        }
      }
    } catch (panierNoteCatchErr) {
      console.error('Exception lors de la création de la note paniers repas:', panierNoteCatchErr);
    }

    // Correction de persistance: certains champs optionnels peuvent ne pas être renseignés par la RPC
    // Assurer que jours_travail (jours de travail technicien) est bien enregistré si fourni
    try {
      const providedJoursTravail = typeof body.jours_travail === 'string' && body.jours_travail.trim().length > 0 ? body.jours_travail.trim() : null;
      const finalHasJoursTravail = (finalContract as any)?.jours_travail ?? null;
      if (providedJoursTravail && !finalHasJoursTravail) {
        const serviceClient = createClient(
          process.env.NEXT_PUBLIC_SUPABASE_URL!,
          process.env.SUPABASE_SERVICE_ROLE_KEY!
        );
        const { error: fixErr } = await serviceClient
          .from('cddu_contracts')
          .update({ jours_travail: providedJoursTravail })
          .eq('id', contractId);
        if (fixErr) {
          console.warn('⚠️ Échec mise à jour jours_travail post-insert:', fixErr);
        } else {
          // Mettre à jour la valeur locale pour la réponse
          if (finalContract) {
            (finalContract as any).jours_travail = providedJoursTravail;
          }
        }
      }
    } catch (fixCatch) {
      console.warn('⚠️ Exception lors de la correction jours_travail:', fixCatch);
    }

    // Envoyer les notifications par email après la création réussie du contrat
    try {
      const shouldSendEmail = body.send_email_confirmation !== false; // envoi par défaut, sauf si explicitement à false
      if (shouldSendEmail) {
        await sendContractNotifications(contractData, organization);
      } else {
        console.log('Email confirmation disabled by user choice, skipping notifications.');
      }
    } catch (emailError) {
      console.error('Erreur envoi notifications email:', emailError);
      // Ne pas faire échouer la création du contrat si l'envoi d'email échoue
    }

    return NextResponse.json({ 
      success: true, 
      contract: finalContract,
      message: 'Contrat créé avec succès'
    });

  } catch (error) {
    console.error('Erreur lors de la création du contrat:', error);
    return NextResponse.json({ error: 'Erreur interne du serveur' }, { status: 500 });
  }
}

function generateContractReference(): string {
  const letters = 'ABCDEFGHIKLMNPQRSTUVWXYZ'; // sans O
  const digits = '123456789'; // sans 0
  const pool = letters + digits;
  const pick = (source: string) => source[Math.floor(Math.random() * source.length)];

  while (true) {
    let ref = '';
    for (let i = 0; i < 8; i += 1) {
      ref += pick(pool);
    }
    if (ref.startsWith('RG')) continue;
    if (!/[A-Z]/.test(ref)) continue;
    if (!/[1-9]/.test(ref)) continue;
    return ref;
  }
}