import { NextResponse, NextRequest } from "next/server";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { createClient } from "@supabase/supabase-js";
import { cookies } from "next/headers";
import { randomUUID } from "crypto";
import { getS3SignedUrlIfExists } from "@/lib/aws-s3";
import { sendContractUpdateNotifications, sendContractCancellationNotifications } from "@/lib/emailService";

// Force dynamic rendering and disable revalidation cache for this proxy
export const dynamic = "force-dynamic";
export const revalidate = 0;
export const runtime = "nodejs";

const UPSTREAM_BASE =
  process.env.STRUCTURE_API_BASE_URL ||
  "https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default";
const PATH_PREFIX = process.env.STRUCTURE_API_PATH_PREFIX ?? "";

function b64(s: string) {
  return Buffer.from(s, "utf8").toString("base64");
}

/** Résout l'organisation active 100% server-side (sans cookies/localStorage) */
async function resolveOrganization(supabase: any, session: any) {
  const userId = session?.user?.id;
  const userMeta = session?.user?.user_metadata || {};
  const appMeta = session?.user?.app_metadata || {};

  // Priorité côté serveur: table staff_users (source de vérité)
  let isStaff = false;
  try {
    const { data: staffRow } = await supabase.from('staff_users').select('is_staff').eq('user_id', userId).maybeSingle();
    isStaff = !!staffRow?.is_staff;
  } catch (e) {
    // Si la requête échoue, fallback sur metadata de session
    isStaff = userMeta.is_staff === true || userMeta.role === 'staff' || (Array.isArray(appMeta?.roles) && appMeta.roles.includes('staff'));
  }

  // Helper: retrouver le nom structure_api à partir d'un org_id
  async function getOrgById(orgId: string) {
    const { data: org, error } = await supabase
      .from("organizations")
      .select("id, structure_api")
      .eq("id", orgId)
      .single();
    if (error || !org?.structure_api) throw new Error("Organisation introuvable");
    return { id: org.id, name: org.structure_api };
  }

  if (isStaff) {
    // Simplify staff handling: staff sees all data. Return a null id to indicate
    // global staff access. Do not attempt to pick an active org.
    return { id: null, name: "Staff Access", isStaff: true } as const;
  }

  // Utilisateur client : lire org depuis organization_members -> organizations (server-side)
  const { data: member, error: mErr } = await supabase
    .from("organization_members")
    .select("org_id")
    .eq("user_id", userId)
    .single();
  if (mErr || !member?.org_id) throw new Error("Aucune organisation associée à l'utilisateur");

  const org = await getOrgById(member.org_id);
  return { ...org, isStaff: false } as const;
}

