// ========================================
// FICHIER: ValidationGuards.js
// SOLUTION D: Validations guard pour détecter problèmes de synchronisation
// ========================================

const { logSh } = require('./ErrorReporting');

/**
 * PATTERNS DE PLACEHOLDERS DÉTECTÉS
 */
const PLACEHOLDER_PATTERNS = {
  // Pattern "[XXX non défini]" ou "[XXX non résolu]"
  unresolvedVariable: /\[([^\]]+) non (défini|résolu)\]/g,

  // Pattern "{{XXX}}" (variable brute non résolue)
  rawVariable: /\{\{([^}]+)\}\}/g,

  // Pattern vide ou null
  empty: /^\s*$/
};

/**
 * Vérifie si une chaîne contient des placeholders non résolus
 * @param {string} text - Texte à vérifier
 * @param {Object} options - Options de vérification
 * @returns {Object} Résultat de la validation
 */
function hasUnresolvedPlaceholders(text, options = {}) {
  const {
    checkRawVariables = false,  // Vérifier aussi les {{XXX}}
    allowEmpty = false           // Autoriser les textes vides
  } = options;

  if (!text || typeof text !== 'string') {
    return {
      hasIssues: !allowEmpty,
      issues: !allowEmpty ? ['Text is null or not a string'] : [],
      placeholders: []
    };
  }

  const issues = [];
  const placeholders = [];

  // Vérifier "[XXX non défini]" ou "[XXX non résolu]"
  const unresolvedMatches = text.match(PLACEHOLDER_PATTERNS.unresolvedVariable);
  if (unresolvedMatches) {
    placeholders.push(...unresolvedMatches);
    issues.push(`Found ${unresolvedMatches.length} unresolved placeholders: ${unresolvedMatches.join(', ')}`);
  }

  // Vérifier "{{XXX}}" si demandé
  if (checkRawVariables) {
    const rawMatches = text.match(PLACEHOLDER_PATTERNS.rawVariable);
    if (rawMatches) {
      placeholders.push(...rawMatches);
      issues.push(`Found ${rawMatches.length} raw variables: ${rawMatches.join(', ')}`);
    }
  }

  // Vérifier vide
  if (!allowEmpty && PLACEHOLDER_PATTERNS.empty.test(text)) {
    issues.push('Text is empty or whitespace only');
  }

  return {
    hasIssues: issues.length > 0,
    issues,
    placeholders
  };
}

/**
 * GUARD: Valider un élément avant utilisation dans génération
 * Throw une erreur si l'élément contient des placeholders non résolus
 * @param {Object} element - Élément à valider
 * @param {Object} options - Options de validation
 * @throws {Error} Si validation échoue
 */
function validateElement(element, options = {}) {
  const {
    strict = true,           // Mode strict: throw error
    checkInstructions = true, // Vérifier les instructions
    checkContent = true,      // Vérifier le contenu résolu
    context = ''              // Contexte pour message d'erreur
  } = options;

  const errors = [];

  // Vérifier resolvedContent
  if (checkContent && element.resolvedContent) {
    const contentCheck = hasUnresolvedPlaceholders(element.resolvedContent, { allowEmpty: false });
    if (contentCheck.hasIssues) {
      errors.push({
        field: 'resolvedContent',
        content: element.resolvedContent.substring(0, 100),
        issues: contentCheck.issues,
        placeholders: contentCheck.placeholders
      });
    }
  }

  // Vérifier instructions
  if (checkInstructions && element.instructions) {
    const instructionsCheck = hasUnresolvedPlaceholders(element.instructions, { allowEmpty: false });
    if (instructionsCheck.hasIssues) {
      errors.push({
        field: 'instructions',
        content: element.instructions.substring(0, 100),
        issues: instructionsCheck.issues,
        placeholders: instructionsCheck.placeholders
      });
    }
  }

  // Si erreurs trouvées
  if (errors.length > 0) {
    const errorMessage = `
❌ VALIDATION FAILED: Element [${element.name || 'unknown'}] contains unresolved placeholders
${context ? `Context: ${context}` : ''}

Errors found:
${errors.map((err, i) => `
  ${i + 1}. Field: ${err.field}
     Content preview: "${err.content}..."
     Issues: ${err.issues.join('; ')}
     Placeholders: ${err.placeholders.join(', ')}
`).join('\n')}

⚠️ This indicates a synchronization problem between resolvedContent and instructions.
💡 Check that MissingKeywords.js properly updates BOTH fields when generating keywords.
`;

    logSh(errorMessage, 'ERROR');

    if (strict) {
      throw new Error(`Element [${element.name}] validation failed: ${errors.map(e => e.issues.join('; ')).join(' | ')}`);
    }

    return { valid: false, errors };
  }

  logSh(`✅ Validation OK: Element [${element.name}] has no unresolved placeholders`, 'DEBUG');
  return { valid: true, errors: [] };
}

