#!/usr/bin/env node

const { DIRS, ROOT, CONFIG, ensureDir, listUserStories, listTestPlans, listTestSpecs, timestamp, log, reloadConfig, autoDetectConfig } = require('./scripts/utils');
const context = require('./scripts/context-manager');
const { executeTests } = require('./scripts/executor');
const { selfHeal } = require('./scripts/healer');
const { generateReport } = require('./scripts/reporter');
const path = require('path');
const fs = require('fs');

const COMMANDS = {
  init:    { desc: 'Create required directories and config', fn: cmdInit },
  plan:    { desc: '(handled by AI agent — see playwright-test-planner.agent.md)', fn: cmdPlan },
  generate:{ desc: '(handled by AI agent — see playwright-test-generator.agent.md)', fn: cmdGenerate },
  execute: { desc: '[test-name]      Run tests with Playwright', fn: cmdExecute },
  heal:    { desc: '[run-id]         Retry failed tests (AI handles deeper diagnosis)', fn: cmdHeal },
  report:  { desc: '[run-id]         Generate execution report', fn: cmdReport },
  'report:allure': { desc: '[run-id]   Generate Allure report from test results', fn: cmdAllure },
  status:  { desc: 'Show workflow state', fn: cmdStatus },
  list:    { desc: 'List user stories, test plans, and test specs', fn: cmdList },
  context: { desc: '[phase] [story]  Mark a pipeline phase complete for a story', fn: cmdContext },
};

function cmdInit() {
  log('INIT', 'Creating required directories...');
  Object.values(DIRS).forEach(dir => ensureDir(dir));

  const created = ['user-story', 'specs', 'tests', 'test-results', 'docs', '.qa-context', '.auth'];
  log('INIT', `Directories: ${created.join(', ')}`);

  const configPath = path.join(ROOT, '.qa-workflow.json');
  if (!fs.existsSync(configPath)) {
    log('INIT', 'Scanning project to auto-detect configuration...');
    const detected = autoDetectConfig();
    fs.writeFileSync(configPath, JSON.stringify(detected, null, 2) + '\n', 'utf-8');
    log('INIT', '.qa-workflow.json created with auto-detected settings');
    log('INIT', `Project: ${detected.project.name} → ${detected.project.url}`);
    reloadConfig();
  }

  const envContent = `# Application Context
# Auto-generated from project scan. Edit to provide more context for AI agents.

## Project
- Name: ${CONFIG.project.name}
- Description: ${CONFIG.project.description || '(auto-detect from README)'}
- URL: ${CONFIG.project.url}
- Environment: ${CONFIG.project.environment || 'Web Application'}

## Tech Stack
- (auto-detected from project files)

## Stable Selectors
- (populate during exploration)

## Known Flaky Areas
- (populate during execution)

## Authentication
- User: ${CONFIG.auth.user || '(set in .qa-workflow.json or auto-detect from .env)'}
`;
  const envPath = path.join(DIRS.docs, 'application-context.md');
  if (!fs.existsSync(envPath)) {
    fs.writeFileSync(envPath, envContent, 'utf-8');
    log('INIT', 'docs/application-context.md created — AI agents will use this for context');
  }

  context.init();
  log('INIT', '.qa-context/ initialized (pipeline.json, selectors.json, heal-history.json, traceability.json)');

  const authGitignore = path.join(DIRS.auth, '.gitignore');
  if (!fs.existsSync(authGitignore)) {
    fs.writeFileSync(authGitignore, '# Auth credentials and Playwright storage state — never commit\n*\n', 'utf-8');
    log('INIT', '.auth/ created (credentials.json, storage-state.json) — gitignored');
  }

  log('INIT', 'Ready. Edit .qa-workflow.json to override auto-detected values');
}

function cmdPlan() {
  console.log('');
  console.log('╔══════════════════════════════════════════════════════════╗');
  console.log('║  PLANNING is handled by the AI agent                   ║');
  console.log('║                                                         ║');
  console.log('║  Tell your AI agent:                                    ║');
  console.log('║  "Read router.md and plan tests for my-story.md"        ║');
  console.log('╚══════════════════════════════════════════════════════════╝');
  console.log('');
}

