// scripts/check-hardcoded-strings.js
const fs = require('fs');
const path = require('path');
const babel = require('@babel/parser');
const traverse = require('@babel/traverse').default;

// Patterns pour les classes Tailwind
const TAILWIND_PATTERNS = [
  // Layout
  /^(container|flex|grid|block|inline|hidden)/,
  // Spacing
  /^(m|p|mt|mb|ml|mr|mx|my|pt|pb|pl|pr|px|py)-[0-9]+/,
  // Sizing
  /^(w|h|min-w|min-h|max-w|max-h)-[0-9]+/,
  // Typography
  /^(text|font|leading)-/,
  // Backgrounds
  /^bg-/,
  // Borders
  /^(border|rounded|divide)-/,
  // Effects
  /^(shadow|opacity|transition)-/,
  // Interactivity
  /^(cursor|pointer-events|select|resize)-/,
  // Layout
  /^(z|top|right|bottom|left|float|clear)-/,
  // Flexbox & Grid
  /^(justify|items|content|self|place|gap)-/,
  // États
  /^(hover|focus|active|disabled|group|dark):/,
  // Couleurs
  /-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-[0-9]+$/,
];

// Nouveaux patterns pour ignorer les logs et imports
const CODE_PATTERNS = [
  // Console et debug avec contenu
  /console\.(log|error|warn|info|debug)\(['"].*['"]/,
  /^console\.(log|error|warn|info|debug)\(/,
  /^debugger/,

  // Imports et requires avec leurs chaînes
  /^import\s+.*\s+from\s+['"].*['"]/,
  /^import\s+['"].*['"]/,
  /^require\(['"].*['"]\)/,
  /^from\s+['"].*['"]/,
  /^@/,

  // Autres cas courants
  /^process\.env\./,
  /^module\.exports/,
  /^export\s+/,
];

function isHardcodedString(str) {
  // Ignorer les chaînes vides ou trop courtes
  if (!str || str.length <= 1) return false;

  // Vérifier si la chaîne fait partie d'un console.log ou d'un import
  const context = str.trim();
  if (CODE_PATTERNS.some((pattern) => pattern.test(context))) {
    return false;
  }

  // Vérifier si c'est une chaîne dans un console.log
  if (context.includes('console.log(')) {
    return false;
  }

  // Vérifier si c'est une chaîne dans un import
  if (context.includes("from '") || context.includes('from "')) {
    return false;
  }

  // Vérifier si c'est une classe Tailwind
  const classes = str.split(' ');
  if (
    classes.some((cls) =>
      TAILWIND_PATTERNS.some((pattern) => pattern.test(cls))
    )
  ) {
    return false;
  }

  // Autres patterns à ignorer
  const IGNORE_PATTERNS = [
    /^[A-Z][A-Za-z]+$/, // Noms de composants
    /^@/, // Imports
    /^[./]/, // Chemins de fichiers
    /^[0-9]+$/, // Nombres
    /^style=/, // Props style
    /^id=/, // Props id
    /^data-/, // Data attributes
    /^aria-/, // Aria attributes
    /^role=/, // Role attributes
    /^className=/, // className attributes
  ];

  return !IGNORE_PATTERNS.some((pattern) => pattern.test(str));
}

async function scanFile(filePath) {
  const content = fs.readFileSync(filePath, 'utf-8');
  const hardcodedStrings = new Map(); // Utiliser Map pour stocker string -> ligne

  try {
    const ast = babel.parse(content, {
      sourceType: 'module',
      plugins: ['jsx', 'typescript'],
      locations: true, // Active le tracking des positions
    });

    traverse(ast, {
      StringLiteral(path) {
        const value = path.node.value;
        const line = path.node.loc.start.line;
        if (isHardcodedString(value)) {
          hardcodedStrings.set(value, line);
        }
      },
      JSXText(path) {
        const value = path.node.value.trim();
        const line = path.node.loc.start.line;
        if (isHardcodedString(value)) {
          hardcodedStrings.set(value, line);
        }
      },
    });
  } catch (error) {
    console.error(`Erreur dans le fichier ${filePath}:`, error);
  }

  return Array.from(hardcodedStrings.entries());
}

async function scanDirectory(dir) {
  const results = {};
  const files = fs.readdirSync(dir);

  for (const file of files) {
    const filePath = path.join(dir, file);
    const stat = fs.statSync(filePath);

    if (
      stat.isDirectory() &&
      !file.startsWith('.') &&
      file !== 'node_modules'
    ) {
      Object.assign(results, await scanDirectory(filePath));
    } else if (
      stat.isFile() &&
      (file.endsWith('.js') || file.endsWith('.jsx') || file.endsWith('.tsx'))
    ) {
      const strings = await scanFile(filePath);
      if (strings.length > 0) {
        results[filePath] = strings;
      }
    }
  }

  return results;
}

async function logStringsToFile(results) {
  const outputPath = path.join(process.cwd(), 'hardcoded-strings-report.md');
  let content = '# Rapport des chaînes en dur\n\n';
  let totalStrings = 0;

  for (const [file, strings] of Object.entries(results)) {
    if (strings.length > 0) {
      const relativePath = path.relative(process.cwd(), file);
      content += `\n## ${relativePath}\n\n`;

      strings.forEach(([str, line]) => {
        totalStrings++;
        content += `- Ligne ${line}: \`${str}\`\n`;
        content += `  → [Voir dans le code](${relativePath}:${line}:1)\n\n`;
      });
    }
  }

  content += `\n## Résumé\n`;
  content += `- Total des chaînes trouvées: ${totalStrings}\n`;
  content += `- Date du scan: ${new Date().toLocaleString('fr-FR')}\n`;

  fs.writeFileSync(outputPath, content, 'utf8');
  console.log(`\nRapport généré: ${outputPath}`);
}

// Modifier la fonction main existante
async function main() {
  const rootDir = process.cwd();
  const results = await scanDirectory(path.join(rootDir, 'src'));
  await logStringsToFile(results);
}

main().catch(console.error);