export async function GET(req: NextRequest, { params }: { params: { id: string } }) {
  const requestId = randomUUID();
  try {
    const contractId = params?.id;
    if (!contractId) return NextResponse.json({ error: "missing_id" }, { status: 400 });

    const supabase = createRouteHandlerClient({ cookies });
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) {
      return NextResponse.json(
        { error: "unauthorized", message: "Vous devez être connecté pour accéder à cette ressource" },
        { status: 401 }
      );
    }

    // Résoudre l'organisation (staff/client)
    const org = await resolveOrganization(supabase, session);

    // 1. Essayer de trouver le contrat dans Supabase (table cddu_contracts)
    // If staff (org.isStaff === true), use the service-role admin client to bypass RLS
    // for reads so staff can see all rows, regardless of active org selection.
    let cddu: any = null;
    let cdduError: any = null;
    if (org.isStaff) {
      // ADMIN client requires SUPABASE_SERVICE_ROLE_KEY and NEXT_PUBLIC_SUPABASE_URL
      const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
      const q = admin.from("cddu_contracts").select("*").eq("id", contractId);
      const res = await q.maybeSingle();
      cddu = res.data;
      cdduError = res.error;
    } else {
      let cdduQuery = supabase.from("cddu_contracts").select("*").eq("id", contractId);
      if (org.id) cdduQuery = cdduQuery.eq("org_id", org.id);
      const res = await cdduQuery.maybeSingle();
      cddu = res.data;
      cdduError = res.error;
    }
    if (cdduError) {
      return NextResponse.json({ error: cdduError.message }, { status: 500 });
    }
    if (cddu) {
      // Helper pour slugifier le nom de l'organisation
      const slugify = (s: string) =>
        s
          .toLowerCase()
          .normalize("NFD")
          .replace(/[\u0300-\u036f]/g, "") // Enlever les accents
          .replace(/[^a-z0-9]+/g, "-")
          .replace(/(^-|-$)/g, "")
          .slice(0, 200);
      
      // Générer l'URL signée S3 si la clé est présente
      let pdfUrl: string | undefined = undefined;
      let s3Key = cddu.contract_pdf_s3_key;
      
      // Si contract_pdf_s3_key est vide, essayer de construire le chemin à partir de structure + contract_number
      if (!s3Key && cddu.structure && cddu.contract_number) {
        const orgSlug = slugify(cddu.structure);
        s3Key = `contracts/${orgSlug}/${cddu.contract_number}.pdf`;
      }
      
      if (s3Key) {
        try {
          const maybe = await getS3SignedUrlIfExists(s3Key);
          pdfUrl = maybe ?? undefined;
        } catch (e) {
          pdfUrl = undefined;
        }
      }
      // Mapping vers ContratDetail attendu par le front
      const isMulti = cddu.multi_mois === "Oui" || cddu.multi_mois === true;
      const td = String(cddu.type_d_embauche || "").toLowerCase();
      const isRG = td.includes("régime général") || td.includes("regime general") || td === "rg";
      const professionCode = (() => {
        const candidates = [
          (cddu as any).profession_code,
          (cddu as any).codeprofession,
          (cddu as any).code_profession,
          (cddu as any).codeemploi,
        ];
        for (const raw of candidates) {
          if (typeof raw === "string" && raw.trim()) return raw.trim();
        }
        const profSource = (cddu.profession || cddu.role || "").toString();
        const match = profSource.match(/([A-Z]{3}\d{3})/);
        return match ? match[1] : undefined;
      })();

      const detail = {
        id: cddu.id,
        numero: cddu.contract_number,
        regime: isRG ? "RG" : (isMulti ? "CDDU_MULTI" : "CDDU_MONO"),
        is_multi_mois: isMulti,
        salarie: { nom: cddu.employee_name },
        salarie_matricule: cddu.employee_matricule,
        production: cddu.production_name || cddu.structure || "",
        objet: cddu.objet_spectacle || cddu.nom_du_spectacle || undefined,
        profession: cddu.profession || cddu.role || "",
        profession_code: professionCode,
        categorie_prof: cddu.categorie_pro || undefined,
        type_salaire: cddu.type_salaire || undefined,
        salaire_demande: cddu.salaire || cddu.gross_pay || undefined,
        salaires_par_date: cddu.salaires_par_date || undefined,
        date_debut: cddu.start_date,
        date_fin: cddu.end_date,
        panier_repas: cddu.paniers_repas,
        pdf_contrat: pdfUrl ? { available: true, url: pdfUrl } : { available: false },
        pdf_avenant: { available: false },
        pdf_paie: cddu.bulletin_paie ? { available: true, url: cddu.bulletin_paie.split('(')[1]?.replace(')', '').trim() } : { available: false },
        etat_traitement: cddu.etat_de_la_paie === "Traitée" ? "termine" : cddu.etat_de_la_paie === "En cours" ? "en_cours" : "a_traiter",
        virement_effectue: cddu.virement_effectue,
        salaire_net_avant_pas: cddu.net,
        net_a_payer_rib: cddu.net_apres_pas,
        salaire_brut: cddu.brut,
        cout_employeur: cddu.cout_employeur,
        precisions_salaire: cddu.precisions_salaire,
        etat_demande: cddu.etat_de_la_demande,
        contrat_signe_employeur: cddu.contrat_signe_par_employeur === "Oui" ? "oui" : "non",
        contrat_signe_salarie: cddu.contrat_signe === "Oui" ? "oui" : "non",
        etat_contrat: undefined,
        dpae: cddu.dpae,
        aem: cddu.aem,
        jours_travailles: cddu.jours_travail_non_artiste ? Number(cddu.jours_travail_non_artiste) : undefined,
        jours_travail: cddu.jours_travail || undefined,
        jours_travail_non_artiste: cddu.jours_travail_non_artiste || undefined,
        dates_representations: cddu.jours_representations || undefined,
        dates_repetitions: cddu.jours_repetitions || undefined,
        nb_representations: cddu.cachets_representations ? Number(cddu.cachets_representations) : undefined,
        nb_services_repetitions: cddu.services_repetitions ? Number(cddu.services_repetitions) : undefined,
        nb_heures_repetitions: cddu.heures_de_repet ? Number(cddu.heures_de_repet) : undefined,
        nb_heures_annexes: cddu.heures_annexe_8 ? Number(cddu.heures_annexe_8) : undefined,
        nb_cachets_aem: cddu.cachets ? Number(cddu.cachets) : undefined,
        nb_heures_aem: cddu.nombre_d_heures ? Number(cddu.nombre_d_heures) : undefined,
        // Temps de travail réel (nouveaux champs informatifs)
        jours_travail_reel: cddu.jours_travail_reel || undefined,
        jours_travail_non_artiste_reel: cddu.jours_travail_non_artiste_reel || undefined,
        nb_representations_reel: cddu.nb_representations_reel ? Number(cddu.nb_representations_reel) : undefined,
        dates_representations_reel: cddu.dates_representations_reel || undefined,
        nb_services_repetitions_reel: cddu.nb_services_repetitions_reel ? Number(cddu.nb_services_repetitions_reel) : undefined,
        nb_heures_repetitions_reel: cddu.nb_heures_repetitions_reel ? Number(cddu.nb_heures_repetitions_reel) : undefined,
        dates_repetitions_reel: cddu.dates_repetitions_reel || undefined,
        nb_heures_annexes_reel: cddu.nb_heures_annexes_reel ? Number(cddu.nb_heures_annexes_reel) : undefined,
        nb_cachets_aem_reel: cddu.nb_cachets_aem_reel ? Number(cddu.nb_cachets_aem_reel) : undefined,
        nb_heures_aem_reel: cddu.nb_heures_aem_reel ? Number(cddu.nb_heures_aem_reel) : undefined,
        created_at: cddu.created_at,
        updated_at: cddu.updated_at,
      };
      return NextResponse.json(detail, { status: 200 });
    }

    // 2. Sinon, fallback sur l'upstream (RG ou autre)
    const upstream = `${UPSTREAM_BASE}${PATH_PREFIX}/contrats/${encodeURIComponent(contractId)}?_t=${Date.now()}`;
    const headers = new Headers({
      Accept: "application/json",
      "x-forwarded-from": "odentas-espace-paie",
      "x-request-id": requestId,
    });
    // Only include organization-identifying headers when a real organization is selected.
    if (org.id && org.name) {
      headers.set("x-active-org-id", org.id);
      headers.set("x-company-name", org.name);
      headers.set("x-company-name-b64", b64(org.name));
    }
    if (process.env.STRUCTURE_API_TOKEN) {
      headers.set("authorization", `Bearer ${process.env.STRUCTURE_API_TOKEN}`);
    }
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(new Error("timeout")), 10_000);
    const res = await fetch(upstream, {
      method: "GET",
      headers: Object.fromEntries(headers.entries()),
      cache: "no-store",
      signal: controller.signal,
    });
    clearTimeout(timeout);
    if (res.status === 404) {
      const body = await res.text().catch(() => "");
      return NextResponse.json({ error: "not_found", message: "Contrat non trouvé ou accès non autorisé" }, { status: 404 });
    }
    if (!res.ok) {
      const text = await res.text().catch(() => "");
      return NextResponse.json({ error: "upstream_error", status: res.status, body: text, requestId }, { status: 502 });
    }
    const data = await res.json();
    
    // Si l'upstream retourne un contract_pdf_s3_key, générer l'URL signée
    if (data.contract_pdf_s3_key && typeof data.contract_pdf_s3_key === 'string') {
      try {
        const signedUrl = await getS3SignedUrlIfExists(data.contract_pdf_s3_key);
        if (signedUrl) {
          data.pdf_contrat = { available: true, url: signedUrl };
        }
      } catch (e) {
        console.error('Error generating S3 URL for upstream contract:', e);
      }
    }
    
    const response = NextResponse.json(data, { status: 200 });
    response.headers.set("x-request-id", requestId);
    return response;
  } catch (err: any) {
    const msg = String(err?.message || err || "");
    if (msg.toLowerCase().includes("timeout") || err?.name === "AbortError") {
      console.error("⏳ CONTRACT TIMEOUT:", { requestId, msg });
      return NextResponse.json({ error: "gateway_timeout", message: "Upstream timeout", requestId }, { status: 504 });
    }
    console.error("💥 ERROR in contract route:", { requestId, msg });
    return NextResponse.json(
      { error: "internal_server_error", message: "Une erreur est survenue lors de la récupération du contrat", requestId },
      { status: 500 }
    );
  }
}

