#!/usr/bin/env node

import * as fs from 'fs';
import * as path from 'path';
import { glob } from 'glob';

interface DocFile {
  originalPath: string;
  relativePath: string;
  content: string;
  frontmatter: Record<string, any>;
  track: 'current' | 'vision';
  domain: string;
  slug: string;
  title: string;
  images: string[];
}

interface PathMapping {
  [originalPath: string]: string;
}

interface MigrationReport {
  totalFiles: number;
  migratedFiles: number;
  currentFiles: number;
  visionFiles: number;
  domainDistribution: Record<string, number>;
  unclassifiedFiles: string[];
  brokenLinks: string[];
  pathMapping: PathMapping;
}

class DocMigrator {
  private projectRoot: string;
  private docsRoot: string;
  private currentRoot: string;
  private visionRoot: string;
  private assetsRoot: string;
  private report: MigrationReport;
  private pathMapping: PathMapping = {};

  constructor(projectRoot: string) {
    this.projectRoot = projectRoot;
    this.docsRoot = path.join(projectRoot, 'veza-docs');
    this.currentRoot = path.join(this.docsRoot, 'current');
    this.visionRoot = path.join(this.docsRoot, 'vision');
    this.assetsRoot = path.join(this.docsRoot, 'current', 'assets');
    
    this.report = {
      totalFiles: 0,
      migratedFiles: 0,
      currentFiles: 0,
      visionFiles: 0,
      domainDistribution: {},
      unclassifiedFiles: [],
      brokenLinks: [],
      pathMapping: {}
    };
  }

  async discoverDocs(): Promise<DocFile[]> {
    console.log('🔍 Découverte des fichiers de documentation...');
    
    const patterns = [
      '**/*.md',
      '**/*.mdx'
    ];
    
    const excludePatterns = [
      'node_modules/**',
      'target/**',
      'dist/**',
      'build/**',
      'vendor/**',
      '.git/**',
      'veza-docs/**',
      'veza-docs-backup/**',
      '*.log',
      '*.pid',
      '**/node_modules/**',
      '**/target/**',
      '**/dist/**',
      '**/build/**'
    ];

    const allFiles: string[] = [];
    
    for (const pattern of patterns) {
      const files = await glob(pattern, {
        cwd: this.projectRoot,
        ignore: excludePatterns
      });
      allFiles.push(...files);
    }

    console.log(`📄 ${allFiles.length} fichiers de documentation trouvés`);

    const docFiles: DocFile[] = [];
    
    for (const file of allFiles) {
      const fullPath = path.join(this.projectRoot, file);
      const content = fs.readFileSync(fullPath, 'utf-8');
      
      const docFile = this.parseDocFile(file, content);
      if (docFile) {
        docFiles.push(docFile);
      }
    }

    return docFiles;
  }

  private parseDocFile(relativePath: string, content: string): DocFile | null {
    const frontmatter = this.extractFrontmatter(content);
    const track = this.determineTrack(relativePath, content, frontmatter);
    const domain = this.determineDomain(relativePath, content, frontmatter);
    const slug = this.generateSlug(relativePath);
    const title = this.extractTitle(content, relativePath);
    const images = this.extractImages(content);

    return {
      originalPath: path.join(this.projectRoot, relativePath),
      relativePath,
      content,
      frontmatter,
      track,
      domain,
      slug,
      title,
      images
    };
  }

