const { DIRS, log } = require('./utils');
const context = require('./context-manager');
const path = require('path');
const fs = require('fs');
const { execSync } = require('child_process');

function selfHeal(runId) {
  const runDir = runId
    ? path.join(DIRS.testResults, runId)
    : findLatestRunDir();

  if (!runDir || !fs.existsSync(runDir)) {
    log('RETRY', 'No execution results found');
    return { rerun: [], stillFailing: [] };
  }

  const resultPath = path.join(runDir, 'execution-result.json');
  if (!fs.existsSync(resultPath)) {
    log('RETRY', 'No execution result found');
    return { rerun: [], stillFailing: [] };
  }

  const result = JSON.parse(fs.readFileSync(resultPath, 'utf-8'));

  const storyName = result.story || null;

  if (result.success) {
    log('RETRY', 'All tests passed — nothing to retry');
    return { rerun: [], stillFailing: [] };
  }

  const failedTests = result.failedTests || [];
  log('RETRY', `Found ${failedTests.length} failed test(s)`);

  const rerun = [];
  const stillFailing = [];
  const healingAttempts = [];

  for (const failure of failedTests) {
    const testFile = failure.file || failure.test || '';
    log('RETRY', `  Re-running: ${testFile}`);

    const startMs = Date.now();
    const args = ['npx', 'playwright', 'test', testFile, '--reporter=list', '--timeout=60000'];

    try {
      execSync(args.join(' '), {
        cwd: DIRS.ROOT,
        encoding: 'utf-8',
        timeout: 120000,
        stdio: 'pipe',
      });
      rerun.push({ test: testFile, status: 'passed' });
      log('RETRY', `  ✓ Passed on retry: ${testFile}`);
      healingAttempts.push({ test: testFile, status: 'passed', duration_ms: Date.now() - startMs, strategy: 'timeout_retry' });
    } catch {
      stillFailing.push({ test: testFile, status: 'failed', error: failure.error || '' });
      log('RETRY', `  ✗ Still failing: ${testFile}`);
      healingAttempts.push({ test: testFile, status: 'failed', duration_ms: Date.now() - startMs, strategy: 'timeout_retry' });
    }
  }

  const healingReport = {
    runId: path.basename(runDir),
    story: storyName,
    totalAttempts: healingAttempts.length,
    totalHealed: rerun.length,
    remainingFailures: stillFailing.length,
    healingAttempts,
    healedTests: rerun.map(r => ({ test: r.test, status: 'passed', healedOnAttempt: 1, strategy: 'timeout_retry' })),
    stillFailingTests: stillFailing.map(f => ({ test: f.test, status: 'failed', error: f.error })),
    timestamp: new Date().toISOString(),
  };

  writeHealingReport(runDir, healingReport);

  if (storyName) {
    context.phaseComplete('heal', storyName);
    if (rerun.length > 0) context.setHealed(storyName, path.basename(runDir));
  }

  console.log('');
  console.log('╔════════════════════════════════════════════════════════════════╗');
  console.log('║  DEEPER DIAGNOSIS is handled by the AI agent                 ║');
  console.log('║                                                               ║');
  console.log('║  The AI reads playwright-test-healer.agent.md, debugs with   ║');
  console.log('║  Playwright MCP (test_debug, browser_snapshot, etc.), and    ║');
  console.log('║  fixes selectors/timing issues or marks real bugs.           ║');
  console.log('║                                                               ║');
  console.log('║  Tell your AI agent:                                          ║');
  console.log('║  "Debug and heal the failing tests in test-results/' + path.basename(runDir) + '"');
  console.log('╚════════════════════════════════════════════════════════════════╝');
  console.log('');

  if (rerun.length > 0) {
    console.log(`  Re-ran ${rerun.length} test(s) with longer timeout`);
    console.log(`  Passed on retry: ${rerun.length}`);
  }
  if (stillFailing.length > 0) {
    console.log(`  Still failing: ${stillFailing.length}`);
    stillFailing.forEach(f => console.log(`    - ${f.test}`));
  }
  console.log('');

  return { rerun, stillFailing };
}

function writeHealingReport(runDir, report) {
  const reportPath = path.join(runDir, 'healing-report.json');
  fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), 'utf-8');
  log('RETRY', `Healing report saved: ${reportPath}`);
}

function findLatestRunDir() {
  if (!fs.existsSync(DIRS.testResults)) return null;
  const dirs = fs.readdirSync(DIRS.testResults)
    .map(d => ({ name: d, path: path.join(DIRS.testResults, d) }))
    .filter(d => fs.statSync(d.path).isDirectory())
    .sort((a, b) => fs.statSync(b.path).mtimeMs - fs.statSync(a.path).mtimeMs);
  return dirs.length > 0 ? dirs[0].path : null;
}

if (require.main === module) {
  const runId = process.argv[2];
  selfHeal(runId);
}

module.exports = { selfHeal };
