// ========================================
// FICHIER: lib/error-reporting.js - CONVERTI POUR NODE.JS
// Description: Système de validation et rapport d'erreur
// ========================================

// Lazy loading des modules externes (évite blocage googleapis)
let google, nodemailer;
const fs = require('fs').promises;
const path = require('path');
const pino = require('pino');
const pretty = require('pino-pretty');
const { PassThrough } = require('stream');
const WebSocket = require('ws');

// Configuration
const SHEET_ID = process.env.GOOGLE_SHEETS_ID || '1iA2GvWeUxX-vpnAMfVm3ZMG9LhaC070SdGssEcXAh2c';

// WebSocket server for real-time logs
let wsServer;
const wsClients = new Set();

// Enhanced Pino logger configuration with real-time streaming and dated files
const now = new Date();
const timestamp = now.toISOString().slice(0, 10) + '_' + 
                 now.toLocaleTimeString('fr-FR').replace(/:/g, '-');
const logFile = path.join(__dirname, '..', 'logs', `seo-generator-${timestamp}.log`);

// File destination with dated filename - JSON format
const fileDest = pino.destination({
  dest: logFile,
  mkdir: true,
  sync: false,
  minLength: 0
});

// Console destination - Pretty format
const prettyStream = pretty({
  colorize: true,
  translateTime: 'HH:MM:ss.l',
  ignore: 'pid,hostname',
  destination: 1  // stdout
});

// Custom levels for Pino
const customLevels = {
  trace: 5,
  debug: 10,
  info: 20,
  prompt: 25,
  llm: 26,
  warn: 30,
  error: 40,
  fatal: 50
};

// ✅ Multistream: pretty sur console + JSON dans fichier (pas de duplication)
const logger = pino(
  {
    level: 'debug',
    base: undefined,
    timestamp: pino.stdTimeFunctions.isoTime,
    customLevels: customLevels,
    useOnlyCustomLevels: true,
    browser: { disabled: true }
  },
  pino.multistream([
    { level: 'debug', stream: prettyStream },  // Console: pretty format
    { level: 'debug', stream: fileDest }       // Fichier: JSON format
  ])
);

// Initialize WebSocket server (only when explicitly requested)
function initWebSocketServer() {
  if (!wsServer && process.env.ENABLE_LOG_WS === 'true') {
    try {
      const logPort = process.env.LOG_WS_PORT || 8082;
      wsServer = new WebSocket.Server({ port: logPort });
      
      wsServer.on('connection', (ws) => {
        wsClients.add(ws);
        logger.info('Client connected to log WebSocket');
        
        ws.on('close', () => {
          wsClients.delete(ws);
          logger.info('Client disconnected from log WebSocket');
        });
        
        ws.on('error', (error) => {
          logger.error('WebSocket error:', error.message);
          wsClients.delete(ws);
        });
      });
      
      wsServer.on('error', (error) => {
        if (error.code === 'EADDRINUSE') {
          logger.warn(`WebSocket port ${logPort} already in use`);
          wsServer = null;
        } else {
          logger.error('WebSocket server error:', error.message);
        }
      });
      
      logger.info(`Log WebSocket server started on port ${logPort}`);
    } catch (error) {
      logger.warn(`Failed to start WebSocket server: ${error.message}`);
      wsServer = null;
    }
  }
}

// Broadcast log to WebSocket clients
function broadcastLog(message, level) {
  const logData = {
    timestamp: new Date().toISOString(),
    level: level.toUpperCase(),
    message: message
  };
  
  wsClients.forEach(ws => {
    if (ws.readyState === WebSocket.OPEN) {
      try {
        ws.send(JSON.stringify(logData));
      } catch (error) {
        logger.error('Failed to send log to WebSocket client:', error.message);
        wsClients.delete(ws);
      }
    }
  });
}

// 🔄 NODE.JS : Google Sheets API setup (remplace SpreadsheetApp)
let sheets;
let auth;