export async function PATCH(req: NextRequest, { params }: { params: { id: string } }) {
  const requestId = randomUUID();
  try {
    const contractId = params?.id;
    if (!contractId) return NextResponse.json({ error: "missing_id" }, { status: 400 });

    const supabase = createRouteHandlerClient({ cookies });
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) return NextResponse.json({ error: "unauthorized" }, { status: 401 });

    // Résoudre l'organisation (même logique que GET)
    const org = await resolveOrganization(supabase, session);

    // Corps tel quel (JSON string)
    const body = await req.text();
    
    // Debug: Log le contenu du body pour voir ce qui est envoyé
    console.log("🔍 PATCH REQUEST DEBUG:", { contractId, body, requestId });

    // 1. Vérifier si le contrat existe dans Supabase
    let cddu: any = null;
    let isSupabaseOnly = false;
    
    if (org.isStaff) {
      // Staff avec accès admin
      const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
      const { data } = await admin.from("cddu_contracts").select("*").eq("id", contractId).maybeSingle();
      cddu = data;
    } else {
      // Client avec accès limité à son organisation
      const { data } = await supabase.from("cddu_contracts").select("*").eq("id", contractId).eq("org_id", org.id).maybeSingle();
      cddu = data;
    }

    if (cddu) {
      isSupabaseOnly = true;
      console.log("📋 CONTRAT SUPABASE TROUVÉ:", { contractId, isSupabaseOnly, requestId });
    }

    // 2. Traitement selon le type de contrat
    if (isSupabaseOnly) {
      // CONTRAT SUPABASE-ONLY : Mise à jour directe dans Supabase
      try {
        const requestBody = JSON.parse(body);
        console.log("🔍 PARSED REQUEST BODY (Supabase-only):", { requestBody, contractId, requestId });
        
        // Mapper les champs appropriés pour la table cddu_contracts
        const supabaseData: any = {};
        
        // Mapper les champs du formulaire vers la table Supabase
        if (requestBody.production !== undefined) {
          supabaseData.production_name = requestBody.production;
          // Ne PAS écraser structure avec la production - structure doit rester l'organisation
        }
        if (requestBody.numero_objet !== undefined) {
          supabaseData.objet_spectacle = requestBody.numero_objet;
        }
        if (requestBody.salarie_matricule !== undefined) {
          supabaseData.employee_matricule = requestBody.salarie_matricule;
        }
        if (requestBody.salarie_nom !== undefined) {
          supabaseData.employee_name = requestBody.salarie_nom;
        }
        if (requestBody.categorie_prof !== undefined) {
          supabaseData.categorie_pro = requestBody.categorie_prof;
        }
        if (requestBody.profession !== undefined) {
          supabaseData.profession = requestBody.profession;
          supabaseData.role = requestBody.profession;
        }
        if (requestBody.date_debut !== undefined) {
          supabaseData.start_date = requestBody.date_debut;
        }
        if (requestBody.date_fin !== undefined) {
          supabaseData.end_date = requestBody.date_fin;
        }
        if (requestBody.nb_representations !== undefined) {
          supabaseData.cachets_representations = requestBody.nb_representations;
        }
        if (requestBody.nb_services_repetition !== undefined) {
          supabaseData.services_repetitions = requestBody.nb_services_repetition;
        }
        if (requestBody.dates_representations !== undefined) {
          supabaseData.jours_representations = requestBody.dates_representations;
        }
        if (requestBody.dates_repetitions !== undefined) {
          supabaseData.jours_repetitions = requestBody.dates_repetitions;
        }
        // Convertir heures + minutes en nombre décimal pour nombre_d_heures
        if (requestBody.heures_travail !== undefined || requestBody.minutes_travail !== undefined) {
          const heures = requestBody.heures_travail || 0;
          const minutes = requestBody.minutes_travail || 0;
          const minutesDecimal = minutes === "30" || minutes === 30 ? 0.5 : 0;
          supabaseData.nombre_d_heures = String(Number(heures) + minutesDecimal);
        }
        if (requestBody.jours_travail !== undefined) {
          supabaseData.jours_travail = requestBody.jours_travail;
        }
        if (requestBody.jours_travail_non_artiste !== undefined) {
          supabaseData.jours_travail_non_artiste = requestBody.jours_travail_non_artiste;
        }
        // Temps de travail réel (informatif pour le client)
        if (requestBody.jours_travail_reel !== undefined) {
          supabaseData.jours_travail_reel = requestBody.jours_travail_reel;
        }
        if (requestBody.nb_representations_reel !== undefined) {
          supabaseData.nb_representations_reel = requestBody.nb_representations_reel;
        }
        if (requestBody.nb_services_repetitions_reel !== undefined) {
          supabaseData.nb_services_repetitions_reel = requestBody.nb_services_repetitions_reel;
        }
        if (requestBody.nb_heures_repetitions_reel !== undefined) {
          supabaseData.nb_heures_repetitions_reel = requestBody.nb_heures_repetitions_reel;
        }
        if (requestBody.nb_heures_annexes_reel !== undefined) {
          supabaseData.nb_heures_annexes_reel = requestBody.nb_heures_annexes_reel;
        }
        if (requestBody.nb_cachets_aem_reel !== undefined) {
          supabaseData.nb_cachets_aem_reel = requestBody.nb_cachets_aem_reel;
        }
        if (requestBody.nb_heures_aem_reel !== undefined) {
          supabaseData.nb_heures_aem_reel = requestBody.nb_heures_aem_reel;
        }
        if (requestBody.type_salaire !== undefined) {
          supabaseData.type_salaire = requestBody.type_salaire;
        }
        
        // Gestion exclusive : soit montant, soit salaires_par_date
        if (requestBody.salaires_par_date !== undefined) {
          if (requestBody.salaires_par_date === null) {
            // On supprime salaires_par_date
            supabaseData.salaires_par_date = null;
          } else {
            // On définit salaires_par_date et on efface montant
            supabaseData.salaires_par_date = requestBody.salaires_par_date;
            supabaseData.gross_pay = null;
            supabaseData.salaire = null;
          }
        } else if (requestBody.montant !== undefined) {
          if (requestBody.montant === null) {
            // On supprime montant
            supabaseData.gross_pay = null;
            supabaseData.salaire = null;
          } else {
            // On définit montant et on efface salaires_par_date
            supabaseData.gross_pay = requestBody.montant;
            supabaseData.salaire = requestBody.montant;
            supabaseData.salaires_par_date = null;
          }
        }
        
        if (requestBody.panier_repas !== undefined) {
          supabaseData.paniers_repas = requestBody.panier_repas;
        }
        if (requestBody.reference !== undefined) {
          supabaseData.contract_number = requestBody.reference;
          supabaseData.reference = requestBody.reference;
        }
        // NE PAS mettre notes dans supabaseData - on les gère séparément dans la table notes
        // if (requestBody.notes !== undefined) {
        //   supabaseData.notes = requestBody.notes;
        // }
        if (requestBody.multi_mois !== undefined) {
          supabaseData.multi_mois = requestBody.multi_mois ? "Oui" : "Non";
        }
        
        console.log("🔄 SUPABASE DATA TO UPDATE (direct):", { supabaseData, contractId, requestId });
        
        // Mise à jour directe dans Supabase
        let updateResult;
        if (org.isStaff) {
          // Staff avec accès admin
          const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
          updateResult = await admin.from("cddu_contracts").update(supabaseData).eq("id", contractId);
        } else {
          // Client avec accès limité à son organisation
          updateResult = await supabase.from("cddu_contracts").update(supabaseData).eq("id", contractId).eq("org_id", org.id);
        }
        
        console.log("✅ SUPABASE UPDATE RESULT (direct):", { updateResult, contractId, syncedFields: Object.keys(supabaseData), requestId });
        
        if (updateResult.error) {
          throw new Error(`Supabase update error: ${updateResult.error.message}`);
        }
        
        // Si une note a été fournie lors de la modification, créer une entrée dans la table `notes`
        try {
          const rawNote = typeof requestBody.notes === 'string' ? requestBody.notes.trim() : '';
          if (rawNote) {
            // Récupérer le contrat pour avoir l'org_id et contract_number
            let contractForNote;
            if (org.isStaff) {
              const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
              const { data } = await admin.from('cddu_contracts').select('org_id, contract_number').eq('id', contractId).single();
              contractForNote = data;
            } else {
              const { data } = await supabase.from('cddu_contracts').select('org_id, contract_number').eq('id', contractId).single();
              contractForNote = data;
            }
            
            if (contractForNote?.org_id) {
              const notePayload = {
                contract_id: contractId,
                organization_id: contractForNote.org_id,
                content: rawNote,
                source: 'Client',
                author: requestBody.author || undefined,
              };
              
              let noteInsertResult;
              if (org.isStaff) {
                const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
                noteInsertResult = await admin.from('notes').insert([notePayload]);
              } else {
                noteInsertResult = await supabase.from('notes').insert([notePayload]);
              }

              if (noteInsertResult.error) {
                console.warn('⚠️ Erreur insertion note lors de la modification:', noteInsertResult.error);
              } else {
                console.log('✅ Note créée avec succès lors de la modification:', { contractId, noteLength: rawNote.length, requestId });
                
                // Envoyer email de notification pour la note
                try {
                  const { sendUniversalEmailV2 } = await import('@/lib/emailTemplateService');
                  
                  // Récupérer les informations de l'organisation
                  const { data: organization } = await supabase
                    .from('organizations')
                    .select('name, structure_api')
                    .eq('id', contractForNote.org_id)
                    .single();

                  if (organization) {
                    const userName = requestBody.author || org.name || 'Utilisateur inconnu';
                    
                    await sendUniversalEmailV2({
                      type: 'contract-note-added',
                      toEmail: 'paie@odentas.fr',
                      data: {
                        organizationName: organization.name,
                        employerCode: organization.structure_api,
                        contractNumber: contractForNote.contract_number || contractId,
                        userName: userName,
                        noteContent: rawNote,
                        contractId: contractId,
                        ctaUrl: `https://espace-paie.odentas.fr/staff/contrats/${contractId}`,
                      },
                    });
                    
                    console.log('✅ Email de notification envoyé pour la note ajoutée au contrat:', contractId);
                  }
                } catch (emailError) {
                  console.error('❌ Erreur lors de l\'envoi de l\'email de notification de note:', emailError);
                }
              }
            } else {
              console.warn('⚠️ Impossible de récupérer org_id du contrat pour créer la note');
            }
          }
        } catch (noteCatchErr) {
          console.error('Exception lors de la création de la note de modification:', noteCatchErr);
        }
        
        // Envoyer les notifications email après la mise à jour réussie (sauf si explicitement désactivé)
        const shouldSendEmail = requestBody.send_email_confirmation !== false;
        
        try {
          if (!shouldSendEmail) {
            console.log("📧 Email notifications disabled by user (send_email_confirmation=false):", { contractId, requestId });
          }
          
          // Récupérer les données du contrat mis à jour pour les emails
          let contractData;
          if (org.isStaff) {
            const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
            const { data } = await admin.from("cddu_contracts").select("*").eq("id", contractId).single();
            contractData = data;
          } else {
            const { data } = await supabase.from("cddu_contracts").select("*").eq("id", contractId).eq("org_id", org.id).single();
            contractData = data;
          }
          
          if (contractData && shouldSendEmail) {
            // Récupérer les données d'organisation avec tous les détails
            let organizationData;
            if (org.isStaff) {
              // Pour staff, récupérer l'organisation du contrat depuis la DB
              if (contractData.org_id) {
                const { data: orgDetails } = await supabase
                  .from("organizations")
                  .select("*, organization_details(*)")
                  .eq("id", contractData.org_id)
                  .single();
                organizationData = orgDetails || { organization_details: {} };
              } else {
                // Pas d'organisation liée, skip les notifications
                console.log("⚠️ No organization linked to contract, skipping email notifications");
                organizationData = null;
              }
            } else {
              const { data: orgDetails, error: orgError } = await supabase
                .from("organizations")
                .select("*, organization_details(*)")
                .eq("id", org.id)
                .single();
              
              console.log("🔍 [ROUTE DEBUG] Organization data retrieved for non-staff user:", {
                orgId: org.id,
                orgName: org.name,
                orgError,
                hasOrgDetails: !!orgDetails,
                orgDetailsStructure: orgDetails ? {
                  id: orgDetails.id,
                  name: orgDetails.name,
                  hasOrganizationDetails: !!orgDetails.organization_details,
                  organizationDetailsIsArray: Array.isArray(orgDetails.organization_details),
                  organizationDetailsKeys: orgDetails.organization_details ? Object.keys(orgDetails.organization_details) : null,
                  emailNotifs: orgDetails.organization_details?.email_notifs,
                  emailNotifsCC: orgDetails.organization_details?.email_notifs_cc
                } : null
              });
              
              organizationData = orgDetails;
            }
            
            if (organizationData) {
              console.log("🔍 [ROUTE DEBUG] About to send email notifications with organizationData:", {
                orgId: organizationData.id,
                orgName: organizationData.name,
                hasOrgDetails: !!organizationData.organization_details,
                emailNotifs: organizationData.organization_details?.email_notifs,
                emailNotifsCC: organizationData.organization_details?.email_notifs_cc
              });
              await sendContractUpdateNotifications(contractData, organizationData);
            }
          }
        } catch (emailError) {
          console.error("⚠️ EMAIL NOTIFICATION ERROR (non-blocking):", { contractId, error: emailError, requestId });
        }
        
        // Retourner les données mises à jour
        return NextResponse.json({ success: true, updated: Object.keys(supabaseData) }, { status: 200 });
        
      } catch (supabaseError) {
        console.error("❌ SUPABASE-ONLY UPDATE ERROR:", { contractId, error: supabaseError, requestId });
        return NextResponse.json({ error: "supabase_update_error", message: String(supabaseError), requestId }, { status: 500 });
      }
    } else {
      // CONTRAT UPSTREAM : Logique originale avec appel upstream + sync Supabase
      const upstream = `${UPSTREAM_BASE}${PATH_PREFIX}/contrats/${encodeURIComponent(contractId)}?_t=${Date.now()}`;

      const headers = new Headers({
        Accept: "application/json",
        "Content-Type": "application/json",
        "x-active-org-id": org.id,
        "x-company-name": org.name,
        "x-company-name-b64": b64(org.name),
        "x-forwarded-from": "odentas-espace-paie",
        "x-request-id": requestId,
      });
      if (process.env.STRUCTURE_API_TOKEN) {
        headers.set("authorization", `Bearer ${process.env.STRUCTURE_API_TOKEN}`);
      }

      // Timeout 10s
      const controller = new AbortController();
      const timeout = setTimeout(() => controller.abort(new Error("timeout")), 10_000);
      console.log("✏️ CONTRACT API PATCH (upstream):", { contractId, orgId: org.id, orgName: org.name, requestId, resolution: "server-side" });

      const res = await fetch(upstream, {
        method: "PATCH",
        headers: Object.fromEntries(headers.entries()),
        cache: "no-store",
        body,
        signal: controller.signal,
      });
      clearTimeout(timeout);

      if (res.status === 404) {
        const bodyText = await res.text().catch(() => "");
        console.warn("⚠️ CONTRACT NOT FOUND (PATCH upstream):", { contractId, requestId, bodyText });
        return NextResponse.json({ error: "not_found" }, { status: 404 });
      }

      if (!res.ok) {
        const text = await res.text().catch(() => "");
        console.error("❌ UPSTREAM ERROR (PATCH contrat):", { status: res.status, requestId, text });
        return NextResponse.json({ error: "upstream_error", status: res.status, body: text, requestId }, { status: 502 });
      }

      const ct = res.headers.get("content-type") || "";
      if (ct.includes("application/json")) {
        const json = await res.json();
        
        // Sauvegarder également dans Supabase si la requête upstream a réussi
        try {
          const requestBody = JSON.parse(body);
          console.log("🔍 PARSED REQUEST BODY (upstream):", { requestBody, contractId, requestId });
          
          // Créer une copie des données pour Supabase en excluant les champs qui ne correspondent pas à la table
          const supabaseData: any = {};
          
          // Mapper les champs appropriés pour la table cddu_contracts
          if (requestBody.date_signature !== undefined) {
            supabaseData.date_signature = requestBody.date_signature;
            console.log("📅 DATE_SIGNATURE FOUND:", requestBody.date_signature);
          }
          if (requestBody.reference !== undefined) {
            supabaseData.reference = requestBody.reference;
          }
          if (requestBody.analytique !== undefined) {
            supabaseData.analytique = requestBody.analytique;
          }
          
          // Ajouter d'autres champs selon les besoins
          const fieldsToSync = [
            'cachets_representations', 'services_repetitions', 'jours_representations', 
            'jours_repetitions', 'nombre_d_heures', 'jours_travail',
            'jours_travail_non_artiste', 'notes',
            'dates_travaillees', 'type_salaire', 'montant', 'panier_repas',
            // Temps de travail réel
            'jours_travail_reel',
            'nb_representations_reel',
            'nb_services_repetitions_reel', 'nb_heures_repetitions_reel',
            'nb_heures_annexes_reel',
            'nb_cachets_aem_reel', 'nb_heures_aem_reel'
          ];
          
          fieldsToSync.forEach(field => {
            if (requestBody[field] !== undefined) {
              supabaseData[field] = requestBody[field];
            }
          });
          
          // Mapper dates_representations → jours_representations
          if (requestBody.dates_representations !== undefined) {
            supabaseData.jours_representations = requestBody.dates_representations;
          }
          // Mapper dates_repetitions → jours_repetitions
          if (requestBody.dates_repetitions !== undefined) {
            supabaseData.jours_repetitions = requestBody.dates_repetitions;
          }
          
          // Convertir heures + minutes en nombre décimal pour nombre_d_heures (upstream)
          if (requestBody.heures_travail !== undefined || requestBody.minutes_travail !== undefined) {
            const heures = requestBody.heures_travail || 0;
            const minutes = requestBody.minutes_travail || 0;
            const minutesDecimal = minutes === "30" || minutes === 30 ? 0.5 : 0;
            supabaseData.nombre_d_heures = String(Number(heures) + minutesDecimal);
          }
          
          console.log("🔄 SUPABASE DATA TO UPDATE (upstream):", { supabaseData, contractId, requestId });
          
          // Ne faire l'update que s'il y a des données à sauvegarder
          if (Object.keys(supabaseData).length > 0) {
            let updateResult;
            if (org.isStaff) {
              // Staff avec accès admin
              const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
              updateResult = await admin.from("cddu_contracts").update(supabaseData).eq("id", contractId);
            } else {
              // Client avec accès limité à son organisation
              updateResult = await supabase.from("cddu_contracts").update(supabaseData).eq("id", contractId).eq("org_id", org.id);
            }
            console.log("✅ SUPABASE UPDATE RESULT (upstream):", { updateResult, contractId, syncedFields: Object.keys(supabaseData), requestId });
            
            // Envoyer les notifications email après la mise à jour réussie (sauf si explicitement désactivé)
            const shouldSendEmail = requestBody.send_email_confirmation !== false;
            
            try {
              if (!shouldSendEmail) {
                console.log("📧 Email notifications disabled by user (send_email_confirmation=false):", { contractId, requestId });
              }
              
              // Récupérer les données du contrat mis à jour pour les emails
              let contractData;
              if (org.isStaff) {
                const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
                const { data } = await admin.from("cddu_contracts").select("*").eq("id", contractId).single();
                contractData = data;
              } else {
                const { data } = await supabase.from("cddu_contracts").select("*").eq("id", contractId).eq("org_id", org.id).single();
                contractData = data;
              }
              
              if (contractData && shouldSendEmail) {
                // Récupérer les données d'organisation avec tous les détails
                let organizationData;
                if (org.isStaff) {
                  // Pour staff, récupérer l'organisation du contrat depuis la DB
                  if (contractData.org_id) {
                    const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
                    const { data: orgDetails } = await admin
                      .from("organizations")
                      .select("*, organization_details(*)")
                      .eq("id", contractData.org_id)
                      .single();
                    organizationData = orgDetails || { organization_details: {} };
                  } else {
                    // Pas d'organisation liée, skip les notifications
                    console.log("⚠️ No organization linked to contract, skipping email notifications");
                    organizationData = null;
                  }
                } else {
                  const { data: orgDetails, error: orgError } = await supabase
                    .from("organizations")
                    .select("*, organization_details(*)")
                    .eq("id", org.id)
                    .single();
                  
                  console.log("🔍 [ROUTE DEBUG] Organization data retrieved for non-staff user (upstream sync):", {
                    orgId: org.id,
                    orgName: org.name,
                    orgError,
                    hasOrgDetails: !!orgDetails,
                    orgDetailsStructure: orgDetails ? {
                      id: orgDetails.id,
                      name: orgDetails.name,
                      hasOrganizationDetails: !!orgDetails.organization_details,
                      organizationDetailsIsArray: Array.isArray(orgDetails.organization_details),
                      organizationDetailsKeys: orgDetails.organization_details ? Object.keys(orgDetails.organization_details) : null,
                      emailNotifs: orgDetails.organization_details?.email_notifs,
                      emailNotifsCC: orgDetails.organization_details?.email_notifs_cc
                    } : null
                  });
                  
                  organizationData = orgDetails;
                }
                
                if (organizationData) {
                  console.log("🔍 [ROUTE DEBUG] About to send email notifications with organizationData (upstream sync):", {
                    orgId: organizationData.id,
                    orgName: organizationData.name,
                    hasOrgDetails: !!organizationData.organization_details,
                    emailNotifs: organizationData.organization_details?.email_notifs,
                    emailNotifsCC: organizationData.organization_details?.email_notifs_cc
                  });
                  await sendContractUpdateNotifications(contractData, organizationData);
                }
              }
            } catch (emailError) {
              console.error("⚠️ EMAIL NOTIFICATION ERROR (non-blocking):", { contractId, error: emailError, requestId });
            }
          } else {
            console.log("⚠️ NO DATA TO SYNC TO SUPABASE (upstream)", { contractId, requestId });
          }
        } catch (syncError) {
          console.error("⚠️ SUPABASE SYNC ERROR (non-blocking):", { contractId, error: syncError, requestId });
          // Ne pas faire échouer la requête principale si la sync Supabase échoue
        }
        
        const response = NextResponse.json(json, { status: 200 });
        response.headers.set("x-request-id", requestId);
        return response;
      } else {
        const text = await res.text();
        return new NextResponse(text, { status: 200, headers: { "content-type": ct, "x-request-id": requestId } });
      }
    } // Fin du bloc else (contrat upstream)
  } catch (err: any) {
    const msg = String(err?.message || err || "");
    if (msg.toLowerCase().includes("timeout") || err?.name === "AbortError") {
      console.error("⏳ CONTRACT PATCH TIMEOUT:", { requestId, msg });
      return NextResponse.json({ error: "gateway_timeout", message: "Upstream timeout", requestId }, { status: 504 });
    }
    console.error("💥 ERROR in contract PATCH route:", { requestId, msg });
    return NextResponse.json({ error: "internal_server_error", message: msg, requestId }, { status: 500 });
  }
}

