#!/usr/bin/env node

/**
 * Outil pour extraire les positions exactes des placeholders DocuSeal
 * Format: {{Label;role=Role;type=signature;height=H;width=W}}
 * 
 * Utilise pdf-lib pour obtenir les vraies coordonnées
 */

const fs = require('fs');
const path = require('path');
const { PDFDocument } = require('pdf-lib');

/**
 * Extrait les placeholders du texte
 */
function extractPlaceholdersFromText(text) {
  const regex = /\{\{([^;]+);role=([^;]+);type=([^;]+);height=(\d+);width=(\d+)\}\}/g;
  const placeholders = [];
  let match;

  while ((match = regex.exec(text)) !== null) {
    placeholders.push({
      fullMatch: match[0],
      label: match[1].trim(),
      role: match[2].trim(),
      type: match[3].trim(),
      height: parseInt(match[4]),
      width: parseInt(match[5]),
      startIndex: match.index,
      endIndex: match.index + match[0].length,
    });
  }

  return placeholders;
}

/**
 * Lit le contenu textuel d'un PDF avec pdf-lib
 * Note: pdf-lib ne fournit pas directement les positions du texte
 * On va donc utiliser une approche hybride
 */
async function analyzePdfWithLib(pdfPath) {
  const pdfBytes = fs.readFileSync(pdfPath);
  const pdfDoc = await PDFDocument.load(pdfBytes);
  
  const pages = pdfDoc.getPages();
  const results = {
    pageCount: pages.length,
    pages: [],
  };
  
  for (let i = 0; i < pages.length; i++) {
    const page = pages[i];
    const { width, height } = page.getSize();
    
    results.pages.push({
      number: i + 1,
      width,
      height,
    });
  }
  
  return results;
}

/**
 * Extrait le texte brut avec pdf-parse
 */
async function extractTextWithPdfParse(pdfPath) {
  try {
    const pdfParse = require('pdf-parse');
    const dataBuffer = fs.readFileSync(pdfPath);
    const data = await pdfParse(dataBuffer);
    return data.text;
  } catch (error) {
    console.warn('⚠️  pdf-parse non disponible, utilisation de méthode alternative');
    return null;
  }
}

/**
 * Méthode alternative : lire le PDF comme texte brut et chercher les patterns
 */
function extractTextFromPdfRaw(pdfPath) {
  const pdfBytes = fs.readFileSync(pdfPath);
  const pdfText = pdfBytes.toString('utf-8');
  return pdfText;
}

/**
 * Estime la position Y basée sur la fréquence du texte dans le document
 * Méthode heuristique pour les PDFs sans extraction de coordonnées
 */
function estimatePositions(placeholders, pdfInfo, totalText) {
  const estimatedPositions = [];
  
  for (const placeholder of placeholders) {
    // Chercher le contexte autour du placeholder
    const contextBefore = totalText.substring(Math.max(0, placeholder.startIndex - 200), placeholder.startIndex);
    const contextAfter = totalText.substring(placeholder.endIndex, Math.min(totalText.length, placeholder.endIndex + 200));
    
    // Estimer la page (simplifié: diviser le document en segments)
    const relativePosition = placeholder.startIndex / totalText.length;
    const estimatedPage = Math.ceil(relativePosition * pdfInfo.pageCount);
    
    // Pour un document A4 standard (842 points de hauteur)
    const pageHeight = pdfInfo.pages[estimatedPage - 1]?.height || 842;
    const pageWidth = pdfInfo.pages[estimatedPage - 1]?.width || 595;
    
    // Position Y: du haut vers le bas
    // Les placeholders de signature sont souvent en bas de page
    const estimatedY = pageHeight * 0.2; // 20% depuis le haut (donc vers le bas)
    
    // Position X: selon le rôle
    let estimatedX = 50; // Marge gauche par défaut
    if (placeholder.role.toLowerCase().includes('salarié') || 
        placeholder.role.toLowerCase().includes('salarie') ||
        placeholder.role.toLowerCase().includes('employé')) {
      estimatedX = pageWidth / 2 + 50; // Droite de la page
    }
    
    estimatedPositions.push({
      role: placeholder.role,
      label: placeholder.label,
      page: estimatedPage,
      x: Math.round(estimatedX),
      y: Math.round(estimatedY),
      width: placeholder.width,
      height: placeholder.height,
      confidence: 'estimated', // Indiquer que c'est une estimation
      context: {
        before: contextBefore.substring(contextBefore.length - 50),
        after: contextAfter.substring(0, 50),
      },
    });
  }
  
  return estimatedPositions;
}

/**
 * Crée un mapping de positions par template
 */
function createTemplateMapping(positions, filename) {
  const templateName = filename.replace(/[_-]\w+\.pdf$/, ''); // Enlever les ID uniques
  
  return {
    templateName,
    filename,
    positions: positions.map(p => ({
      role: p.role,
      page: p.page,
      x: p.x,
      y: p.y,
      width: p.width,
      height: p.height,
    })),
    metadata: {
      generatedAt: new Date().toISOString(),
      method: 'docuseal-placeholder-extraction',
    },
  };
}

