const path = require('node:path');
const { promisify } = require('node:util');
const { execFile } = require('node:child_process');
const kleur = require('kleur');
const ui = require('../utils/ui');
const { printCompactHeader } = require('../utils/brand');
const { createTranslator, detectDefaultLanguage } = require('../utils/i18n');
const { pathExists } = require('../utils/fs');

const execFileAsync = promisify(execFile);
const REPO_ROOT = path.resolve(__dirname, '../../..');

const VALIDATION_MATRIX = [
  {
    id: 'firebase_widget',
    backend: 'firebase',
    features: ['widget'],
    projectPath: path.join(REPO_ROOT, 'kasy_firebase_base')
  },
  {
    id: 'supabase_widget',
    backend: 'supabase',
    features: ['widget'],
    projectPath: path.join(REPO_ROOT, 'kasy_supabase_base')
  },
  {
    id: 'api_web_ci',
    backend: 'api',
    features: ['web', 'ci'],
    projectPath: path.join(REPO_ROOT, 'kasy_api_base')
  }
];

async function runCommand(cmd, args, cwd) {
  await execFileAsync(cmd, args, { cwd, env: process.env });
}

function buildCommandsForPlatform(analyzeOnly) {
  const commands = [['flutter', ['analyze']]];
  if (analyzeOnly) {
    return commands;
  }

  commands.push(['flutter', ['build', 'apk', '--debug', '--no-pub']]);

  if (process.platform === 'darwin') {
    commands.push(['flutter', ['build', 'ios', '--simulator', '--no-codesign', '--no-pub']]);
  }

  return commands;
}

async function runValidate({ language, analyzeOnly = false } = {}) {
  const t = createTranslator(language || detectDefaultLanguage());

  const anyExists = await Promise.any(
    VALIDATION_MATRIX.map(async (c) => {
      if (!(await pathExists(c.projectPath))) throw new Error();
    })
  ).then(() => true).catch(() => false);

  if (!anyExists) {
    printCompactHeader(t);
    ui.intro(t('validate.title'));
    ui.log.warn('kasy validate is only available in the Kasy development environment.');
    ui.log.message(kleur.dim('Generate test projects with `kasy new` first, then run this command.'));
    ui.outro('Skipped');
    return;
  }

  printCompactHeader(t);
  ui.intro(t('validate.title'));

  const commands = buildCommandsForPlatform(analyzeOnly);
  const failures = [];

  for (const combo of VALIDATION_MATRIX) {
    const label = `${combo.backend} + ${combo.features.join('+')}`;
    const exists = await pathExists(combo.projectPath);

    if (!exists) {
      const projectName = path.basename(combo.projectPath);
      failures.push({ combo: combo.id, reason: `${t('validate.projectNotFound')}: ${combo.projectPath}` });
      ui.log.error(label);
      ui.log.message(
        `${kleur.dim(combo.projectPath)}\n` +
        kleur.yellow(
          `⚠ Projeto base não encontrado. Gere-o antes de validar:\n` +
          `   kasy new ${projectName} --backend ${combo.backend}\n` +
          `   O projeto deve ser gerado uma vez e mantido localmente para CI.`
        )
      );
      continue;
    }

    ui.log.step(`${kleur.cyan('•')} ${label}\n${kleur.dim(combo.projectPath)}`);

    let comboFailed = false;
    for (const [cmd, args] of commands) {
      const printable = `${cmd} ${args.join(' ')}`;
      const spinner = ui.spinner();
      spinner.start(printable);
      try {
        await runCommand(cmd, args, combo.projectPath);
        spinner.stop(`${printable} ${kleur.green(t('validate.ok'))}`);
      } catch (error) {
        comboFailed = true;
        failures.push({
          combo: combo.id,
          reason: `${printable} ${t('validate.fail')}`
        });
        spinner.error(`${printable} ${t('validate.fail')}`);
        break;
      }
    }

    if (!comboFailed) {
      ui.log.success(`${combo.id} ${t('validate.passed')}`);
    }
  }

  if (failures.length > 0) {
    ui.log.error(t('validate.failed'));
    failures.forEach((failure) => {
      ui.log.error(`- ${failure.combo}: ${failure.reason}`);
    });
    throw new Error(t('validate.error'));
  }

  ui.outro(t('validate.success'));
}

module.exports = {
  runValidate,
  VALIDATION_MATRIX
};
