#!/usr/bin/env tsx

/**
 * Script de synchronisation de la documentation Docusaurus
 * Vérifie la cohérence entre Vision et Current
 * Génère des rapports de synchronisation
 */

import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'fs';
import { join, relative } from 'path';
import { execSync } from 'child_process';

interface DocFile {
  path: string;
  content: string;
  lastModified: Date;
  size: number;
}

interface SyncReport {
  timestamp: Date;
  visionFiles: DocFile[];
  currentFiles: DocFile[];
  inconsistencies: Inconsistency[];
  recommendations: string[];
}

interface Inconsistency {
  type: 'missing' | 'outdated' | 'mismatch' | 'broken-link';
  file: string;
  description: string;
  severity: 'low' | 'medium' | 'high' | 'critical';
  suggestion: string;
}

class DocSyncManager {
  private visionPath = 'veza-docs/docs-vision';
  private currentPath = 'veza-docs/docs-current';
  private assetsPath = 'veza-docs/docs-assets';
  private reportPath = 'REPORTS';

  constructor() {
    console.log('🔄 Initialisation du gestionnaire de synchronisation de documentation');
  }

  /**
   * Scanne un répertoire et retourne la liste des fichiers
   */
  private scanDirectory(dirPath: string): DocFile[] {
    if (!existsSync(dirPath)) {
      console.warn(`⚠️  Répertoire non trouvé: ${dirPath}`);
      return [];
    }

    const files: DocFile[] = [];
    const scanDir = (currentPath: string) => {
      const entries = readdirSync(currentPath);
      
      for (const entry of entries) {
        const fullPath = join(currentPath, entry);
        const stat = statSync(fullPath);
        
        if (stat.isDirectory()) {
          scanDir(fullPath);
        } else if (entry.endsWith('.md')) {
          try {
            const content = readFileSync(fullPath, 'utf-8');
            files.push({
              path: relative(dirPath, fullPath),
              content,
              lastModified: stat.mtime,
              size: stat.size
            });
          } catch (error) {
            console.error(`❌ Erreur lecture fichier ${fullPath}:`, error);
          }
        }
      }
    };

    scanDir(dirPath);
    return files;
  }

  /**
   * Vérifie la cohérence entre Vision et Current
   */
  private checkConsistency(visionFiles: DocFile[], currentFiles: DocFile[]): Inconsistency[] {
    const inconsistencies: Inconsistency[] = [];

    // Vérifier les fichiers manquants
    const visionPaths = new Set(visionFiles.map(f => f.path));
    const currentPaths = new Set(currentFiles.map(f => f.path));

    // Fichiers manquants dans Current
    for (const visionFile of visionFiles) {
      if (!currentPaths.has(visionFile.path)) {
        inconsistencies.push({
          type: 'missing',
          file: visionFile.path,
          description: `Fichier Vision manquant dans Current: ${visionFile.path}`,
          severity: 'medium',
          suggestion: `Créer le fichier correspondant dans docs-current/`
        });
      }
    }

    // Vérifier les liens brisés
    for (const file of [...visionFiles, ...currentFiles]) {
      const brokenLinks = this.findBrokenLinks(file.content, file.path);
      inconsistencies.push(...brokenLinks);
    }

    // Vérifier les badges de statut
    for (const file of [...visionFiles, ...currentFiles]) {
      const badgeIssues = this.checkStatusBadges(file);
      inconsistencies.push(...badgeIssues);
    }

    return inconsistencies;
  }

  /**
   * Trouve les liens brisés dans un fichier
   */
  private findBrokenLinks(content: string, filePath: string): Inconsistency[] {
    const inconsistencies: Inconsistency[] = [];
    const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
    let match;

    while ((match = linkRegex.exec(content)) !== null) {
      const [, text, link] = match;
      
      // Vérifier les liens internes
      if (link.startsWith('./') || link.startsWith('../')) {
        const resolvedPath = this.resolveLink(link, filePath);
        if (!existsSync(resolvedPath)) {
          inconsistencies.push({
            type: 'broken-link',
            file: filePath,
            description: `Lien brisé: ${link} (vers ${text})`,
            severity: 'medium',
            suggestion: `Vérifier le chemin: ${resolvedPath}`
          });
        }
      }
    }

    return inconsistencies;
  }

  /**
   * Résout un lien relatif
   */
  private resolveLink(link: string, fromFile: string): string {
    const baseDir = fromFile.includes('docs-vision') ? this.visionPath : this.currentPath;
    const fromDir = join(baseDir, fromFile.split('/').slice(0, -1).join('/'));
    return join(fromDir, link);
  }