async function initGoogleSheets() {
  if (!sheets) {
    // Lazy load googleapis seulement quand nécessaire
    if (!google) {
      google = require('googleapis').google;
    }
    
    // Configuration auth Google Sheets API
    // Pour la démo, on utilise une clé de service (à configurer)
    auth = new google.auth.GoogleAuth({
      keyFile: process.env.GOOGLE_CREDENTIALS_PATH, // Chemin vers fichier JSON credentials
      scopes: ['https://www.googleapis.com/auth/spreadsheets']
    });
    
    sheets = google.sheets({ version: 'v4', auth });
  }
  return sheets;
}

async function logSh(message, level = 'INFO') {
  // Initialize WebSocket server if not already done
  if (!wsServer) {
    initWebSocketServer();
  }

  // Convert level to lowercase for Pino
  const pinoLevel = level.toLowerCase();
  
  // Enhanced trace metadata for hierarchical logging
  const traceData = {};
  if (message.includes('▶') || message.includes('✔') || message.includes('✖') || message.includes('•')) {
    traceData.trace = true;
    traceData.evt = message.includes('▶') ? 'span.start' : 
                   message.includes('✔') ? 'span.end' : 
                   message.includes('✖') ? 'span.error' : 'span.event';
  }
  
  // Log with Pino (handles console output with pretty formatting and file logging)
  switch (pinoLevel) {
    case 'error':
      logger.error(traceData, message);
      break;
    case 'warning':
    case 'warn':
      logger.warn(traceData, message);
      break;
    case 'debug':
      logger.debug(traceData, message);
      break;
    case 'trace':
      logger.trace(traceData, message);
      break;
    case 'prompt':
      logger.prompt(traceData, message);
      break;
    case 'llm':
      logger.llm(traceData, message);
      break;
    default:
      logger.info(traceData, message);
  }
  
  // Broadcast to WebSocket clients for real-time viewing
  broadcastLog(message, level);
  
  // Force immediate flush to ensure real-time display and prevent log loss
  logger.flush();
  
  // Log to Google Sheets if enabled (async, non-blocking)
  if (process.env.ENABLE_SHEETS_LOGGING === 'true') {
    setImmediate(() => {
      logToGoogleSheets(message, level).catch(err => {
        // Silent fail for Google Sheets logging to avoid recursion
      });
    });
  }
}

// Fonction pour déterminer si on doit logger en console
function shouldLogToConsole(messageLevel, configLevel) {
  const levels = { DEBUG: 0, INFO: 1, WARNING: 2, ERROR: 3 };
  return levels[messageLevel] >= levels[configLevel];
}

// Log to file is now handled by Pino transport
// This function is kept for compatibility but does nothing
async function logToFile(message, level) {
  // Pino handles file logging via transport configuration
  // This function is deprecated and kept for compatibility only
}

// 🔄 NODE.JS : Log vers Google Sheets (version async)
async function logToGoogleSheets(message, level) {
  try {
    const sheetsApi = await initGoogleSheets();
    
    const values = [[
      new Date().toISOString(),
      level,
      message,
      'Node.js workflow'
    ]];
    
    await sheetsApi.spreadsheets.values.append({
      spreadsheetId: SHEET_ID,
      range: 'Logs!A:D',
      valueInputOption: 'RAW',
      insertDataOption: 'INSERT_ROWS',
      resource: { values }
    });
    
  } catch (error) {
    logSh('Échec log Google Sheets: ' + error.message, 'WARNING'); // Using logSh instead of console.warn
  }
}

// 🔄 NODE.JS : Version simplifiée cleanLogSheet 
async function cleanLogSheet() {
  try {
    logSh('🧹 Nettoyage logs...', 'INFO'); // Using logSh instead of console.log
    
    // 1. Nettoyer fichiers logs locaux (garder 7 derniers jours)
    await cleanLocalLogs();
    
    // 2. Nettoyer Google Sheets si activé
    if (process.env.ENABLE_SHEETS_LOGGING === 'true') {
      await cleanGoogleSheetsLogs();
    }
    
    logSh('✅ Logs nettoyés', 'INFO'); // Using logSh instead of console.log
    
  } catch (error) {
    logSh('Erreur nettoyage logs: ' + error.message, 'ERROR'); // Using logSh instead of console.error
  }
}

