import fs from 'fs';
import path from 'path';

function walk(dir) {
  let results = [];
  const entries = fs.readdirSync(dir, { withFileTypes: true });
  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name);
    if (entry.isDirectory()) {
      results = results.concat(walk(fullPath));
    } else if (/\.(tsx|ts|jsx|js|css|scss)$/.test(entry.name)) {
      results.push(fullPath);
    }
  }
  return results;
}

const files = walk('src');
console.log(`Found ${files.length} source files under src/ to inspect.`);

const findings = [];

// Patterns:
// 1. Any shadow class except shadow-none, shadow-[none], shadow-[0px]
const shadowPattern = /\bshadow(-[a-zA-Z0-9_/\[\]#.-]+)?\b/g;
// 2. Any rounded class except rounded-none, rounded-[0px], rounded-0, rounded-[0]
const roundedPattern = /\brounded(-[a-zA-Z0-9_/\[\]#.-]+)?\b/g;
// 3. bg-gradient-*
const bgGradientPattern = /\bbg-gradient(-[a-zA-Z0-9_-]+)?\b/g;
// 4. from-* gradient stop
const fromPattern = /\bfrom-[a-zA-Z0-9_/\[\]#.-]+\b/g;
// 5. via-* gradient stop
const viaPattern = /\bvia-[a-zA-Z0-9_/\[\]#.-]+\b/g;
// 6. to-* gradient stop (e.g., to-black, to-white, to-slate-900, to-[#...])
const toPattern = /\bto-(black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|transparent|current|\[#[a-fA-F0-9]+\])(-[0-9]+)?(\/[0-9]+)?\b/g;
// 7. CSS box-shadow
const cssBoxShadowPattern = /box-shadow\s*:\s*([^;]+)/gi;
// 8. CSS border-radius
const cssBorderRadiusPattern = /border-radius\s*:\s*([^;]+)/gi;

for (const filePath of files) {
  const content = fs.readFileSync(filePath, 'utf8');
  const lines = content.split('\n');

  lines.forEach((line, index) => {
    const lineNum = index + 1;
    const trimmed = line.trim();

    // Check CSS properties
    let match;
    while ((match = cssBoxShadowPattern.exec(line)) !== null) {
      const val = match[1].trim();
      if (val !== 'none' && val !== '0' && val !== '0px') {
        findings.push({
          type: 'CSS_BOX_SHADOW',
          file: filePath,
          line: lineNum,
          matched: match[0],
          raw: trimmed,
        });
      }
    }

    while ((match = cssBorderRadiusPattern.exec(line)) !== null) {
      const val = match[1].trim();
      if (val !== '0' && val !== '0px' && val !== '0 0 0 0') {
        findings.push({
          type: 'CSS_BORDER_RADIUS',
          file: filePath,
          line: lineNum,
          matched: match[0],
          raw: trimmed,
        });
      }
    }

    // Check Tailwind / Class matches
    // Look for string literals or className definitions
    // To be thorough, check any occurrence in the file
    let rMatch;
    while ((rMatch = roundedPattern.exec(line)) !== null) {
      const cls = rMatch[0];
      if (
        cls !== 'rounded-none' &&
        cls !== 'rounded-[0px]' &&
        cls !== 'rounded-0' &&
        cls !== 'rounded-[0]'
      ) {
        // Exclude JS identifier words like roundedTotal, Math.round, etc. if not a class token
        // A class token is typically in quotes, backticks, or preceded/followed by whitespace/quotes
        const before = line[rMatch.index - 1] || ' ';
        const after = line[rMatch.index + cls.length] || ' ';
        if (
          /['"`\s=:({[,>]/.test(before) &&
          /['"`\s=:)}],<]/.test(after)
        ) {
          findings.push({
            type: 'FORBIDDEN_ROUNDED_CLASS',
            file: filePath,
            line: lineNum,
            matched: cls,
            raw: trimmed,
          });
        }
      }
    }

    let sMatch;
    while ((sMatch = shadowPattern.exec(line)) !== null) {
      const cls = sMatch[0];
      if (
        cls !== 'shadow-none' &&
        cls !== 'shadow-[none]' &&
        cls !== 'shadow-[0px]'
      ) {
        const before = line[sMatch.index - 1] || ' ';
        const after = line[sMatch.index + cls.length] || ' ';
        if (
          /['"`\s=:({[,>]/.test(before) &&
          /['"`\s=:)}],<]/.test(after)
        ) {
          findings.push({
            type: 'FORBIDDEN_SHADOW_CLASS',
            file: filePath,
            line: lineNum,
            matched: cls,
            raw: trimmed,
          });
        }
      }
    }

    let gMatch;
    while ((gMatch = bgGradientPattern.exec(line)) !== null) {
      findings.push({
        type: 'FORBIDDEN_BG_GRADIENT_CLASS',
        file: filePath,
        line: lineNum,
        matched: gMatch[0],
        raw: trimmed,
      });
    }

    let fMatch;
    while ((fMatch = fromPattern.exec(line)) !== null) {
      // Exclude JS imports: import { ... } from '...'
      if (!/\bimport\b|\bexport\b/.test(line)) {
        findings.push({
          type: 'FORBIDDEN_FROM_GRADIENT_CLASS',
          file: filePath,
          line: lineNum,
          matched: fMatch[0],
          raw: trimmed,
        });
      }
    }

    let vMatch;
    while ((vMatch = viaPattern.exec(line)) !== null) {
      findings.push({
        type: 'FORBIDDEN_VIA_GRADIENT_CLASS',
        file: filePath,
        line: lineNum,
        matched: vMatch[0],
        raw: trimmed,
      });
    }

    let tMatch;
    while ((tMatch = toPattern.exec(line)) !== null) {
      // Check if it's inside className or class attribute or tailwind string
      findings.push({
        type: 'FORBIDDEN_TO_GRADIENT_CLASS',
        file: filePath,
        line: lineNum,
        matched: tMatch[0],
        raw: trimmed,
      });
    }
  });
}

console.log('=== ADVERSARIAL SCAN REPORT ===');
console.log(`Scanned files: ${files.length}`);
console.log(`Total violations detected: ${findings.length}`);
if (findings.length > 0) {
  console.log('\n--- VIOLATIONS LIST ---');
  findings.forEach((f, idx) => {
    console.log(`${idx + 1}. [${f.type}] ${f.file}:${f.line}`);
    console.log(`   Token: "${f.matched}"`);
    console.log(`   Line: ${f.raw}`);
  });
  process.exit(1);
} else {
  console.log('CLEAN: No forbidden rounded, shadow, gradient, or box-shadow tokens found in src/');
  process.exit(0);
}
