import { NextRequest, NextResponse } from 'next/server';
import { createSbServiceRole } from '@/lib/supabaseServer';
import { DynamoDBClient, PutItemCommand, UpdateItemCommand } from '@aws-sdk/client-dynamodb';
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import { sendUniversalEmailV2, renderUniversalEmailV2, EmailDataV2 } from '@/lib/emailTemplateService';
import { ENV } from '@/lib/cleanEnv';
import axios from 'axios';

// Configuration AWS
const region = ENV.AWS_REGION;
const dynamoDBClient = new DynamoDBClient({ 
  region,
  credentials: {
    accessKeyId: ENV.AWS_ACCESS_KEY_ID,
    secretAccessKey: ENV.AWS_SECRET_ACCESS_KEY
  }
});

// Vérification des variables d'environnement au démarrage
console.log('🔧 Configuration DynamoDB:', {
  region,
  hasAccessKey: !!ENV.AWS_ACCESS_KEY_ID,
  hasSecretKey: !!ENV.AWS_SECRET_ACCESS_KEY,
  accessKeyLength: ENV.AWS_ACCESS_KEY_ID?.length,
  secretKeyLength: ENV.AWS_SECRET_ACCESS_KEY?.length
});
const s3Client = new S3Client({ region });
// Envoi d'e-mails géré via le service de templates universels

