// app/api/contrats/[id]/generate-pdf/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createSbServer } from "@/lib/supabaseServer";
import { createClient } from "@supabase/supabase-js";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { PROFESSIONS_ARTISTE, ProfessionOption } from "@/components/constants/ProfessionsArtiste";
import { parseDateString } from "@/lib/dateFormatter";
import { promises as fs } from "fs";
import path from "path";

// Type pour les féminisations
type ProfessionFeminisation = {
  profession_code: string;
  profession_label: string;
  profession_feminine: string;
};

// Fonction pour récupérer les professions techniciens
async function getTechniciensData(): Promise<ProfessionOption[]> {
  try {
    const filePath = path.join(process.cwd(), 'public/data/professions-techniciens.json');
    const fileContent = await fs.readFile(filePath, 'utf8');
    return JSON.parse(fileContent);
  } catch (error) {
    console.error("Erreur lors du chargement des professions techniciens:", error);
    return [];
  }
}

// Fonction pour récupérer les féminisations depuis Supabase
async function getFeminisations(): Promise<ProfessionFeminisation[]> {
  try {
    const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
    const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;
    
    const supabase = createClient(supabaseUrl, supabaseServiceKey, {
      auth: {
        autoRefreshToken: false,
        persistSession: false
      }
    });

    const { data: feminisations, error } = await supabase
      .from('professions_feminisations')
      .select('profession_code, profession_label, profession_feminine');

    if (error) {
      console.warn("Erreur lors du chargement des féminisations depuis Supabase:", error);
      return [];
    }

    return feminisations || [];
  } catch (error) {
    console.warn("Erreur lors du chargement des féminisations:", error);
    return [];
  }
}

// Fonction pour trouver le code profession à partir du label
function findProfessionCode(professionLabel: string): string | null {
  // Chercher dans les professions artistes
  const artisteProfession = PROFESSIONS_ARTISTE.find(p => 
    p.label.toLowerCase() === professionLabel.toLowerCase()
  );
  if (artisteProfession) {
    return artisteProfession.code;
  }

  // Si pas trouvé, nous chercherons dans les techniciens (mais ce sera fait de manière asynchrone)
  return null;
}

// Fonction pour obtenir la profession avec le bon genre
async function getProfessionWithGender(professionLabel: string, professionCode: string, civilite: string): Promise<string> {
  // Si c'est un homme ou si pas de civilité spécifiée, utiliser la profession normale
  if (!civilite || civilite.toLowerCase().includes('monsieur') || civilite.toLowerCase().includes('m.')) {
    return professionLabel;
  }

  // Si c'est une femme, chercher la féminisation
  if (civilite.toLowerCase().includes('madame') || civilite.toLowerCase().includes('mme')) {
    try {
      const feminisations = await getFeminisations();
      const feminisation = feminisations.find(f => f.profession_code === professionCode);
      
      if (feminisation && feminisation.profession_feminine) {
        console.log(`Utilisation de la profession féminine: "${feminisation.profession_feminine}" pour "${professionLabel}"`);
        return feminisation.profession_feminine;
      }
    } catch (error) {
      console.warn("Erreur lors de la recherche de féminisation:", error);
    }
  }

  // Par défaut, retourner la profession originale
  return professionLabel;
}

// Fonction de formatage d'une date en "DD/MM/YYYY"
function formatDate(dateStr: string | null): string {
  if (!dateStr) return "";
  const date = new Date(dateStr);
  if (isNaN(date.getTime())) return dateStr;
  const dd = String(date.getDate()).padStart(2, '0');
  const mm = String(date.getMonth() + 1).padStart(2, '0');
  const yyyy = date.getFullYear();
  return `${dd}/${mm}/${yyyy}`;
}