async function cleanLocalLogs() {
  try {
    // Note: With Pino, log files are managed differently
    // This function is kept for compatibility with Google Sheets logs cleanup
    // Pino log rotation should be handled by external tools like logrotate
    
    // For now, we keep the basic cleanup for any remaining old log files
    const logsDir = path.join(__dirname, '../logs');
    
    try {
      const files = await fs.readdir(logsDir);
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - 7); // Garder 7 jours
      
      for (const file of files) {
        if (file.endsWith('.log')) {
          const filePath = path.join(logsDir, file);
          const stats = await fs.stat(filePath);
          
          if (stats.mtime < cutoffDate) {
            await fs.unlink(filePath);
            logSh(`🗑️ Supprimé log ancien: ${file}`, 'INFO');
          }
        }
      }
    } catch (error) {
      // Directory might not exist, that's fine
    }
  } catch (error) {
    // Silent fail
  }
}

async function cleanGoogleSheetsLogs() {
  try {
    const sheetsApi = await initGoogleSheets();
    
    // Clear + remettre headers
    await sheetsApi.spreadsheets.values.clear({
      spreadsheetId: SHEET_ID,
      range: 'Logs!A:D'
    });
    
    await sheetsApi.spreadsheets.values.update({
      spreadsheetId: SHEET_ID,
      range: 'Logs!A1:D1',
      valueInputOption: 'RAW',
      resource: {
        values: [['Timestamp', 'Level', 'Message', 'Source']]
      }
    });
    
  } catch (error) {
    logSh('Échec nettoyage Google Sheets: ' + error.message, 'WARNING'); // Using logSh instead of console.warn
  }
}

// ============= VALIDATION PRINCIPALE - IDENTIQUE =============

function validateWorkflowIntegrity(elements, generatedContent, finalXML, csvData) {
  logSh('🔍 >>> VALIDATION INTÉGRITÉ WORKFLOW <<<', 'INFO'); // Using logSh instead of console.log
  
  const errors = [];
  const warnings = [];
  const stats = {
    elementsExtracted: elements.length,
    contentGenerated: Object.keys(generatedContent).length,
    tagsReplaced: 0,
    tagsRemaining: 0
  };
  
  // TEST 1: Détection tags dupliqués
  const duplicateCheck = detectDuplicateTags(elements);
  if (duplicateCheck.hasDuplicates) {
    errors.push({
      type: 'DUPLICATE_TAGS',
      severity: 'HIGH',
      message: `Tags dupliqués détectés: ${duplicateCheck.duplicates.join(', ')}`,
      impact: 'Certains contenus ne seront pas remplacés dans le XML final',
      suggestion: 'Vérifier le template XML pour corriger la structure'
    });
  }
  
  // TEST 2: Cohérence éléments extraits vs générés
  const missingGeneration = elements.filter(el => !generatedContent[el.originalTag]);
  if (missingGeneration.length > 0) {
    errors.push({
      type: 'MISSING_GENERATION',
      severity: 'HIGH', 
      message: `${missingGeneration.length} éléments extraits mais non générés`,
      details: missingGeneration.map(el => el.originalTag),
      impact: 'Contenu incomplet dans le XML final'
    });
  }
  
  // TEST 3: Tags non remplacés dans XML final
  const remainingTags = (finalXML.match(/\|[^|]*\|/g) || []);
  stats.tagsRemaining = remainingTags.length;
  
  if (remainingTags.length > 0) {
    errors.push({
      type: 'UNREPLACED_TAGS',
      severity: 'HIGH',
      message: `${remainingTags.length} tags non remplacés dans le XML final`,
      details: remainingTags.slice(0, 5),
      impact: 'XML final contient des placeholders non remplacés'
    });
  }
  
  // TEST 4: Variables CSV manquantes
  const missingVars = detectMissingCSVVariables(csvData);
  if (missingVars.length > 0) {
    warnings.push({
      type: 'MISSING_CSV_VARIABLES',
      severity: 'MEDIUM',
      message: `Variables CSV manquantes: ${missingVars.join(', ')}`,
      impact: 'Système de génération de mots-clés automatique activé'
    });
  }
  
  // TEST 5: Qualité génération IA
  const generationQuality = assessGenerationQuality(generatedContent);
  if (generationQuality.errorRate > 0.1) {
    warnings.push({
      type: 'GENERATION_QUALITY',
      severity: 'MEDIUM', 
      message: `${(generationQuality.errorRate * 100).toFixed(1)}% d'erreurs de génération IA`,
      impact: 'Qualité du contenu potentiellement dégradée'
    });
  }
  
  // CALCUL STATS FINALES
  stats.tagsReplaced = elements.length - remainingTags.length;
  stats.successRate = stats.elementsExtracted > 0 ? 
    ((stats.tagsReplaced / elements.length) * 100).toFixed(1) : '100';
  
  const report = {
    timestamp: new Date().toISOString(),
    csvData: { mc0: csvData.mc0, t0: csvData.t0 },
    stats: stats,
    errors: errors,
    warnings: warnings,
    status: errors.length === 0 ? 'SUCCESS' : 'ERROR'
  };
  
  const logLevel = report.status === 'SUCCESS' ? 'INFO' : 'ERROR';
  logSh(`✅ Validation terminée: ${report.status} (${errors.length} erreurs, ${warnings.length} warnings)`, 'INFO'); // Using logSh instead of console.log
  
  // ENVOYER RAPPORT SI ERREURS (async en arrière-plan)
  if (errors.length > 0 || warnings.length > 2) {
    sendErrorReport(report).catch(err => {
      logSh('Erreur envoi rapport: ' + err.message, 'ERROR'); // Using logSh instead of console.error
    });
  }
  
  return report;
}