export async function POST(request: NextRequest) {
  console.log('=== DocuSeal Signature API ===');
  
  try {
    // Utiliser le service role pour les opérations serveur
    const supabase = createSbServiceRole();
    
    const data = await request.json();
    console.log('Données reçues:', JSON.stringify(data, null, 2));

    const {
      contractId,
      pdfS3Key,
      employerEmail,
      employeeEmail,
      reference,
      employeeName,
      startDate,
      role,
      analytique,
      structure,
      signerFirstName,
      employerCode,
      employeeFirstName,
      matricule,
      contractType = 'CDDU',
      skipEmployerEmail = false, // Nouveau paramètre pour éviter l'envoi d'email à l'employeur
      orgId = null // ID de l'organisation pour récupérer la signature
    } = data;

    // Validation des champs requis
    if (!contractId || !pdfS3Key || !employerEmail || !employeeEmail) {
      return NextResponse.json(
        { error: 'Champs manquants: contractId, pdfS3Key, employerEmail, employeeEmail' },
        { status: 400 }
      );
    }

    // 🔒 SÉCURITÉ : Validation du format des emails
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    
    if (!emailRegex.test(employeeEmail)) {
      console.error('❌ [SÉCURITÉ] Format d\'email salarié invalide:', employeeEmail);
      return NextResponse.json(
        { error: 'Format d\'email salarié invalide' },
        { status: 400 }
      );
    }
    
    // Validation de l'email employeur avec fallback sécurisé
    let validatedEmployerEmail = employerEmail;
    if (!emailRegex.test(employerEmail)) {
      console.warn('⚠️ [SÉCURITÉ] Email employeur invalide, utilisation du fallback:', employerEmail);
      validatedEmployerEmail = "paie@odentas.fr";
      console.log('✅ [SÉCURITÉ] Email employeur remplacé par:', validatedEmployerEmail);
    }

    // 🔒 SÉCURITÉ CRITIQUE : Vérifier que le contrat appartient bien à l'organisation spécifiée
    console.log('🔒 [SÉCURITÉ] Vérification de la cohérence contrat/organisation...');
    console.log('🔒 [SÉCURITÉ] contractId:', contractId);
    console.log('🔒 [SÉCURITÉ] orgId fourni:', orgId);
    
    const { data: contractVerification, error: contractVerifError } = await supabase
      .from('cddu_contracts')
      .select('org_id, employee_matricule, employee_name, contract_number')
      .eq('id', contractId)
      .single();

    if (contractVerifError || !contractVerification) {
      console.error('❌ [SÉCURITÉ] Contrat non trouvé:', contractVerifError);
      return NextResponse.json(
        { error: 'Contrat introuvable' },
        { status: 404 }
      );
    }

    console.log('🔒 [SÉCURITÉ] org_id du contrat en base:', contractVerification.org_id);
    
    // Vérifier que l'org_id fourni correspond bien à celui du contrat
    if (orgId && contractVerification.org_id !== orgId) {
      console.error('❌ [SÉCURITÉ CRITIQUE] Tentative de signature avec une mauvaise organisation!');
      console.error('   - org_id du contrat:', contractVerification.org_id);
      console.error('   - org_id fourni:', orgId);
      console.error('   - contrat:', contractVerification.contract_number);
      console.error('   - salarié:', contractVerification.employee_name);
      
      return NextResponse.json(
        { 
          error: 'SÉCURITÉ : Le contrat n\'appartient pas à l\'organisation spécifiée',
          details: 'Incohérence détectée entre le contrat et l\'organisation'
        },
        { status: 403 }
      );
    }

    // Vérifier également que le matricule fourni correspond (double vérification)
    if (matricule && contractVerification.employee_matricule !== matricule) {
      console.error('❌ [SÉCURITÉ] Incohérence détectée sur le matricule du salarié!');
      console.error('   - Matricule du contrat:', contractVerification.employee_matricule);
      console.error('   - Matricule fourni:', matricule);
      
      return NextResponse.json(
        { 
          error: 'SÉCURITÉ : Le matricule du salarié ne correspond pas au contrat',
          details: 'Incohérence détectée entre les données'
        },
        { status: 403 }
      );
    }

    console.log('✅ [SÉCURITÉ] Vérification réussie - Le contrat appartient bien à l\'organisation');
    console.log('   - Contrat:', contractVerification.contract_number);
    console.log('   - Organisation:', contractVerification.org_id);
    console.log('   - Salarié:', contractVerification.employee_name);
    console.log('   - Matricule:', contractVerification.employee_matricule);

    // Récupérer la signature base64 de l'organisation si disponible
    let employerSignatureB64 = null;
    if (orgId) {
      console.log('🔍 [SIGNATURE] Recherche de la signature pour org_id:', orgId);
      const { data: orgDetails } = await supabase
        .from('organization_details')
        .select('signature_b64')
        .eq('org_id', orgId)
        .maybeSingle();
      
      if (orgDetails?.signature_b64) {
        employerSignatureB64 = orgDetails.signature_b64;
        console.log('✅ [SIGNATURE] Signature trouvée pour l\'employeur');
      } else {
        console.log('ℹ️ [SIGNATURE] Aucune signature trouvée pour l\'employeur');
      }
    }

    // Extraire le submission_id depuis le nom du fichier PDF
    // pdfS3Key format: "unsigned-contracts/contrat_cddu_REFERENCE.pdf"
    // submission_id attendu: "contrats/contrat_cddu_REFERENCE" (format pour DynamoDB)
    const pdfFileName = pdfS3Key.split('/').pop() || ''; // "contrat_cddu_REFERENCE.pdf"
    const contractFileName = pdfFileName.replace('.pdf', ''); // "contrat_cddu_REFERENCE"
    const submissionId = `contrats/${contractFileName}`; // "contrats/contrat_cddu_REFERENCE"
    console.log('📝 [SUBMISSION] pdfS3Key:', pdfS3Key);
    console.log('📝 [SUBMISSION] pdfFileName:', pdfFileName);
    console.log('📝 [SUBMISSION] contractFileName:', contractFileName);
    console.log('📝 [SUBMISSION] submission_id généré:', submissionId);
    const formattedDate = formatDate(startDate);

    // Étape 1 : Stocker les données du contrat dans DynamoDB
    console.log('🗄️ [DYNAMODB] Tentative de stockage pour submission_id:', submissionId);
    try {
      await storeContractData(submissionId, {
        employerEmail: validatedEmployerEmail,
        employeeEmail,
        reference,
        salarie: employeeName,
        date: startDate,
        poste: role,
        analytique,
        structure,
        prenom_signataire: signerFirstName,
        code_employeur: employerCode,
        prenom_salarie: employeeFirstName,
        matricule,
        typecontrat: contractType
      });
      console.log('✅ [DYNAMODB] Données du contrat stockées avec succès dans DynamoDB');
    } catch (dynamoError) {
      console.error('❌ [DYNAMODB] Erreur détaillée lors du stockage:', {
        error: dynamoError,
        message: dynamoError instanceof Error ? dynamoError.message : 'Erreur inconnue',
        stack: dynamoError instanceof Error ? dynamoError.stack : undefined
      });
      // Continue le processus même si DynamoDB échoue
    }

        // Étape 2 : Récupération du PDF depuis S3
    const getObjectCommand = new GetObjectCommand({
      Bucket: ENV.AWS_S3_BUCKET,
      Key: pdfS3Key,
    });
    
    const s3Object = await s3Client.send(getObjectCommand);
    const bodyBytes = await s3Object.Body?.transformToByteArray();
    
    if (!bodyBytes) {
      throw new Error('Impossible de lire le contenu du fichier PDF depuis S3');
    }
    
    const pdfBase64 = Buffer.from(bodyBytes).toString('base64');
    console.log('PDF récupéré depuis S3:', pdfS3Key);

    // Extraire le nom de fichier depuis la clé S3 (exemple: "unsigned-contracts/contrat_cddu_6ET5Z3XW_DEMO002.pdf")
    const docusealFileName = pdfS3Key.split('/').pop() || `contrat_${submissionId}.pdf`;
    console.log('Nom de fichier extrait pour DocuSeal:', docusealFileName);
    
    // Debug de la configuration DocuSeal
    console.log('🔧 [DOCUSEAL] Configuration:', {
      hasToken: !!ENV.DOCUSEAL_TOKEN,
      tokenLength: ENV.DOCUSEAL_TOKEN.length,
      tokenPreview: ENV.DOCUSEAL_TOKEN.substring(0, 10) + '...',
      apiBase: ENV.DOCUSEAL_API_BASE,
      apiBaseRaw: process.env.DOCUSEAL_API_BASE,
      rawTokenLength: process.env.DOCUSEAL_TOKEN?.length
    });

    // Étape 3 : Création du template DocuSeal
    const templateResponse = await axios.post(`${ENV.DOCUSEAL_API_BASE}/templates/pdf`, {
      name: `CDDU - ${reference}`,
      documents: [{ name: docusealFileName, file: pdfBase64 }]
    }, {
      headers: { 
        'X-Auth-Token': ENV.DOCUSEAL_TOKEN,
        'Content-Type': 'application/json'
      }
    });

    const templateId = templateResponse.data.id;
    console.log('Template DocuSeal créé:', templateResponse.data);

    // Étape 4 : Création de la soumission DocuSeal
    console.log('🔧 [DOCUSEAL] Création de la soumission avec:', {
      templateId,
      hasEmployerSignature: !!employerSignatureB64,
      signaturePreview: employerSignatureB64 ? employerSignatureB64.substring(0, 50) + '...' : 'N/A'
    });

    const submissionPayload = {
      template_id: templateId,
      send_email: false,
      submitters: [
        { 
          role: 'Employeur', 
          email: validatedEmployerEmail,
          // Pré-remplir la signature de l'employeur si disponible
          ...(employerSignatureB64 && {
            values: {
              signature: employerSignatureB64
            }
          })
        },
        { 
          role: 'Salarié', 
          email: employeeEmail
        }
      ]
    };

    console.log('📤 [DOCUSEAL] Payload complet:', JSON.stringify(submissionPayload, null, 2));

    const submissionResponse = await axios.post(`${ENV.DOCUSEAL_API_BASE}/submissions`, submissionPayload, {
      headers: {
        'X-Auth-Token': ENV.DOCUSEAL_TOKEN,
        'Content-Type': 'application/json'
      }
    });

    console.log('Soumission DocuSeal créée:', submissionResponse.data);
    if (employerSignatureB64) {
      console.log('✅ [SIGNATURE] Signature employeur pré-remplie');
    }

    // Récupérer le submission_id DocuSeal
    const docusealSubmissionId = submissionResponse.data[0].submission_id;
    console.log(`DocuSeal submission_id: ${docusealSubmissionId}`);

    // Mettre à jour DynamoDB avec le docusealSubID
    console.log('🗄️ [DYNAMODB] Mise à jour avec docusealSubID:', docusealSubmissionId);
    try {
      await updateContractWithDocusealId(submissionId, docusealSubmissionId);
      console.log('✅ [DYNAMODB] Mise à jour réussie avec docusealSubID');
    } catch (updateError) {
      console.error('❌ [DYNAMODB] Erreur lors de la mise à jour:', updateError);
    }

    // Récupérer les informations pour le lien de signature
    const employerSubmission = submissionResponse.data.find((sub: any) => sub.role === 'Employeur');
    const employeeSubmission = submissionResponse.data.find((sub: any) => sub.role === 'Salarié');
    const embedCode = employerSubmission.slug;
    const employeeSlug = employeeSubmission?.slug || null;
    
    // Construire l'URL propre sans paramètres (les data-* sont ajoutés sur le composant HTML)
    const signatureLink = `https://staging.paie.odentas.fr/odentas-sign?docuseal_id=${embedCode}`;
    
    console.log('🔗 [SIGNATURE] Lien généré:', signatureLink);
    console.log('🔗 [SIGNATURE] Slug salarié:', employeeSlug);
    if (employerSignatureB64) {
      console.log('✅ [SIGNATURE] Signature B64 disponible pour pré-remplissage côté client');
    }

    // Étape 5 : Envoi de l'email de signature via le template universel (employeur)
    // Seulement si skipEmployerEmail est false (signature individuelle)
    let messageId = '';
    let emailLink = '';
    
    if (!skipEmployerEmail) {
      const emailData: EmailDataV2 = {
        firstName: signerFirstName,
        organizationName: structure,
        employerCode: employerCode,
        employeeName: employeeName,
        documentType: contractType || 'Contrat',
        contractReference: reference,
        status: 'En attente',
        ctaUrl: signatureLink,
        contractId: contractId, // Ajout pour traçabilité dans email_logs
      };

      // Rendu HTML pour archivage puis envoi
      const rendered = await renderUniversalEmailV2({
        type: 'signature-request-employer',
        toEmail: validatedEmployerEmail,
        subject: `Demande de signature – ${reference}`,
        data: emailData,
      });

      messageId = await sendUniversalEmailV2({
        type: 'signature-request-employer',
        toEmail: validatedEmployerEmail,
        subject: `Demande de signature – ${reference}`,
        data: emailData,
      });

      // Mettre à jour le timestamp de dernière notification employeur
      const now = new Date().toISOString();
      const { error: updateError } = await supabase
        .from('cddu_contracts')
        .update({ last_employer_notification_at: now })
        .eq('id', contractId);

      if (updateError) {
        console.warn("⚠️ [DOCUSEAL] Impossible de mettre à jour last_employer_notification_at:", updateError);
      } else {
        console.log("✅ [DOCUSEAL] Timestamp notification employeur enregistré:", now);
      }

      // Étape 6 : Upload de l'email HTML rendu sur S3 et logging
      const emailHtml = rendered.html;
      emailLink = await uploadEmailToS3(emailHtml, messageId);
      console.log('Email HTML uploadé sur S3:', emailLink);
    } else {
      console.log('⏭️ [EMAIL] Envoi d\'email employeur ignoré (mode bulk)');
    }

    // Étape 7 : Mise à jour du contrat dans Supabase avec les infos DocuSeal
    console.log('🗄️ [SUPABASE] Début de la mise à jour du contrat:', {
      contractId,
      templateId,
      docusealSubmissionId,
      signatureLink,
      employeeSlug
    });

    const supabaseResult = await supabase
      .from('cddu_contracts')
      .update({
        docuseal_template_id: templateId,
        docuseal_submission_id: docusealSubmissionId,
        employee_docuseal_slug: employeeSlug,
        signature_status: 'En attente',
        signature_link: signatureLink,
        updated_at: new Date().toISOString()
      })
      .eq('id', contractId);

    console.log('🗄️ [SUPABASE] Résultat de la mise à jour:', {
      error: supabaseResult.error,
      status: supabaseResult.status,
      statusText: supabaseResult.statusText,
      count: supabaseResult.count
    });

    if (supabaseResult.error) {
      console.error('❌ [SUPABASE] Erreur lors de la mise à jour:', supabaseResult.error);
      throw new Error(`Erreur Supabase: ${supabaseResult.error.message}`);
    }

    console.log('✅ [SUPABASE] Contrat mis à jour avec succès dans Supabase');

    return NextResponse.json({
      success: true,
      message: 'Signature électronique initiée avec succès',
      data: {
        templateId,
        submissionId: docusealSubmissionId,
        signatureLink,
        emailLink
      }
    });

  } catch (error) {
    console.error('Erreur lors de l\'initiation de la signature:', error);
    return NextResponse.json(
      { 
        error: 'Erreur lors de l\'initiation de la signature électronique',
        details: error instanceof Error ? error.message : 'Erreur inconnue'
      },
      { status: 500 }
    );
  }
}

