#!/usr/bin/env node

const fs = require('node:fs');
const path = require('node:path');
const { mergeIntoConfig, scanUiSelectors } = require('./lib/ui-scanner');

function main(argv) {
  const args = parseArgs(argv);
  const configPath = path.resolve(args.configPath ?? path.join(process.cwd(), 'bdd-ui.config.json'));
  const configExists = fs.existsSync(configPath);
  const existingConfig = configExists
    ? JSON.parse(fs.readFileSync(configPath, 'utf8'))
    : {};
  const scannerConfig = existingConfig.uiScanner ?? {};

  if (!args.uiPath) {
    throw new Error('Missing required --ui-path argument.');
  }

  const scanResult = scanUiSelectors({
    uiPath: args.uiPath,
    language: scannerConfig.language ?? args.language ?? 'react-tsx',
    include: scannerConfig.include,
    exclude: scannerConfig.exclude,
    selectorOutput: scannerConfig.selectorOutput
  });

  const nextConfig = mergeIntoConfig(existingConfig, scanResult);

  if (args.write) {
    if (configExists) {
      const backupPath = buildBackupPath(configPath);
      fs.copyFileSync(configPath, backupPath);
      console.log(`Backed up existing config to ${backupPath}`);
    }
    if (scanResult.selectorFiles && scannerConfig.selectorOutput?.generatedDir) {
      writeSelectorFiles(resolveGeneratedDirRoot(configPath, scannerConfig.selectorOutput.generatedDir), scanResult.selectorFiles);
    }
    fs.writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, 'utf8');
    console.log(`Updated ${configPath}`);
  } else {
    console.log(JSON.stringify(nextConfig, null, 2));
  }

  console.log(
    [
      `Scanned ${scanResult.scannedFileCount} files.`,
      `Found ${Object.keys(scanResult.selectors).length} static selectors.`,
      `Found ${Object.keys(scanResult.grids).length} grid selectors.`,
      `Skipped ${scanResult.dynamic.length} dynamic selector expressions.`
    ].join(' ')
  );

  if (scanResult.dynamic.length > 0) {
    console.log('Dynamic selector expressions that were not added:');
    for (const item of scanResult.dynamic.slice(0, 20)) {
      console.log(`- ${item.filePath}: ${item.expression}`);
    }
    if (scanResult.dynamic.length > 20) {
      console.log(`- ... and ${scanResult.dynamic.length - 20} more`);
    }
  }
}

function parseArgs(argv) {
  const args = {};

  for (let index = 0; index < argv.length; index += 1) {
    const token = argv[index];
    if (token === '--write') {
      args.write = true;
      continue;
    }
    if (token === '--ui-path') {
      args.uiPath = argv[index + 1];
      index += 1;
      continue;
    }
    if (token === '--config-path') {
      args.configPath = argv[index + 1];
      index += 1;
      continue;
    }
    if (token === '--language') {
      args.language = argv[index + 1];
      index += 1;
      continue;
    }
  }

  return args;
}

function buildBackupPath(configPath) {
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const extension = path.extname(configPath);
  const baseName = extension ? configPath.slice(0, -extension.length) : configPath;
  return `${baseName}.${timestamp}.bak${extension || ''}`;
}

function writeSelectorFiles(outputRoot, selectorFiles) {
  for (const [relativePath, selectors] of Object.entries(selectorFiles)) {
    const absolutePath = path.join(outputRoot, relativePath);
    fs.mkdirSync(path.dirname(absolutePath), { recursive: true });
    fs.writeFileSync(absolutePath, `${JSON.stringify(selectors.selectors, null, 2)}\n`, 'utf8');
  }
}

function resolveGeneratedDirRoot(configPath, generatedDir) {
  const configDir = path.dirname(configPath);
  const normalizedConfigDir = configDir.split(path.sep).join('/');
  const configRoot = normalizedConfigDir.endsWith('/resources/4-config')
    ? path.resolve(configDir, '..', '..')
    : configDir;

  return path.resolve(configRoot, generatedDir);
}

try {
  main(process.argv.slice(2));
} catch (error) {
  console.error(error instanceof Error ? error.message : String(error));
  process.exitCode = 1;
}