/**
 * GUARD: Valider une hiérarchie complète
 * @param {Object} hierarchy - Hiérarchie à valider
 * @param {Object} options - Options de validation
 * @returns {Object} Résultat de validation avec statistiques
 */
function validateHierarchy(hierarchy, options = {}) {
  const {
    strict = false  // En mode non-strict, on continue même avec des erreurs
  } = options;

  const stats = {
    totalElements: 0,
    validElements: 0,
    invalidElements: 0,
    errors: []
  };

  Object.entries(hierarchy).forEach(([path, section]) => {
    // Valider titre
    if (section.title && section.title.originalElement) {
      stats.totalElements++;
      try {
        const result = validateElement(section.title.originalElement, {
          strict,
          context: `Hierarchy path: ${path} (title)`
        });
        if (result.valid) {
          stats.validElements++;
        } else {
          stats.invalidElements++;
          stats.errors.push({ path, element: 'title', errors: result.errors });
        }
      } catch (error) {
        stats.invalidElements++;
        stats.errors.push({ path, element: 'title', error: error.message });
        if (strict) throw error;
      }
    }

    // Valider texte
    if (section.text && section.text.originalElement) {
      stats.totalElements++;
      try {
        const result = validateElement(section.text.originalElement, {
          strict,
          context: `Hierarchy path: ${path} (text)`
        });
        if (result.valid) {
          stats.validElements++;
        } else {
          stats.invalidElements++;
          stats.errors.push({ path, element: 'text', errors: result.errors });
        }
      } catch (error) {
        stats.invalidElements++;
        stats.errors.push({ path, element: 'text', error: error.message });
        if (strict) throw error;
      }
    }

    // Valider questions FAQ
    if (section.questions && section.questions.length > 0) {
      section.questions.forEach((q, index) => {
        if (q.originalElement) {
          stats.totalElements++;
          try {
            const result = validateElement(q.originalElement, {
              strict,
              context: `Hierarchy path: ${path} (question ${index + 1})`
            });
            if (result.valid) {
              stats.validElements++;
            } else {
              stats.invalidElements++;
              stats.errors.push({ path, element: `question_${index + 1}`, errors: result.errors });
            }
          } catch (error) {
            stats.invalidElements++;
            stats.errors.push({ path, element: `question_${index + 1}`, error: error.message });
            if (strict) throw error;
          }
        }
      });
    }
  });

  // Log résumé
  if (stats.invalidElements > 0) {
    logSh(`⚠️ Hierarchy validation: ${stats.invalidElements}/${stats.totalElements} elements have unresolved placeholders`, 'WARNING');
    logSh(`   Errors: ${JSON.stringify(stats.errors, null, 2)}`, 'WARNING');
  } else {
    logSh(`✅ Hierarchy validation: All ${stats.totalElements} elements are valid`, 'INFO');
  }

  return {
    valid: stats.invalidElements === 0,
    stats
  };
}

/**
 * HELPER: Extraire tous les placeholders d'un texte
 * @param {string} text - Texte à analyser
 * @returns {Array} Liste des placeholders trouvés
 */
function extractPlaceholders(text) {
  if (!text || typeof text !== 'string') return [];

  const placeholders = [];

  // Extraire "[XXX non défini]"
  const unresolvedMatches = text.match(PLACEHOLDER_PATTERNS.unresolvedVariable);
  if (unresolvedMatches) {
    placeholders.push(...unresolvedMatches);
  }

  // Extraire "{{XXX}}"
  const rawMatches = text.match(PLACEHOLDER_PATTERNS.rawVariable);
  if (rawMatches) {
    placeholders.push(...rawMatches);
  }

  return placeholders;
}

module.exports = {
  // Fonctions principales
  validateElement,
  validateHierarchy,
  hasUnresolvedPlaceholders,

  // Helpers
  extractPlaceholders,
  PLACEHOLDER_PATTERNS
};