// Fonction pour formater la date
function formatDate(dateStr: string): string {
  try {
    const dateObj = new Date(dateStr);
    if (isNaN(dateObj.getTime())) {
      console.error('Date invalide:', dateStr);
      return dateStr;
    }

    const day = String(dateObj.getUTCDate()).padStart(2, '0');
    const month = String(dateObj.getUTCMonth() + 1).padStart(2, '0');
    const year = dateObj.getUTCFullYear();

    return `${day}/${month}/${year}`;
  } catch (error) {
    console.error('Erreur lors du formatage de la date:', error);
    return dateStr;
  }
}

// Fonction pour stocker les données du contrat dans DynamoDB
async function storeContractData(submissionId: string, data: any) {
  console.log('🗄️ [DYNAMODB] storeContractData - Données à sauvegarder:', {
    submissionId,
    dataKeys: Object.keys(data),
    data
  });

  const command = new PutItemCommand({
    TableName: 'DocuSealNotification',
    Item: {
      submission_id: { S: submissionId },
      employerEmail: { S: data.employerEmail || '' },
      employeeEmail: { S: data.employeeEmail || '' },
      reference: { S: data.reference || '' },
      salarie: { S: data.salarie || '' },
      date: { S: data.date || '' },
      poste: { S: data.poste || '' },
      analytique: { S: data.analytique || '' },
      structure: { S: data.structure || '' },
      prenom_signataire: { S: data.prenom_signataire || '' },
      code_employeur: { S: data.code_employeur || '' },
      prenom_salarie: { S: data.prenom_salarie || '' },
      matricule: { S: data.matricule || '' },
      typecontrat: { S: data.typecontrat || '' }
    }
  });

  console.log('🗄️ [DYNAMODB] Commande DynamoDB préparée:', {
    TableName: command.input.TableName,
    submissionId: command.input.Item?.submission_id
  });

  try {
    const result = await dynamoDBClient.send(command);
    console.log('✅ [DYNAMODB] PutItem réussi:', result);
    return result;
  } catch (error) {
    console.error('❌ [DYNAMODB] Erreur détaillée dans storeContractData:', {
      error,
      errorName: error instanceof Error ? error.name : 'Unknown',
      errorMessage: error instanceof Error ? error.message : 'Unknown error',
      errorCode: (error as any)?.code,
      errorRequestId: (error as any)?.$metadata?.requestId
    });
    // Ne pas faire échouer tout le processus pour DynamoDB
    console.log('⚠️ Continuing without DynamoDB storage...');
    throw error; // Re-throw pour que le catch parent puisse logger
  }
}