// ============= HELPERS - IDENTIQUES =============

function detectDuplicateTags(elements) {
  const tagCounts = {};
  const duplicates = [];
  
  elements.forEach(element => {
    const tag = element.originalTag;
    tagCounts[tag] = (tagCounts[tag] || 0) + 1;
    
    if (tagCounts[tag] === 2) {
      duplicates.push(tag);
      logSh(`❌ DUPLICATE détecté: ${tag}`, 'ERROR'); // Using logSh instead of console.error
    }
  });
  
  return {
    hasDuplicates: duplicates.length > 0,
    duplicates: duplicates,
    counts: tagCounts
  };
}

function detectMissingCSVVariables(csvData) {
  const missing = [];
  
  if (!csvData.mcPlus1 || csvData.mcPlus1.split(',').length < 4) {
    missing.push('MC+1 (insuffisant)');
  }
  if (!csvData.tPlus1 || csvData.tPlus1.split(',').length < 4) {
    missing.push('T+1 (insuffisant)');  
  }
  if (!csvData.lPlus1 || csvData.lPlus1.split(',').length < 4) {
    missing.push('L+1 (insuffisant)');
  }
  
  return missing;
}

function assessGenerationQuality(generatedContent) {
  let errorCount = 0;
  let totalCount = Object.keys(generatedContent).length;
  
  Object.values(generatedContent).forEach(content => {
    if (content && (
        content.includes('[ERREUR') || 
        content.includes('ERROR') ||
        content.length < 10
    )) {
      errorCount++;
    }
  });
  
  return {
    errorRate: totalCount > 0 ? errorCount / totalCount : 0,
    totalGenerated: totalCount,
    errorsFound: errorCount
  };
}

// 🔄 NODE.JS : Email avec nodemailer (remplace MailApp)
async function sendErrorReport(report) {
  try {
    logSh('📧 Envoi rapport d\'erreur par email...', 'INFO'); // Using logSh instead of console.log
    
    // Lazy load nodemailer seulement quand nécessaire
    if (!nodemailer) {
      nodemailer = require('nodemailer');
    }
    
    // Configuration nodemailer (Gmail par exemple)
    const transporter = nodemailer.createTransport({
      service: 'gmail',
      auth: {
        user: process.env.EMAIL_USER, // 'your-email@gmail.com'
        pass: process.env.EMAIL_APP_PASSWORD // App password Google
      }
    });
    
    const subject = `Erreur Workflow SEO Node.js - ${report.status} - ${report.csvData.mc0}`;
    const htmlBody = createHTMLReport(report);
    
    const mailOptions = {
      from: process.env.EMAIL_USER,
      to: 'alexistrouve.pro@gmail.com',
      subject: subject,
      html: htmlBody,
      attachments: [{
        filename: `error-report-${Date.now()}.json`,
        content: JSON.stringify(report, null, 2),
        contentType: 'application/json'
      }]
    };
    
    await transporter.sendMail(mailOptions);
    logSh('✅ Rapport d\'erreur envoyé par email', 'INFO'); // Using logSh instead of console.log
    
  } catch (error) {
    logSh(`❌ Échec envoi email: ${error.message}`, 'ERROR'); // Using logSh instead of console.error
  }
}

