/**
 * Script de migration des PDF des avenants depuis Airtable vers S3
 * 
 * Ce script télécharge les PDF des avenants depuis Airtable et les uploade sur S3,
 * puis met à jour la base de données Supabase avec les URLs.
 * 
 * Prérequis:
 * - Le CSV doit avoir les colonnes: Reference, Avenant PDF
 * - Les variables d'environnement AWS et Supabase doivent être configurées
 * 
 * Utilisation:
 *   npx tsx scripts/migrate-avenants-pdf-from-airtable.ts
 */

import { createClient } from '@supabase/supabase-js';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import * as fs from 'fs';
import * as path from 'path';
import * as readline from 'readline';
import * as https from 'https';
import * as http from 'http';
import { config } from 'dotenv';

// Charger les variables d'environnement
config({ path: path.join(process.cwd(), '.env.local') });

// Configuration
const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const SUPABASE_SERVICE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY!;
const CSV_FILE_PATH = path.join(process.cwd(), 'Contrats-PDF-Avenants.csv');

// AWS S3 Configuration
const AWS_REGION = process.env.AWS_REGION || 'eu-west-3';
const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID!;
const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY!;
const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME || 'odentas-documents';

if (!SUPABASE_URL || !SUPABASE_SERVICE_KEY) {
  console.error('❌ Variables d\'environnement Supabase manquantes');
  process.exit(1);
}

if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {
  console.error('❌ Variables d\'environnement AWS manquantes');
  process.exit(1);
}

const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY);
const s3Client = new S3Client({
  region: AWS_REGION,
  credentials: {
    accessKeyId: AWS_ACCESS_KEY_ID,
    secretAccessKey: AWS_SECRET_ACCESS_KEY,
  },
});

interface AirtableAvenantPdfRow {
  reference: string;           // Référence du contrat
  avenant_pdf_url: string;     // URL du PDF de l'avenant
}

/**
 * Lit et parse le fichier CSV
 */
async function readCSV(): Promise<AirtableAvenantPdfRow[]> {
  return new Promise((resolve, reject) => {
    const rows: AirtableAvenantPdfRow[] = [];
    const fileStream = fs.createReadStream(CSV_FILE_PATH);
    const rl = readline.createInterface({
      input: fileStream,
      crlfDelay: Infinity
    });
    
    let isFirstLine = true;
    let pdfColumnIndex = -1;
    let referenceColumnIndex = -1;
    
    rl.on('line', (line) => {
      // Parser la première ligne pour trouver les index des colonnes
      if (isFirstLine) {
        isFirstLine = false;
        const matches = line.match(/(?:^|,)("(?:[^"]|"")*"|[^,]*)/g);
        if (!matches) return;
        
        const cols = matches.map(m => {
          let val = m.replace(/^,/, '');
          if (val.startsWith('"') && val.endsWith('"')) {
            val = val.slice(1, -1).replace(/""/g, '"');
          }
          return val.trim();
        });
        
        referenceColumnIndex = cols.indexOf('Reference');
        pdfColumnIndex = cols.indexOf('Avenant PDF');
        
        if (referenceColumnIndex === -1 || pdfColumnIndex === -1) {
          console.error('❌ Colonnes "Reference" ou "Avenant PDF" non trouvées');
          reject(new Error('Colonnes manquantes dans le CSV'));
          return;
        }
        return;
      }
      
      // Parser les lignes de données
      const matches = line.match(/(?:^|,)("(?:[^"]|"")*"|[^,]*)/g);
      if (!matches || matches.length <= Math.max(referenceColumnIndex, pdfColumnIndex)) return;
      
      const cols = matches.map(m => {
        let val = m.replace(/^,/, '');
        if (val.startsWith('"') && val.endsWith('"')) {
          val = val.slice(1, -1).replace(/""/g, '"');
        }
        return val.trim();
      });
      
      const reference = cols[referenceColumnIndex] || '';
      let pdfUrl = cols[pdfColumnIndex] || '';
      
      // Extraire l'URL si le format est "nom_fichier.pdf (url)"
      const urlMatch = pdfUrl.match(/\(https?:\/\/[^)]+\)/);
      if (urlMatch) {
        pdfUrl = urlMatch[0].slice(1, -1); // Retirer les parenthèses
      }
      
      if (reference && pdfUrl && pdfUrl.startsWith('http')) {
        rows.push({
          reference,
          avenant_pdf_url: pdfUrl
        });
      }
    });
    
    rl.on('close', () => resolve(rows));
    rl.on('error', reject);
  });
}

/**
 * Télécharge un fichier depuis une URL
 */
async function downloadFile(url: string): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    const protocol = url.startsWith('https') ? https : http;
    
    protocol.get(url, (response) => {
      if (response.statusCode === 301 || response.statusCode === 302) {
        // Suivre la redirection
        if (response.headers.location) {
          downloadFile(response.headers.location).then(resolve).catch(reject);
          return;
        }
      }
      
      if (response.statusCode !== 200) {
        reject(new Error(`Erreur HTTP: ${response.statusCode}`));
        return;
      }
      
      const chunks: Buffer[] = [];
      response.on('data', (chunk) => chunks.push(chunk));
      response.on('end', () => resolve(Buffer.concat(chunks)));
      response.on('error', reject);
    }).on('error', reject);
  });
}

/**
 * Upload un fichier sur S3
 */