async function main() {
  const args = process.argv.slice(2);
  
  if (args.length === 0) {
    console.error('Usage: node extract-signature-positions.js <chemin-pdf> [--save-template]');
    console.error('');
    console.error('Options:');
    console.error('  --save-template    Sauvegarder comme template réutilisable');
    console.error('');
    console.error('Exemples:');
    console.error('  node extract-signature-positions.js contrat_cddu.pdf');
    console.error('  node extract-signature-positions.js contrat_cddu.pdf --save-template');
    process.exit(1);
  }
  
  const pdfPath = args[0];
  const saveTemplate = args.includes('--save-template');
  
  if (!fs.existsSync(pdfPath)) {
    console.error(`❌ Fichier introuvable: ${pdfPath}`);
    process.exit(1);
  }
  
  console.log('═══════════════════════════════════════════════════════');
  console.log('   🔍 Extraction des positions DocuSeal');
  console.log('═══════════════════════════════════════════════════════\n');
  
  const filename = path.basename(pdfPath);
  console.log(`📄 PDF: ${filename}\n`);
  
  // 1. Analyser le PDF avec pdf-lib
  console.log('📖 Analyse du PDF...');
  const pdfInfo = await analyzePdfWithLib(pdfPath);
  console.log(`   Pages: ${pdfInfo.pageCount}`);
  pdfInfo.pages.forEach(p => {
    console.log(`   Page ${p.number}: ${Math.round(p.width)}x${Math.round(p.height)} points`);
  });
  console.log('');
  
  // 2. Extraire le texte
  console.log('📝 Extraction du texte...');
  let text = await extractTextWithPdfParse(pdfPath);
  
  if (!text) {
    text = extractTextFromPdfRaw(pdfPath);
  }
  
  console.log(`   ${text.length} caractères extraits\n`);
  
  // 3. Trouver les placeholders
  console.log('🔍 Recherche des placeholders DocuSeal...');
  const placeholders = extractPlaceholdersFromText(text);
  
  if (placeholders.length === 0) {
    console.log('   ❌ Aucun placeholder DocuSeal trouvé');
    console.log('');
    console.log('   Format attendu: {{Label;role=Role;type=signature;height=H;width=W}}');
    console.log('   Exemple: {{Signature Employé;role=Salarié;type=signature;height=60;width=150}}');
    process.exit(1);
  }
  
  console.log(`   ✅ ${placeholders.length} placeholder(s) trouvé(s):\n`);
  placeholders.forEach((p, i) => {
    console.log(`   ${i + 1}. ${p.label}`);
    console.log(`      Rôle: ${p.role}`);
    console.log(`      Type: ${p.type}`);
    console.log(`      Dimensions: ${p.width}x${p.height}px`);
    console.log('');
  });
  
  // 4. Estimer les positions
  console.log('📍 Calcul des positions...');
  const positions = estimatePositions(placeholders, pdfInfo, text);
  
  console.log('');
  console.log('═══════════════════════════════════════════════════════');
  console.log('   📊 Positions extraites');
  console.log('═══════════════════════════════════════════════════════\n');
  
  positions.forEach((pos, i) => {
    console.log(`${i + 1}. ${pos.role} - "${pos.label}"`);
    console.log(`   Page: ${pos.page}`);
    console.log(`   Position: (${pos.x}, ${pos.y})`);
    console.log(`   Dimensions: ${pos.width}x${pos.height}px`);
    console.log(`   Confiance: ${pos.confidence}`);
    console.log(`   Contexte avant: ...${pos.context.before}`);
    console.log(`   Contexte après: ${pos.context.after}...`);
    console.log('');
  });
  
  // 5. Format pour l'API
  console.log('═══════════════════════════════════════════════════════');
  console.log('   💻 Format pour create-real-signature.js');
  console.log('═══════════════════════════════════════════════════════\n');
  
  const positionsObject = {};
  positions.forEach(pos => {
    positionsObject[pos.role] = {
      page: pos.page,
      x: pos.x,
      y: pos.y,
      width: pos.width,
      height: pos.height,
    };
  });
  
  console.log('```javascript');
  console.log('const positions = ' + JSON.stringify(positionsObject, null, 2) + ';');
  console.log('```\n');
  
  // 6. Sauvegarder comme template si demandé
  if (saveTemplate) {
    const template = createTemplateMapping(positions, filename);
    const templateDir = path.join(__dirname, 'signature-templates');
    
    if (!fs.existsSync(templateDir)) {
      fs.mkdirSync(templateDir);
    }
    
    const templateFile = path.join(templateDir, `${template.templateName}.json`);
    fs.writeFileSync(templateFile, JSON.stringify(template, null, 2));
    
    console.log(`💾 Template sauvegardé: ${templateFile}\n`);
  }
  
  // 7. Avertissement sur les estimations
  console.log('⚠️  IMPORTANT:');
  console.log('   Les positions sont ESTIMÉES car pdf-lib ne peut pas extraire');
  console.log('   les coordonnées exactes du texte.');
  console.log('');
  console.log('   Pour des positions PRÉCISES, utilisez une de ces méthodes:');
  console.log('   1. Créer un template manuel basé sur vos vrais documents');
  console.log('   2. Utiliser pdf.js (plus complexe mais précis)');
  console.log('   3. Ajuster manuellement les coordonnées après tests');
  console.log('');
  console.log('💡 Conseil: Testez avec create-real-signature.js et ajustez');
  console.log('   les positions si nécessaire.\n');
}

main().catch(error => {
  console.error('❌ Erreur:', error.message);
  process.exit(1);
});