export async function DELETE(req: NextRequest, { params }: { params: { id: string } }) {
  const requestId = randomUUID();
  try {
    const contractId = params?.id;
    if (!contractId) return NextResponse.json({ error: "missing_id" }, { status: 400 });

    const supabase = createRouteHandlerClient({ cookies });
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) return NextResponse.json({ error: "unauthorized" }, { status: 401 });

    // Résoudre l'organisation (même logique que GET/PATCH)
    const org = await resolveOrganization(supabase, session);

    console.log("🗑️ CONTRACT DELETE:", { contractId, orgId: org.id, orgName: org.name, requestId });

    // 1. Récupérer les données du contrat avant suppression (pour les emails)
    let contractData;
    let organizationData;
    
    if (org.isStaff) {
      // Staff avec accès admin
      const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
      const { data } = await admin.from("cddu_contracts").select("*").eq("id", contractId).single();
      contractData = data;
      
      // Pour staff, récupérer l'organisation du contrat depuis la DB
      if (contractData?.org_id) {
        const { data: orgDetails } = await admin
          .from("organizations")
          .select("*, organization_details(*)")
          .eq("id", contractData.org_id)
          .single();
        organizationData = orgDetails || { organization_details: {} };
      } else {
        // Pas d'organisation liée, skip les notifications
        console.log("⚠️ No organization linked to contract, skipping email notifications");
        organizationData = null;
      }
    } else {
      // Client avec accès limité à son organisation
      const { data } = await supabase.from("cddu_contracts").select("*").eq("id", contractId).eq("org_id", org.id).single();
      contractData = data;
      
      // Récupérer les détails d'organisation
      const { data: orgDetails } = await supabase
        .from("organizations")
        .select("*, organization_details(*)")
        .eq("id", org.id)
        .single();
      organizationData = orgDetails;
    }

    if (!contractData) {
      console.warn("⚠️ CONTRACT NOT FOUND FOR DELETE:", { contractId, requestId });
      return NextResponse.json({ error: "not_found", message: "Contrat non trouvé" }, { status: 404 });
    }

    // 2. Vérifier que le contrat est annulable (statut "Reçue")
    const isRecue = contractData.etat_de_la_demande === "Reçue" || 
                   contractData.etat_de_la_demande === "reçue" ||
                   contractData.etat_de_la_demande === "recu";

    if (!isRecue) {
      console.warn("⚠️ CONTRACT NOT CANCELLABLE:", { contractId, status: contractData.etat_de_la_demande, requestId });
      return NextResponse.json({ 
        error: "not_cancellable", 
        message: "Ce contrat ne peut plus être annulé car son traitement a commencé" 
      }, { status: 400 });
    }

    // 3. Supprimer le contrat de Supabase
    let deleteResult;
    if (org.isStaff) {
      // Staff avec accès admin
      const admin = createClient(process.env.NEXT_PUBLIC_SUPABASE_URL || "", process.env.SUPABASE_SERVICE_ROLE_KEY || "");
      deleteResult = await admin.from("cddu_contracts").delete().eq("id", contractId);
    } else {
      // Client avec accès limité à son organisation
      deleteResult = await supabase.from("cddu_contracts").delete().eq("id", contractId).eq("org_id", org.id);
    }

    if (deleteResult.error) {
      console.error("❌ SUPABASE DELETE ERROR:", { contractId, error: deleteResult.error, requestId });
      return NextResponse.json({ 
        error: "delete_error", 
        message: `Erreur lors de la suppression: ${deleteResult.error.message}` 
      }, { status: 500 });
    }

    console.log("✅ CONTRACT DELETED:", { contractId, requestId });

    // 4. Envoyer les notifications email d'annulation
    try {
      if (organizationData) {
        await sendContractCancellationNotifications(contractData, organizationData);
      } else {
        console.log("⚠️ No organization data available, skipping cancellation email notifications");
      }
    } catch (emailError) {
      console.error("⚠️ EMAIL NOTIFICATION ERROR (non-blocking):", { contractId, error: emailError, requestId });
    }

    // 5. Retourner le succès
    return NextResponse.json({ 
      success: true, 
      message: "Contrat annulé avec succès",
      contractId,
      requestId 
    }, { status: 200 });

  } catch (err: any) {
    const msg = String(err?.message || err || "");
    console.error("💥 ERROR in contract DELETE route:", { requestId, msg });
    return NextResponse.json({ error: "internal_server_error", message: msg, requestId }, { status: 500 });
  }
}