// Fonction de polling pour vérifier le statut du document PDFMonkey
async function pollDocumentStatus(documentId: string, pdfMonkeyUrl: string, pdfMonkeyApiKey: string) {
  const url = `${pdfMonkeyUrl}/${documentId}`;
  let attempts = 0;
  const maxAttempts = 10;
  let status = "pending";
  
  while (status !== "success" && attempts < maxAttempts) {
    console.log(`Polling PDFMonkey (tentative ${attempts + 1}/${maxAttempts})...`);
    
    const response = await fetch(url, {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${pdfMonkeyApiKey}`
      }
    });
    
    if (!response.ok) {
      throw new Error(`Erreur PDFMonkey: ${response.status} ${response.statusText}`);
    }
    
    const data = await response.json();
    status = data.document.status;
    console.log("Statut du document:", status);
    
    if (status === "success") {
      return data.document;
    }
    
    await new Promise(resolve => setTimeout(resolve, 3000));
    attempts++;
  }
  
  return { status, attempts };
}

// Fonction pour formater un texte de dates brutes en texte PDFMonkey formaté
function formatDateFieldIfNeeded(dateText: string | null | undefined, yearContext: string): string {
  if (!dateText || !dateText.trim()) return "";
  
  // Si contient déjà les marqueurs de formatage, c'est déjà du texte formaté
  if (dateText.includes(" ; ") || dateText.includes(" le ") || dateText.includes(" du ")) {
    return dateText;
  }
  
  // Sinon, parser et reformater
  try {
    const parsed = parseDateString(dateText, yearContext);
    return parsed.pdfFormatted || "";
  } catch (error) {
    console.warn("Erreur lors du formatage des dates:", error);
    return dateText; // Retourner le texte original en cas d'erreur
  }
}

export async function POST(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const sb = createSbServer();
    
    // Vérification de l'authentification et du staff
    const { data: { user }, error: authError } = await sb.auth.getUser();
    if (authError || !user) {
      return NextResponse.json(
        { error: "Authentification requise" },
        { status: 401 }
      );
    }

    const { data: staffUser } = await sb
      .from("staff_users")
      .select("is_staff")
      .eq("user_id", user.id)
      .maybeSingle();

    if (!staffUser?.is_staff) {
      return NextResponse.json(
        { error: "Accès refusé - réservé au staff" },
        { status: 403 }
      );
    }

    // Variables d'environnement
    const pdfMonkeyUrl = process.env.PDFMONKEY_URL;
    const pdfMonkeyApiKey = process.env.PDFMONKEY_API_KEY;
    
    if (!pdfMonkeyUrl || !pdfMonkeyApiKey) {
      return NextResponse.json(
        { error: "Configuration PDFMonkey manquante" },
        { status: 500 }
      );
    }

    // Configuration S3
    const s3Client = new S3Client({
      region: process.env.AWS_REGION || "eu-west-3",
      credentials: {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
      },
    });

    // Récupération du contrat
    const { data: contract, error: contractError } = await sb
      .from("cddu_contracts")
      .select("*")
      .eq("id", params.id)
      .single();

    if (contractError || !contract) {
      return NextResponse.json(
        { error: "Contrat non trouvé" },
        { status: 404 }
      );
    }

    console.log("Contrat trouvé:", {
      id: contract.id,
      org_id: contract.org_id,
      contract_number: contract.contract_number
    });

    // Récupération des données de l'organisation
    console.log("Recherche organization_details avec org_id:", contract.org_id);
    const { data: orgDetails, error: orgError } = await sb
      .from("organization_details")
      .select("*")
      .eq("org_id", contract.org_id)
      .single();

    console.log("Résultat organization_details:", { 
      orgDetails, 
      orgError,
      logoField: orgDetails?.logo ? `${orgDetails.logo.substring(0, 50)}...` : 'NULL'
    });

    if (orgError || !orgDetails) {
      return NextResponse.json(
        { 
          error: "Détails de l'organisation non trouvés",
          debug: {
            org_id: contract.org_id,
            orgError: orgError?.message,
            orgDetails: orgDetails
          }
        },
        { status: 404 }
      );
    }

    // Récupération du nom de la structure depuis la table organizations
    console.log("Recherche organizations avec id:", contract.org_id);
    const { data: organization } = await sb
      .from("organizations")
      .select("name")
      .eq("id", contract.org_id)
      .single();

    console.log("Résultat organizations:", organization);

    // Récupération des données du salarié
    console.log("Recherche salarié avec id:", contract.employee_id);
    const { data: salarie, error: salarieError } = await sb
      .from("salaries")
      .select("*")
      .eq("id", contract.employee_id)
      .single();

    console.log("Résultat salaries:", { salarie, salarieError });

    if (salarieError || !salarie) {
      return NextResponse.json(
        { 
          error: "Salarié non trouvé",
          debug: {
            employee_id: contract.employee_id,
            salarieError: salarieError?.message
          }
        },
        { status: 404 }
      );
    }

    // Récupération des données de production si disponible
    const { data: production } = await sb
      .from("productions")
      .select("prod_type")
      .eq("name", contract.production_name)
      .maybeSingle();

    // Construction du nom de fichier
    const matricule = salarie.code_salarie || "000";
    const filename = `contrat_cddu_${contract.contract_number}_${matricule}.pdf`;

    // Extraction du code emploi et de la profession depuis le champ profession
    const professionField = contract.profession || "";
    let employee_codeprofession = "DEMO001"; // Code par défaut
    let employee_profession = professionField;
    
    // Essayer de trouver le code dans les professions artistes d'abord
    const artisteCode = findProfessionCode(professionField);
    if (artisteCode) {
      employee_codeprofession = artisteCode;
      // Utiliser la profession avec le bon genre selon la civilité
      employee_profession = await getProfessionWithGender(professionField, artisteCode, salarie.civilite || "");
    } else {
      // Chercher dans les professions techniciens
      try {
        const techniciensData = await getTechniciensData();
        const technicienProfession = techniciensData.find(p => 
          p.label.toLowerCase() === professionField.toLowerCase()
        );
        if (technicienProfession) {
          employee_codeprofession = technicienProfession.code;
          // Utiliser la profession avec le bon genre selon la civilité
          employee_profession = await getProfessionWithGender(professionField, technicienProfession.code, salarie.civilite || "");
        } else {
          console.warn(`Code profession non trouvé pour: "${professionField}". Utilisation du code par défaut.`);
        }
      } catch (error) {
        console.error("Erreur lors de la recherche du code profession:", error);
      }
    }

    console.log(`Profession: "${professionField}" -> Code: "${employee_codeprofession}" -> Genrée: "${employee_profession}"`);
    console.log(`Civilité du salarié: "${salarie.civilite}"`);

    // Déterminer la catégorie professionnelle à envoyer
    // Pour "Metteur en scène", on envoie "Metteur en scène"
    // Pour toutes les autres professions artistes, on envoie "Artiste"
    // Pour les techniciens, on envoie "Technicien"
    let employee_catpro = contract.categorie_pro || "";
    if (contract.categorie_pro === "Artiste" && contract.profession === "Metteur en scène") {
      employee_catpro = "Metteur en scène";
    }

    console.log(`Catégorie professionnelle pour PDFMonkey: "${employee_catpro}"`);
    console.log(`Profession du contrat: "${contract.profession}"`);
    console.log(`Metteur en scène détecté: ${contract.profession === "Metteur en scène"}`);
    console.log(`Jours de travail (jours_travail): "${contract.jours_travail}"`);
    console.log(`Jours de travail non-artiste (jours_travail_non_artiste): "${contract.jours_travail_non_artiste}"`);

    // Construction du payload pour PDFMonkey selon le mapping CSV
    const dataPayload = {
      structure_name: organization?.name || orgDetails.structure || "",
      structure_adresse: orgDetails.adresse || "",
      structure_cpville: orgDetails.cp || "",
      structure_ville: orgDetails.ville || "",
      structure_siret: orgDetails.siret || "",
      structure_licence: orgDetails.licence_spectacles || "",
      structure_spectacle: orgDetails.structure_a_spectacles ? "Oui" : "Non",
      forme_juridique: orgDetails.forme_juridique || "",
      structure_signataire: `${orgDetails.prenom_signataire || ""} ${orgDetails.nom_signataire || ""}`.trim(),
      structure_signatairequalite: orgDetails.qualite_signataire || "",
      delegation: orgDetails.delegation_signature ? "Oui" : "Non",
      employee_civ: salarie.civilite || "",
      employee_firstname: salarie.prenom || "",
      employee_lastname: salarie.nom || "",
      employee_birthname: salarie.nom_de_naissance || "",
      employee_pseudo: salarie.pseudonyme || "",
      employee_dob: formatDate(salarie.date_naissance),
      employee_cob: salarie.lieu_de_naissance || "",
      employee_address: salarie.adresse || "",
      employee_ss: salarie.nir || "",
      employee_cs: salarie.conges_spectacles || "",
      employee_profession: employee_profession,
      employee_codeprofession: employee_codeprofession,
      employee_catpro: employee_catpro,
      mineur1618: contract.mineur_entre_16_et_18 || "",
      representant_civ: contract.civilite_representant_legal || "",
      representant_nom: contract.nom_representant_legal || "",
      representant_dob: formatDate(contract.dob_representant_legal),
      representant_cob: contract.cob_representant_legal || "",
      representant_adresse: contract.adresse_representant_legal || "",
      spectacle: contract.production_name || "",
      numobjet: contract.objet_spectacle || "",
      type_numobjet: production?.prod_type || "",
      date_debut: formatDate(contract.start_date),
      date_fin: formatDate(contract.end_date),
      // Combiner toutes les dates travaillées : représentations, répétitions, jours de travail
      // Format: "1 représentation le 12/10 ; 2 heures le 13/10 ; 1 service de répétition par jour du 14/10 au 16/10."
      // Formater chaque source au besoin, puis les combiner
      // Pour les metteurs en scène, utiliser jours_travail_non_artiste
      dates_travaillees: (() => {
        // Cas spécifiques
        const isMetteurEnScene = contract.profession === "Metteur en scène";
        const isTechnicien = (contract.categorie_pro || "").toLowerCase() === "technicien";

        if (isMetteurEnScene) {
          // Metteur en scène: déjà correct, utiliser jours_travail_non_artiste tel quel
          return contract.jours_travail_non_artiste || "";
        }

        if (isTechnicien) {
          // Technicien: utiliser jours_travail_non_artiste tel quel (ne rien changer pour artistes)
          return contract.jours_travail_non_artiste || "";
        }

        // Artistes (autres cas): combiner les dates comme avant
        const datesSources = [
          formatDateFieldIfNeeded(contract.jours_representations, contract.start_date || new Date().toISOString().slice(0, 10)),
          formatDateFieldIfNeeded(contract.jours_repetitions, contract.start_date || new Date().toISOString().slice(0, 10)),
          formatDateFieldIfNeeded(contract.jours_travail, contract.start_date || new Date().toISOString().slice(0, 10))
        ];

        return (
          datesSources
            .filter((s) => s.trim().length > 0)
            .join(" ; ")
            .replace(/ ; \./g, ".") // Éviter les doubles points
            .replace(/\.{2}/, ".") // Éviter les double points
            .replace(/; $/, ".") // Fin correcte
        ) || "";
      })(),
      salaire_brut: contract.gross_pay 
        ? parseFloat(contract.gross_pay.toString()).toLocaleString('fr-FR', { 
            minimumFractionDigits: 2, 
            maximumFractionDigits: 2 
          }) 
        : "",
      date_signature: formatDate(contract.date_signature),
      CCN: orgDetails.ccn || "",
      // Toujours envoyer precisions_salaire depuis la colonne Supabase
      precisions_salaire: contract.precisions_salaire || "",
      autreprecision_duree: contract.autreprecision_duree || "",
      autreprecision_salaire: contract.autreprecision_salaire || "",
      panierrepas: contract.paniers_repas || "",
      panierrepasccn: contract.panier_repas_ccn || "",
      montantpanierrepas: contract.si_non_montant_par_panier || "",
      cachets: {
        representations: contract.cachets_representations ? parseInt(contract.cachets_representations) || 0 : 0,
        repetitions: contract.services_repetitions ? parseInt(contract.services_repetitions) || 0 : 0,
        heures: contract.nombre_d_heures ? parseFloat(contract.nombre_d_heures) || 0 : 0,
        heuresparjour: contract.nombre_d_heures_par_jour ? parseFloat(contract.nombre_d_heures_par_jour) || 0 : 0
      },
      nom_responsable_traitement: orgDetails.nom_responsable_traitement || "",
      qualite_responsable_traitement: orgDetails.qualite_responsable_traitement || "",
      email_responsable_traitement: orgDetails.email_responsable_traitement || "",
      imageUrl: orgDetails.logo || ""
    };

    // Log de débogage pour vérifier le logo
    console.log("🖼️ [PDF Generation] Logo récupéré depuis DB:", {
      hasLogo: !!orgDetails.logo,
      logoLength: orgDetails.logo?.length || 0,
      logoPrefix: orgDetails.logo?.substring(0, 30) || 'VIDE',
      hasDataPrefix: orgDetails.logo?.startsWith('data:') || false
    });

    const pdfPayload = {
      document_template_id: "736E1A5F-BBA1-4D3E-91ED-A6184479B58D",
      payload: dataPayload,
      status: "pending",
      filename: filename
    };

    console.log("Payload envoyé à PDFMonkey:", JSON.stringify(pdfPayload, null, 2));

    // Envoi du payload vers PDFMonkey
    const pdfResponse = await fetch(pdfMonkeyUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${pdfMonkeyApiKey}`
      },
      body: JSON.stringify(pdfPayload)
    });

    if (!pdfResponse.ok) {
      const errorText = await pdfResponse.text();
      console.error("Erreur PDFMonkey:", pdfResponse.status, errorText);
      return NextResponse.json(
        { error: `Erreur PDFMonkey: ${pdfResponse.status}` },
        { status: 500 }
      );
    }

    const pdfData = await pdfResponse.json();
    console.log("Réponse initiale de PDFMonkey:", JSON.stringify(pdfData));

    // Récupération de l'ID du document
    const documentId = pdfData.document?.id;
    if (!documentId) {
      throw new Error("Aucun ID de document retourné par PDFMonkey");
    }

    console.log("ID du document PDFMonkey:", documentId);

    // Polling pour vérifier le statut jusqu'à "success"
    const finalDocumentData = await pollDocumentStatus(documentId, pdfMonkeyUrl, pdfMonkeyApiKey);
    
    console.log("Document final:", JSON.stringify(finalDocumentData));

    if (finalDocumentData.download_url) {
      console.log("Téléchargement du PDF depuis:", finalDocumentData.download_url);
      
      // Télécharger le PDF depuis PDFMonkey
      const pdfResponse = await fetch(finalDocumentData.download_url);
      if (!pdfResponse.ok) {
        throw new Error("Impossible de télécharger le PDF depuis PDFMonkey");
      }
      
      const pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer());
      
      // Upload vers S3
      const s3Key = `unsigned-contracts/${filename}`;
      console.log("Upload du fichier dans S3 sous la clé:", s3Key);
      
      const uploadCommand = new PutObjectCommand({
        Bucket: (process.env.AWS_S3_BUCKET || "odentas-docs").trim(),
        Key: s3Key,
        Body: pdfBuffer,
        ContentType: "application/pdf",
      });
      
      await s3Client.send(uploadCommand);
      console.log("Fichier PDF uploadé sur S3 avec succès.");
      
      // URL S3 pour accéder au fichier
      const bucketName = (process.env.AWS_S3_BUCKET || "odentas-docs").trim();
      const s3Url = `https://${bucketName}.s3.eu-west-3.amazonaws.com/${s3Key}`;
      
      // Mettre à jour le contrat avec l'URL du PDF
      console.log("Mise à jour du contrat avec:", {
        contract_pdf_url: s3Url,
        contract_pdf_filename: filename
      });
      
      const { error: updateError } = await sb
        .from("cddu_contracts")
        .update({ 
          contract_pdf_url: s3Url,
          contract_pdf_filename: filename
        })
        .eq("id", params.id);
      
      if (updateError) {
        console.error("Erreur lors de la mise à jour du contrat:", updateError);
      } else {
        console.log("Contrat mis à jour avec succès");
      }
      
      return NextResponse.json({
        success: true,
        message: "PDF créé et sauvegardé avec succès",
        documentId: documentId,
        filename: filename,
        s3Url: s3Url,
        pdfMonkeyResponse: finalDocumentData
      });
    } else {
      return NextResponse.json(
        { error: "Aucun URL de téléchargement disponible" },
        { status: 500 }
      );
    }

  } catch (error) {
    console.error("Erreur lors de la génération du PDF:", error);
    return NextResponse.json(
      { 
        error: "Erreur interne du serveur", 
        details: error instanceof Error ? error.message : String(error) 
      },
      { status: 500 }
    );
  }
}