function cmdGenerate() {
  console.log('');
  console.log('╔══════════════════════════════════════════════════════════╗');
  console.log('║  TEST GENERATION is handled by the AI agent            ║');
  console.log('║                                                         ║');
  console.log('║  Tell your AI agent:                                    ║');
  console.log('║  "Generate tests for the plan in specs/"                ║');
  console.log('╚══════════════════════════════════════════════════════════╝');
  console.log('');
}

function cmdExecute() {
  const testName = process.argv[3];
  const headed = process.argv.includes('--headed');
  ensureDir(DIRS.testResults);

  console.log('');
  const result = executeTests(testName, { headed });

  console.log(`\n  Result: ${result.success ? '✓ PASSED' : '✗ FAILED'}`);
  console.log(`  Duration: ${(result.duration / 1000).toFixed(1)}s`);
  if (result.failedTests && result.failedTests.length > 0) {
    console.log(`  Failures: ${result.failedTests.length}`);
    result.failedTests.forEach(ft => console.log(`    - ${ft.test || ft.file}`));
  }

  if (!result.success) {
    console.log(`\n  Next step: Auto-heal failures:`);
    console.log(`  node ai-qa-workflow.js heal ${result.runId}`);
  } else {
    console.log(`\n  Next step: Generate report:`);
    console.log(`  node ai-qa-workflow.js report ${result.runId}`);
  }
}

function cmdHeal() {
  const runId = process.argv[3];
  const result = selfHeal(runId);

  if (result.rerun.length > 0) {
    console.log(`\n  Re-ran ${result.rerun.length} test(s) with longer timeout`);
  }
  if (result.stillFailing.length > 0) {
    console.log(`\n  ${result.stillFailing.length} test(s) still failing — AI agent should diagnose`);
    console.log(`  Tell your AI agent: "Debug the failing tests in test-results/"`);
  }
  if (result.rerun.length === 0 && result.stillFailing.length === 0) {
    console.log('\n  No failures to retry.');
  }
}

function cmdReport() {
  const runId = process.argv[3];
  const result = generateReport(runId);

  if (!result) {
    console.log('\n  No test results found. Run tests first: node ai-qa-workflow.js execute');
    process.exit(1);
  }

  console.log(`\n  ✓ Report generated: ${result.reportPath}`);
  console.log(`  Passed: ${result.stats.passed} | Failed: ${result.stats.failed} | Healed: ${result.stats.healed}`);
}

function cmdAllure() {
  const { execSync } = require('child_process');
  const allureResults = path.join(ROOT, 'allure-results');
  const allureReport = path.join(ROOT, 'allure-report');

  if (!fs.existsSync(allureResults)) {
    console.log('\n  No allure-results/ directory found.');
    console.log('  Ensure your Playwright config outputs Allure results.');
    console.log('  Add to playwright.config: reporter: [["list"], ["allure-playwright"]]');
    console.log('  Install: npm install -D allure-playwright');
    process.exit(1);
  }

  log('ALLURE', `Generating report from: allure-results/`);

  try {
    execSync(`npx allure generate "${allureResults}" --clean -o "${allureReport}"`, {
      cwd: ROOT,
      encoding: 'utf-8',
      timeout: 60000,
      stdio: 'pipe',
    });
    log('ALLURE', `Report generated: allure-report/index.html`);
    console.log(`\n  ✓ Allure report: allure-report/index.html`);
    console.log(`  Open in dashboard: /allure-report`);
  } catch (err) {
    console.error('\n  ✗ Failed to generate Allure report.');
    console.error('  Ensure Allure CLI is available: npm install -D allure-commandline');
    if (err.stderr) console.error(`  ${err.stderr.substring(0, 500)}`);
    process.exit(1);
  }
}