async function uploadToS3(buffer: Buffer, key: string, contentType: string): Promise<string> {
  const command = new PutObjectCommand({
    Bucket: S3_BUCKET_NAME,
    Key: key,
    Body: buffer,
    ContentType: contentType,
  });
  
  await s3Client.send(command);
  
  // Retourner l'URL publique (si le bucket est public) ou une URL signée
  return `https://${S3_BUCKET_NAME}.s3.${AWS_REGION}.amazonaws.com/${key}`;
}

/**
 * Recherche les avenants d'un contrat
 */
async function findAvenantsForContract(contractReference: string): Promise<any[]> {
  const { data: contract } = await supabase
    .from('cddu_contracts')
    .select('id')
    .or(`contract_number.eq.${contractReference},reference.eq.${contractReference}`)
    .maybeSingle();
  
  if (!contract) {
    return [];
  }
  
  const { data: avenants } = await supabase
    .from('avenants')
    .select('id, numero_avenant, date_avenant, pdf_s3_key')
    .eq('contract_id', contract.id)
    .order('date_avenant', { ascending: true });
  
  return avenants || [];
}

/**
 * Met à jour un avenant avec le PDF
 */
async function updateAvenantWithPdf(avenantId: string, s3Key: string, pdfUrl: string) {
  const { error } = await supabase
    .from('avenants')
    .update({
      pdf_s3_key: s3Key,
      pdf_url: pdfUrl,
    })
    .eq('id', avenantId);
  
  if (error) {
    throw error;
  }
}

/**
 * Fonction principale de migration
 */
async function migrate() {
  console.log('🚀 Début de la migration des PDF des avenants depuis Airtable\n');
  
  // Vérifier que le fichier CSV existe
  if (!fs.existsSync(CSV_FILE_PATH)) {
    console.error(`❌ Fichier CSV non trouvé: ${CSV_FILE_PATH}`);
    console.error('📝 Placez le fichier "Contrats-PDF-Avenants.csv" à la racine du projet');
    process.exit(1);
  }
  
  console.log(`📄 Lecture du fichier: ${CSV_FILE_PATH}\n`);
  
  const rows = await readCSV();
  console.log(`📊 Nombre de lignes avec PDF: ${rows.length}\n`);
  
  const stats = {
    total: rows.length,
    success: 0,
    noAvenants: 0,
    downloadError: 0,
    uploadError: 0,
    updateError: 0,
  };
  
  for (let i = 0; i < rows.length; i++) {
    const row = rows[i];
    const index = i + 1;
    
    console.log(`\n[${index}/${rows.length}] Traitement de ${row.reference}`);
    
    // Rechercher les avenants pour ce contrat
    const avenants = await findAvenantsForContract(row.reference);
    
    if (avenants.length === 0) {
      console.log(`   ⚠️  Aucun avenant trouvé pour ce contrat`);
      stats.noAvenants++;
      continue;
    }
    
    console.log(`   ✅ ${avenants.length} avenant(s) trouvé(s)`);
    
    // Si plusieurs avenants, on prend le premier (le plus ancien)
    // Dans Airtable, il n'y a qu'un seul PDF par contrat
    const avenant = avenants[0];
    
    if (avenant.pdf_s3_key) {
      console.log(`   ⏭️  PDF déjà présent (${avenant.pdf_s3_key}) - Ignoré`);
      stats.success++;
      continue;
    }
    
    try {
      // Télécharger le PDF depuis Airtable
      console.log(`   📥 Téléchargement du PDF...`);
      const pdfBuffer = await downloadFile(row.avenant_pdf_url);
      console.log(`   ✅ PDF téléchargé (${(pdfBuffer.length / 1024).toFixed(2)} KB)`);
      
      // Générer la clé S3
      const timestamp = new Date().getTime();
      const s3Key = `avenants/${row.reference}_avenant_${timestamp}.pdf`;
      
      // Upload sur S3
      console.log(`   ☁️  Upload vers S3...`);
      const pdfUrl = await uploadToS3(pdfBuffer, s3Key, 'application/pdf');
      console.log(`   ✅ PDF uploadé: ${s3Key}`);
      
      // Mettre à jour l'avenant dans Supabase
      console.log(`   💾 Mise à jour de l'avenant ${avenant.numero_avenant}...`);
      await updateAvenantWithPdf(avenant.id, s3Key, pdfUrl);
      console.log(`   ✅ Avenant mis à jour`);
      
      stats.success++;
      
    } catch (error: any) {
      console.log(`   ❌ Erreur: ${error.message}`);
      if (error.message.includes('HTTP') || error.message.includes('download')) {
        stats.downloadError++;
      } else if (error.message.includes('S3') || error.message.includes('upload')) {
        stats.uploadError++;
      } else {
        stats.updateError++;
      }
    }
    
    // Délai entre chaque traitement pour éviter de surcharger les APIs
    await new Promise(resolve => setTimeout(resolve, 500));
  }
  
  // Résumé
  console.log('\n\n' + '='.repeat(60));
  console.log('📊 RÉSUMÉ DE LA MIGRATION');
  console.log('='.repeat(60));
  console.log(`Total de PDF:              ${stats.total}`);
  console.log(`PDF migrés avec succès:    ${stats.success} ✅`);
  console.log(`Contrats sans avenants:    ${stats.noAvenants} ⚠️`);
  console.log(`Erreurs téléchargement:    ${stats.downloadError} ❌`);
  console.log(`Erreurs upload S3:         ${stats.uploadError} ❌`);
  console.log(`Erreurs mise à jour DB:    ${stats.updateError} ❌`);
  console.log('='.repeat(60));
  
  console.log('\n✅ Migration terminée!\n');
}

// Exécuter la migration
migrate().catch(console.error);