// ============= HTML REPORT - IDENTIQUE =============

function createHTMLReport(report) {
  const statusColor = report.status === 'SUCCESS' ? '#28a745' : '#dc3545';
  
  let html = `
    <div style="font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto;">
      <h1 style="color: ${statusColor};">Rapport Workflow SEO Automatisé (Node.js)</h1>
      
      <div style="background: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0;">
        <h2>Résumé Exécutif</h2>
        <p><strong>Statut:</strong> <span style="color: ${statusColor};">${report.status}</span></p>
        <p><strong>Article:</strong> ${report.csvData.t0}</p>
        <p><strong>Mot-clé:</strong> ${report.csvData.mc0}</p>
        <p><strong>Taux de réussite:</strong> ${report.stats.successRate}%</p>
        <p><strong>Timestamp:</strong> ${report.timestamp}</p>
        <p><strong>Plateforme:</strong> Node.js Server</p>
      </div>`;
  
  if (report.errors.length > 0) {
    html += `<div style="background: #f8d7da; padding: 15px; border-radius: 5px; margin: 20px 0;">
      <h2>Erreurs Critiques (${report.errors.length})</h2>`;
    
    report.errors.forEach((error, i) => {
      html += `
        <div style="margin: 10px 0; padding: 10px; border-left: 3px solid #dc3545;">
          <h4>${i + 1}. ${error.type}</h4>
          <p><strong>Message:</strong> ${error.message}</p>
          <p><strong>Impact:</strong> ${error.impact}</p>
          ${error.suggestion ? `<p><strong>Solution:</strong> ${error.suggestion}</p>` : ''}
        </div>`;
    });
    
    html += `</div>`;
  }
  
  if (report.warnings.length > 0) {
    html += `<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin: 20px 0;">
      <h2>Avertissements (${report.warnings.length})</h2>`;
    
    report.warnings.forEach((warning, i) => {
      html += `
        <div style="margin: 10px 0; padding: 10px; border-left: 3px solid #ffc107;">
          <h4>${i + 1}. ${warning.type}</h4>
          <p>${warning.message}</p>
        </div>`;
    });
    
    html += `</div>`;
  }
  
  html += `
      <div style="background: #e9ecef; padding: 15px; border-radius: 5px; margin: 20px 0;">
        <h2>Statistiques Détaillées</h2>
        <ul>
          <li>Éléments extraits: ${report.stats.elementsExtracted}</li>
          <li>Contenus générés: ${report.stats.contentGenerated}</li>
          <li>Tags remplacés: ${report.stats.tagsReplaced}</li>
          <li>Tags restants: ${report.stats.tagsRemaining}</li>
        </ul>
      </div>
      
      <div style="background: #d1ecf1; padding: 15px; border-radius: 5px; margin: 20px 0;">
        <h2>Informations Système</h2>
        <ul>
          <li>Plateforme: Node.js</li>
          <li>Version: ${process.version}</li>
          <li>Mémoire: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB</li>
          <li>Uptime: ${Math.round(process.uptime())}s</li>
        </ul>
      </div>
    </div>`;
  
  return html;
}

// 🔄 NODE.JS EXPORTS
module.exports = {
  logSh,
  cleanLogSheet,
  validateWorkflowIntegrity,
  detectDuplicateTags,
  detectMissingCSVVariables,
  assessGenerationQuality,
  sendErrorReport,
  createHTMLReport,
  initWebSocketServer
};