// Fonction pour mettre à jour l'enregistrement dans DynamoDB
async function updateContractWithDocusealId(submissionId: string, docusealSubID: string | number) {
  console.log('🗄️ [DYNAMODB] updateContractWithDocusealId:', { submissionId, docusealSubID });

  const command = new UpdateItemCommand({
    TableName: 'DocuSealNotification',
    Key: { 
      submission_id: { S: submissionId }
    },
    UpdateExpression: 'set docusealSubID = :docusealSubID',
    ExpressionAttributeValues: {
      ':docusealSubID': { S: String(docusealSubID) } // Convertir en string
    },
    ReturnValues: 'UPDATED_NEW'
  });

  try {
    const result = await dynamoDBClient.send(command);
    console.log('✅ [DYNAMODB] UpdateItem réussi:', result);
    return result;
  } catch (error) {
    console.error('❌ [DYNAMODB] Erreur détaillée dans updateContractWithDocusealId:', {
      error,
      errorName: error instanceof Error ? error.name : 'Unknown',
      errorMessage: error instanceof Error ? error.message : 'Unknown error',
      errorCode: (error as any)?.code,
      errorRequestId: (error as any)?.$metadata?.requestId
    });
    // Ne pas faire échouer tout le processus pour DynamoDB
    console.log('⚠️ Continuing without DynamoDB update...');
    throw error; // Re-throw pour le catch parent
  }
}

// Fonction pour uploader l'email HTML sur S3
async function uploadEmailToS3(emailHtml: string, key: string): Promise<string> {
  const command = new PutObjectCommand({
    Bucket: ENV.S3_BUCKET_NAME_EMAILS,
    Key: `${key}.html`,
    Body: emailHtml,
    ContentType: 'text/html',
    ACL: 'public-read'
  });

  try {
    await s3Client.send(command);
    return `https://${ENV.S3_BUCKET_NAME_EMAILS}.s3.amazonaws.com/${key}.html`;
  } catch (error) {
    console.error('Erreur lors de l\'upload de l\'email sur S3:', error);
    throw new Error('Échec de l\'upload de l\'email HTML sur S3.');
  }
}

// Anciennes fonctions HTML/SES supprimées au profit du système universel