  /**
   * Vérifie les badges de statut
   */
  private checkStatusBadges(file: DocFile): Inconsistency[] {
    const inconsistencies: Inconsistency[] = [];
    const content = file.content;

    // Vérifier la présence de badges
    if (!content.includes(':::note') && !content.includes(':::tip') && !content.includes(':::warning')) {
      inconsistencies.push({
        type: 'mismatch',
        file: file.path,
        description: 'Fichier sans badge de statut',
        severity: 'low',
        suggestion: 'Ajouter un badge de statut (NOTE, TIP, WARNING)'
      });
    }

    // Vérifier la cohérence des badges
    if (file.path.includes('docs-vision') && !content.includes('CIBLE')) {
      inconsistencies.push({
        type: 'mismatch',
        file: file.path,
        description: 'Fichier Vision sans badge CIBLE',
        severity: 'medium',
        suggestion: 'Ajouter le badge CIBLE pour les fichiers Vision'
      });
    }

    if (file.path.includes('docs-current') && !content.includes('ÉTAT ACTUEL')) {
      inconsistencies.push({
        type: 'mismatch',
        file: file.path,
        description: 'Fichier Current sans badge ÉTAT ACTUEL',
        severity: 'medium',
        suggestion: 'Ajouter le badge ÉTAT ACTUEL pour les fichiers Current'
      });
    }

    return inconsistencies;
  }

  /**
   * Génère des recommandations
   */
  private generateRecommendations(inconsistencies: Inconsistency[]): string[] {
    const recommendations: string[] = [];

    const criticalIssues = inconsistencies.filter(i => i.severity === 'critical');
    const highIssues = inconsistencies.filter(i => i.severity === 'high');
    const mediumIssues = inconsistencies.filter(i => i.severity === 'medium');

    if (criticalIssues.length > 0) {
      recommendations.push(`🚨 ${criticalIssues.length} problème(s) critique(s) à résoudre immédiatement`);
    }

    if (highIssues.length > 0) {
      recommendations.push(`⚠️  ${highIssues.length} problème(s) de haute priorité à traiter cette semaine`);
    }

    if (mediumIssues.length > 0) {
      recommendations.push(`📝 ${mediumIssues.length} problème(s) de priorité moyenne à traiter prochainement`);
    }

    // Recommandations spécifiques
    const missingFiles = inconsistencies.filter(i => i.type === 'missing');
    if (missingFiles.length > 0) {
      recommendations.push(`📄 ${missingFiles.length} fichier(s) manquant(s) dans Current - synchroniser avec Vision`);
    }

    const brokenLinks = inconsistencies.filter(i => i.type === 'broken-link');
    if (brokenLinks.length > 0) {
      recommendations.push(`🔗 ${brokenLinks.length} lien(s) brisé(s) à corriger`);
    }

    const badgeIssues = inconsistencies.filter(i => i.type === 'mismatch');
    if (badgeIssues.length > 0) {
      recommendations.push(`🏷️  ${badgeIssues.length} problème(s) de badges à corriger`);
    }

    return recommendations;
  }

  /**
   * Génère un rapport de synchronisation
   */
  private generateReport(visionFiles: DocFile[], currentFiles: DocFile[], inconsistencies: Inconsistency[]): SyncReport {
    return {
      timestamp: new Date(),
      visionFiles,
      currentFiles,
      inconsistencies,
      recommendations: this.generateRecommendations(inconsistencies)
    };
  }

  /**
   * Sauvegarde le rapport
   */
  private saveReport(report: SyncReport): void {
    const timestamp = report.timestamp.toISOString().split('T')[0];
    const reportFile = join(this.reportPath, `doc-sync-${timestamp}.md`);

    const reportContent = this.formatReport(report);
    writeFileSync(reportFile, reportContent, 'utf-8');
    console.log(`📊 Rapport sauvegardé: ${reportFile}`);
  }