function cmdStatus() {
  console.log('\n📊 AI QA Workflow Status\n');

  const stories = listUserStories();
  console.log(`📝 User Stories: ${stories.length}`);
  stories.forEach(s => {
    const planFile = s.replace(/\.md$/, '-test-plan.md');
    const specFile = s.replace(/\.md$/, '.spec.ts');

    const hasPlan = listTestPlans().includes(planFile);
    const hasSpec = listTestSpecs().includes(specFile);

    const status = hasSpec ? '✅ Test written' : hasPlan ? '📋 Test plan ready' : '📄 Story only';
    console.log(`  ${status}  ${s}`);
  });

  const plans = listTestPlans();
  console.log(`\n📋 Test Plans: ${plans.length}`);
  plans.forEach(p => {
    const hasSpec = listTestSpecs().includes(p.replace('-test-plan.md', '.spec.ts'));
    console.log(`  ${hasSpec ? '✅ Test written' : '📄 Plan only'}  ${p}`);
  });

  const specs = listTestSpecs();
  console.log(`\n🧪 Test Specs: ${specs.length}`);
  specs.forEach(s => console.log(`  ${s}`));

  if (fs.existsSync(DIRS.testResults)) {
    const runDirs = fs.readdirSync(DIRS.testResults)
      .filter(d => fs.statSync(path.join(DIRS.testResults, d)).isDirectory());
    console.log(`\n📊 Execution Runs: ${runDirs.length}`);
    runDirs.forEach(d => {
      const resultFile = path.join(DIRS.testResults, d, 'execution-result.json');
      if (fs.existsSync(resultFile)) {
        const result = JSON.parse(fs.readFileSync(resultFile, 'utf-8'));
        console.log(`  ${result.success ? '✅' : '❌'} ${d} (${(result.duration / 1000).toFixed(1)}s)${result.failedTests ? ` - ${result.failedTests.length} failure(s)` : ''}`);
      } else {
        console.log(`  ⏳ ${d} (incomplete)`);
      }
    });
  }

  console.log('');
}

function cmdList() {
  console.log('\n📝 User Stories:');
  listUserStories().forEach(s => console.log(`  ${s}`));

  console.log('\n📋 Test Plans:');
  listTestPlans().forEach(p => console.log(`  ${p}`));

  console.log('\n🧪 Test Specs:');
  listTestSpecs().forEach(s => console.log(`  ${s}`));
  console.log('');
}

function cmdContext() {
  const phase = process.argv[3];
  const story = process.argv[4];

  if (!phase || !story) {
    console.log('\nUsage: node ai-qa-workflow.js context <phase> <story>');
    console.log('Phases: plan, generate, execute, heal, report');
    console.log('Example: node ai-qa-workflow.js context plan login\n');
    process.exit(1);
  }

  const validPhases = ['plan', 'generate', 'execute', 'heal', 'report'];
  if (!validPhases.includes(phase)) {
    console.log(`\nInvalid phase: ${phase}`);
    console.log(`Valid: ${validPhases.join(', ')}\n`);
    process.exit(1);
  }

  context.phaseComplete(phase, story);
  context.setCurrentStory(story);

  const pipeline = context.getPipeline();
  const storyData = pipeline.phases[phase];
  const completed = storyData ? storyData.completed.join(', ') : '—';

  console.log(`\n  ✓ Phase "${phase}" marked complete for story "${story}"`);
  console.log(`  Completed for this phase: ${completed}\n`);
}

const cmd = process.argv[2];

if (!cmd || cmd === '--help' || cmd === '-h') {
  console.log('\nAI QA Workflow - Test Automation Pipeline\n');
  console.log('Usage: node ai-qa-workflow.js <command> [options]\n');
  console.log('Commands:');
  for (const [name, { desc }] of Object.entries(COMMANDS)) {
    console.log(`  ${name.padEnd(12)} ${desc}`);
  }
  console.log('\nNote: Planning and test generation are done by the AI agent, not CLI commands.');
  console.log('See: .github/agents/ and prompts/ for AI instructions.\n');
  console.log('Examples:');
  console.log('  node ai-qa-workflow.js init');
  console.log('  node ai-qa-workflow.js execute');
  console.log('  node ai-qa-workflow.js execute my-feature');
  console.log('  node ai-qa-workflow.js heal');
  console.log('  node ai-qa-workflow.js heal run-2026-05-24');
  console.log('  node ai-qa-workflow.js report');
  console.log('  node ai-qa-workflow.js report:allure');
  console.log('  node ai-qa-workflow.js status');
  console.log('  node ai-qa-workflow.js list');
  console.log('  node ai-qa-workflow.js context plan login\n');
  process.exit(0);
}

if (!COMMANDS[cmd]) {
  console.error(`Unknown command: ${cmd}`);
  console.log(`Available: ${Object.keys(COMMANDS).join(', ')}`);
  process.exit(1);
}

ensureDir(DIRS.docs);
ensureDir(DIRS.testResults);

COMMANDS[cmd].fn();