  private extractFrontmatter(content: string): Record<string, any> {
    const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/;
    const match = content.match(frontmatterRegex);
    
    if (!match) return {};

    const frontmatterText = match[1];
    const frontmatter: Record<string, any> = {};
    
    frontmatterText.split('\n').forEach(line => {
      const [key, ...valueParts] = line.split(':');
      if (key && valueParts.length > 0) {
        const value = valueParts.join(':').trim();
        frontmatter[key.trim()] = value.replace(/^["']|["']$/g, '');
      }
    });

    return frontmatter;
  }

  private determineTrack(relativePath: string, content: string, frontmatter: Record<string, any>): 'current' | 'vision' {
    // Priorité au frontmatter
    if (frontmatter.track === 'vision' || frontmatter.track === 'current') {
      return frontmatter.track;
    }

    // Mots-clés dans le chemin
    const visionKeywords = ['vision', 'target', 'future', 'roadmap', 'spec', 'cible', 'but visé'];
    const pathLower = relativePath.toLowerCase();
    
    if (visionKeywords.some(keyword => pathLower.includes(keyword))) {
      return 'vision';
    }

    // Mots-clés dans le contenu
    const contentLower = content.toLowerCase();
    if (visionKeywords.some(keyword => contentLower.includes(keyword))) {
      return 'vision';
    }

    // Par défaut, c'est l'état actuel
    return 'current';
  }

  private determineDomain(relativePath: string, content: string, frontmatter: Record<string, any>): string {
    // Priorité au frontmatter
    if (frontmatter.domain) {
      return frontmatter.domain;
    }

    const pathLower = relativePath.toLowerCase();
    const contentLower = content.toLowerCase();

    // Backend
    if (pathLower.includes('backend') || pathLower.includes('api') || pathLower.includes('go') || 
        contentLower.includes('backend') || contentLower.includes('api') || contentLower.includes('golang')) {
      return 'backend';
    }

    // Frontend
    if (pathLower.includes('frontend') || pathLower.includes('react') || pathLower.includes('ui') || 
        pathLower.includes('vite') || contentLower.includes('frontend') || contentLower.includes('react')) {
      return 'frontend';
    }

    // Rust
    if (pathLower.includes('rust') || pathLower.includes('chat') || pathLower.includes('stream') || 
        contentLower.includes('rust') || contentLower.includes('cargo')) {
      return 'rust';
    }

    // Infrastructure
    if (pathLower.includes('infra') || pathLower.includes('docker') || pathLower.includes('compose') || 
        pathLower.includes('incus') || pathLower.includes('haproxy') || pathLower.includes('redis') || 
        pathLower.includes('postgres') || contentLower.includes('infrastructure') || contentLower.includes('deployment')) {
      return 'infra';
    }

    // Security
    if (pathLower.includes('security') || pathLower.includes('auth') || pathLower.includes('waf') || 
        pathLower.includes('coraza') || contentLower.includes('security') || contentLower.includes('auth')) {
      return 'security';
    }

    // Operations
    if (pathLower.includes('ops') || pathLower.includes('ci') || pathLower.includes('cd') || 
        pathLower.includes('monitoring') || pathLower.includes('logs') || pathLower.includes('zfs') || 
        contentLower.includes('operations') || contentLower.includes('monitoring')) {
      return 'ops';
    }

    // Product
    if (pathLower.includes('product') || pathLower.includes('ux') || pathLower.includes('personas') || 
        contentLower.includes('product') || contentLower.includes('ux') || contentLower.includes('roadmap')) {
      return 'product';
    }

    // Legal
    if (pathLower.includes('legal') || pathLower.includes('cgu') || pathLower.includes('mentions') || 
        contentLower.includes('legal') || contentLower.includes('cgu')) {
      return 'legal';
    }

    return 'misc';
  }

  private generateSlug(relativePath: string): string {
    const baseName = path.basename(relativePath, path.extname(relativePath));
    return baseName
      .toLowerCase()
      .replace(/[^a-z0-9-]/g, '-')
      .replace(/-+/g, '-')
      .replace(/^-|-$/g, '');
  }

  private extractTitle(content: string, relativePath: string): string {
    // Chercher un titre H1
    const h1Match = content.match(/^#\s+(.+)$/m);
    if (h1Match) {
      return h1Match[1].trim();
    }

    // Utiliser le nom du fichier
    const baseName = path.basename(relativePath, path.extname(relativePath));
    return baseName
      .replace(/[-_]/g, ' ')
      .replace(/\b\w/g, l => l.toUpperCase());
  }

  private extractImages(content: string): string[] {
    const imageRegex = /!\[.*?\]\((.*?)\)/g;
    const images: string[] = [];
    let match;

    while ((match = imageRegex.exec(content)) !== null) {
      images.push(match[1]);
    }

    return images;
  }

  async migrateDocs(docFiles: DocFile[]): Promise<void> {
    console.log('📦 Migration des documents...');

    for (const docFile of docFiles) {
      await this.migrateDocFile(docFile);
    }

    // Copier les assets
    await this.copyAssets(docFiles);
  }

  private async migrateDocFile(docFile: DocFile): Promise<void> {
    const targetDir = docFile.track === 'current' ? this.currentRoot : this.visionRoot;
    const domainDir = path.join(targetDir, 'domains', docFile.domain);
    
    // Créer le répertoire si nécessaire
    if (!fs.existsSync(domainDir)) {
      fs.mkdirSync(domainDir, { recursive: true });
    }

    const targetPath = path.join(domainDir, `${docFile.slug}.md`);
    
    // Préparer le contenu avec frontmatter
    const frontmatter = {
      id: docFile.slug,
      title: docFile.title,
      sidebar_label: docFile.title,
      ...docFile.frontmatter
    };

    const frontmatterText = Object.entries(frontmatter)
      .map(([key, value]) => `${key}: ${value}`)
      .join('\n');

    const content = `---
${frontmatterText}
---

${docFile.content}`;

    // Ajouter le badge de piste
    const badge = docFile.track === 'current' 
      ? '> NOTE: Cette page reflète l\'ÉTAT ACTUEL.'
      : '> NOTE: Cette page décrit la CIBLE (but visé).';

    const finalContent = content.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, `---\n${frontmatterText}\n---\n\n${badge}\n\n`);

    fs.writeFileSync(targetPath, finalContent);

    // Mettre à jour le mapping
    this.pathMapping[docFile.relativePath] = `/${docFile.track}/domains/${docFile.domain}/${docFile.slug}`;

    // Mettre à jour les statistiques
    this.report.migratedFiles++;
    if (docFile.track === 'current') {
      this.report.currentFiles++;
    } else {
      this.report.visionFiles++;
    }

    if (!this.report.domainDistribution[docFile.domain]) {
      this.report.domainDistribution[docFile.domain] = 0;
    }
    this.report.domainDistribution[docFile.domain]++;

    console.log(`✅ Migré: ${docFile.relativePath} → ${docFile.track}/domains/${docFile.domain}/${docFile.slug}.md`);
  }

  private async copyAssets(docFiles: DocFile[]): Promise<void> {
    console.log('🖼️  Copie des assets...');

    const allImages = new Set<string>();
    docFiles.forEach(doc => {
      doc.images.forEach(img => allImages.add(img));
    });

    for (const imagePath of allImages) {
      if (imagePath.startsWith('http')) continue; // Ignorer les URLs

      const sourcePath = path.resolve(this.projectRoot, imagePath);
      if (fs.existsSync(sourcePath)) {
        const fileName = path.basename(imagePath);
        const targetPath = path.join(this.assetsRoot, fileName);
        
        fs.copyFileSync(sourcePath, targetPath);
        console.log(`📷 Copié: ${imagePath} → assets/${fileName}`);
      } else {
        this.report.brokenLinks.push(imagePath);
        console.log(`❌ Image manquante: ${imagePath}`);
      }
    }
  }

  async generateReport(): Promise<void> {
    console.log('📊 Génération du rapport de migration...');

    this.report.totalFiles = this.report.migratedFiles;
    this.report.pathMapping = this.pathMapping;

    const reportPath = path.join(this.docsRoot, '_reports', 'migration_report.md');
    const pathMapPath = path.join(this.docsRoot, '_reports', 'path_map.json');

    // Générer le rapport Markdown
    const reportContent = `# Rapport de Migration de Documentation

## Résumé
- **Total des fichiers traités**: ${this.report.totalFiles}
- **Fichiers migrés**: ${this.report.migratedFiles}
- **État actuel**: ${this.report.currentFiles}
- **Vision**: ${this.report.visionFiles}

## Distribution par domaine
${Object.entries(this.report.domainDistribution)
  .map(([domain, count]) => `- **${domain}**: ${count} fichiers`)
  .join('\n')}

## Fichiers non classés
${this.report.unclassifiedFiles.length > 0 
  ? this.report.unclassifiedFiles.map(file => `- ${file}`).join('\n')
  : 'Aucun'}

## Liens brisés
${this.report.brokenLinks.length > 0 
  ? this.report.brokenLinks.map(link => `- ${link}`).join('\n')
  : 'Aucun'}

## Mapping des chemins
Le mapping complet des anciens vers les nouveaux chemins est disponible dans \`path_map.json\`.
`;

    fs.writeFileSync(reportPath, reportContent);

    // Générer le mapping JSON
    fs.writeFileSync(pathMapPath, JSON.stringify(this.pathMapping, null, 2));

    console.log(`📋 Rapport généré: ${reportPath}`);
    console.log(`🗺️  Mapping généré: ${pathMapPath}`);
  }

  async run(): Promise<void> {
    console.log('🚀 Démarrage de la migration de documentation...');
    
    try {
      const docFiles = await this.discoverDocs();
      await this.migrateDocs(docFiles);
      await this.generateReport();
      
      console.log('✅ Migration terminée avec succès!');
    } catch (error) {
      console.error('❌ Erreur lors de la migration:', error);
      process.exit(1);
    }
  }
}

// Exécution du script
if (require.main === module) {
  const projectRoot = process.argv[2] || path.join(__dirname, '..', '..');
  const migrator = new DocMigrator(projectRoot);
  migrator.run();
}

export { DocMigrator };
