const { execSync, spawn } = require('child_process');
const path = require('path');
const fs = require('fs');

class CliBridge {
  constructor(projectPath) {
    this.projectPath = projectPath;
    this.isRunning = false;
  }

  runAsync(command, onData, onEnd) {
    if (this.isRunning) {
      throw new Error('Un pipeline de test est déjà en cours d\'exécution sur ce projet.');
    }

    this.isRunning = true;

    // Split command into executable and args
    const args = command.split(' ');
    const cmd = args.shift();

    const child = spawn(cmd, args, {
      cwd: this.projectPath,
      shell: true,
      env: { ...process.env, FORCE_COLOR: '0' } // Disable ANSI escape codes for clean browser logs
    });

    child.stdout.on('data', (data) => {
      onData(data.toString());
    });

    child.stderr.on('data', (data) => {
      onData(data.toString());
    });

    child.on('close', (code) => {
      this.isRunning = false;
      onEnd(code === 0);
    });

    return child;
  }

  _run(command) {
    try {
      const output = execSync(command, {
        cwd: this.projectPath,
        encoding: 'utf-8',
        timeout: 300000,
        maxBuffer: 10 * 1024 * 1024,
        stdio: ['pipe', 'pipe', 'pipe'],
      });
      return { success: true, output, error: null };
    } catch (err) {
      return {
        success: false,
        output: err.stdout || '',
        error: err.message,
        stderr: err.stderr || '',
      };
    }
  }

  status() {
    return this._run('node ai-qa-workflow.js status');
  }

  plan(storyName) {
    return this._run(`node ai-qa-workflow.js plan "${storyName}"`);
  }

  generate(planName) {
    return this._run(`node ai-qa-workflow.js generate "${planName}"`);
  }

  execute(testName) {
    return this._run(`node ai-qa-workflow.js execute ${testName}`);
  }

  heal(runId) {
    return this._run(`node ai-qa-workflow.js heal ${runId || ''}`);
  }

  report(runId) {
    return this._run(`node ai-qa-workflow.js report ${runId || ''}`);
  }

  runFull(storyName) {
    return this._run(`node ai-qa-workflow.js run "${storyName}"`);
  }

  _readDir(subDir, extension) {
    const dirPath = path.join(this.projectPath, subDir);
    if (!fs.existsSync(dirPath)) return [];
    return fs.readdirSync(dirPath)
      .filter(f => f.endsWith(extension))
      .sort();
  }

  listUserStories() {
    return this._readDir('user-story', '.md');
  }

  listTestPlans() {
    return this._readDir('specs', '.md');
  }

  listTestSpecs() {
    return this._readDir('tests', '.spec.ts');
  }

  listAll() {
    return {
      stories: this.listUserStories(),
      plans: this.listTestPlans(),
      specs: this.listTestSpecs(),
    };
  }

  getStoryContent(storyName) {
    const storyPath = path.join(this.projectPath, 'user-story', storyName);
    if (!fs.existsSync(storyPath)) return null;
    return fs.readFileSync(storyPath, 'utf-8');
  }

  getPlanContent(planName) {
    const planPath = path.join(this.projectPath, 'specs', planName);
    if (!fs.existsSync(planPath)) return null;
    return fs.readFileSync(planPath, 'utf-8');
  }

  getSpecContent(specName) {
    const specPath = path.join(this.projectPath, 'tests', specName);
    if (!fs.existsSync(specPath)) return null;
    return fs.readFileSync(specPath, 'utf-8');
  }

  getRunDirs() {
    const resultsDir = path.join(this.projectPath, 'test-results');
    if (!fs.existsSync(resultsDir)) return [];
    const dirs = fs.readdirSync(resultsDir)
      .map(d => ({ name: d, path: path.join(resultsDir, d) }))
      .filter(d => fs.statSync(d.path).isDirectory())
      .sort((a, b) => fs.statSync(b.path).mtimeMs - fs.statSync(a.path).mtimeMs);
    return dirs;
  }

  getRunResult(runDirName) {
    const resultPath = path.join(this.projectPath, 'test-results', runDirName, 'execution-result.json');
    if (!fs.existsSync(resultPath)) return null;
    try {
      return JSON.parse(fs.readFileSync(resultPath, 'utf-8'));
    } catch (err) {
      console.error(`Error parsing execution-result.json for ${runDirName}:`, err.message);
      return null;
    }
  }

  getHealingReport(runDirName) {
    const reportPath = path.join(this.projectPath, 'test-results', runDirName, 'healing-report.json');
    if (!fs.existsSync(reportPath)) return null;
    try {
      return JSON.parse(fs.readFileSync(reportPath, 'utf-8'));
    } catch (err) {
      console.error(`Error parsing healing-report.json for ${runDirName}:`, err.message);
      return null;
    }
  }

  getFinalReport(runDirName) {
    const reportPath = path.join(this.projectPath, 'test-results', runDirName, 'final-test-report.md');
    if (!fs.existsSync(reportPath)) return null;
    return fs.readFileSync(reportPath, 'utf-8');
  }

  hasAllureReport() {
    return fs.existsSync(path.join(this.projectPath, 'allure-report', 'index.html'));
  }

  getAllureResultsDir() {
    const dir = path.join(this.projectPath, 'allure-results');
    if (!fs.existsSync(dir)) return null;
    return dir;
  }
}

module.exports = CliBridge;