  /**
   * Formate le rapport en Markdown
   */
  private formatReport(report: SyncReport): string {
    const { timestamp, visionFiles, currentFiles, inconsistencies, recommendations } = report;

    let content = `# 📚 Rapport de Synchronisation Documentation\n\n`;
    content += `**Date** : ${timestamp.toLocaleDateString('fr-FR')}\n`;
    content += `**Heure** : ${timestamp.toLocaleTimeString('fr-FR')}\n\n`;

    // Statistiques
    content += `## 📊 Statistiques\n\n`;
    content += `- **Fichiers Vision** : ${visionFiles.length}\n`;
    content += `- **Fichiers Current** : ${currentFiles.length}\n`;
    content += `- **Incohérences** : ${inconsistencies.length}\n`;
    content += `- **Recommandations** : ${recommendations.length}\n\n`;

    // Recommandations
    if (recommendations.length > 0) {
      content += `## 🎯 Recommandations\n\n`;
      recommendations.forEach(rec => {
        content += `- ${rec}\n`;
      });
      content += `\n`;
    }

    // Incohérences par sévérité
    const critical = inconsistencies.filter(i => i.severity === 'critical');
    const high = inconsistencies.filter(i => i.severity === 'high');
    const medium = inconsistencies.filter(i => i.severity === 'medium');
    const low = inconsistencies.filter(i => i.severity === 'low');

    if (critical.length > 0) {
      content += `## 🚨 Problèmes Critiques\n\n`;
      critical.forEach(issue => {
        content += `### ${issue.file}\n`;
        content += `- **Type** : ${issue.type}\n`;
        content += `- **Description** : ${issue.description}\n`;
        content += `- **Suggestion** : ${issue.suggestion}\n\n`;
      });
    }

    if (high.length > 0) {
      content += `## ⚠️ Problèmes de Haute Priorité\n\n`;
      high.forEach(issue => {
        content += `### ${issue.file}\n`;
        content += `- **Type** : ${issue.type}\n`;
        content += `- **Description** : ${issue.description}\n`;
        content += `- **Suggestion** : ${issue.suggestion}\n\n`;
      });
    }

    if (medium.length > 0) {
      content += `## 📝 Problèmes de Priorité Moyenne\n\n`;
      medium.forEach(issue => {
        content += `### ${issue.file}\n`;
        content += `- **Type** : ${issue.type}\n`;
        content += `- **Description** : ${issue.description}\n`;
        content += `- **Suggestion** : ${issue.suggestion}\n\n`;
      });
    }

    if (low.length > 0) {
      content += `## ℹ️ Problèmes de Priorité Faible\n\n`;
      low.forEach(issue => {
        content += `### ${issue.file}\n`;
        content += `- **Type** : ${issue.type}\n`;
        content += `- **Description** : ${issue.description}\n`;
        content += `- **Suggestion** : ${issue.suggestion}\n\n`;
      });
    }

    // Fichiers récents
    content += `## 📄 Fichiers Récents\n\n`;
    const recentFiles = [...visionFiles, ...currentFiles]
      .sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime())
      .slice(0, 10);

    recentFiles.forEach(file => {
      const type = file.path.includes('docs-vision') ? 'Vision' : 'Current';
      content += `- **${type}** : ${file.path} (${file.lastModified.toLocaleDateString('fr-FR')})\n`;
    });

    content += `\n---\n\n`;
    content += `*Rapport généré automatiquement par DocSyncManager*\n`;

    return content;
  }

  /**
   * Exécute la synchronisation complète
   */
  public async sync(): Promise<void> {
    console.log('🔄 Démarrage de la synchronisation de documentation...');

    try {
      // Scanner les répertoires
      console.log('📁 Scan des fichiers Vision...');
      const visionFiles = this.scanDirectory(this.visionPath);

      console.log('📁 Scan des fichiers Current...');
      const currentFiles = this.scanDirectory(this.currentPath);

      // Vérifier la cohérence
      console.log('🔍 Vérification de la cohérence...');
      const inconsistencies = this.checkConsistency(visionFiles, currentFiles);

      // Générer le rapport
      console.log('📊 Génération du rapport...');
      const report = this.generateReport(visionFiles, currentFiles, inconsistencies);

      // Sauvegarder le rapport
      this.saveReport(report);

      // Afficher le résumé
      console.log('\n📋 Résumé de la synchronisation:');
      console.log(`  - Fichiers Vision: ${visionFiles.length}`);
      console.log(`  - Fichiers Current: ${currentFiles.length}`);
      console.log(`  - Incohérences: ${inconsistencies.length}`);
      console.log(`  - Recommandations: ${report.recommendations.length}`);

      if (inconsistencies.length > 0) {
        console.log('\n⚠️  Incohérences détectées:');
        inconsistencies.forEach(issue => {
          const emoji = issue.severity === 'critical' ? '🚨' : 
                       issue.severity === 'high' ? '⚠️' : 
                       issue.severity === 'medium' ? '📝' : 'ℹ️';
          console.log(`  ${emoji} ${issue.file}: ${issue.description}`);
        });
      } else {
        console.log('\n✅ Aucune incohérence détectée!');
      }

    } catch (error) {
      console.error('❌ Erreur lors de la synchronisation:', error);
      process.exit(1);
    }
  }
}

// Exécution du script
if (require.main === module) {
  const syncManager = new DocSyncManager();
  syncManager.sync().catch(console.error);
}

export default DocSyncManager;
