const express = require('express');
const router = express.Router();
const pm = require('../services/project-manager');
const fs = require('fs');
const path = require('path');

router.get('/', (req, res) => {
  const projectId = req.query.project;
  const project = projectId ? pm.get(projectId) : pm.getAll()[0];
  if (!project) return res.redirect('/projects');

  const bridge = pm.getBridge(project.id);
  const stories = bridge.listUserStories().map(s => {
    const baseName = s.replace(/\.md$/i, '');
    const plans = bridge.listTestPlans();
    const specs = bridge.listTestSpecs();
    return {
      name: s,
      content: bridge.getStoryContent(s),
      hasPlan: plans.some(p => p.toLowerCase().includes(baseName.toLowerCase())),
      planName: plans.find(p => p.toLowerCase().includes(baseName.toLowerCase())),
      hasSpec: specs.some(sp => sp.toLowerCase().includes(baseName.toLowerCase())),
    };
  });

  res.render('stories', { project, stories });
});

router.get('/:storyName', (req, res) => {
  const projectId = req.query.project;
  const project = projectId ? pm.get(projectId) : pm.getAll()[0];
  if (!project) return res.redirect('/projects');

  const bridge = pm.getBridge(project.id);
  const content = bridge.getStoryContent(req.params.storyName);
  if (!content) return res.status(404).render('error', { message: 'Story not found' });

  const baseName = req.params.storyName.replace(/\.md$/i, '');
  const plans = bridge.listTestPlans();
  const specs = bridge.listTestSpecs();
  const planName = plans.find(p => p.toLowerCase().includes(baseName.toLowerCase()));
  const specName = specs.find(sp => sp.toLowerCase().includes(baseName.toLowerCase()));

  const plan = planName ? bridge.getPlanContent(planName) : null;
  const spec = specName ? bridge.getSpecContent(specName) : null;

  const runDirs = bridge.getRunDirs();
  const results = runDirs.map(d => {
    const r = bridge.getRunResult(d.name);
    if (!r) return null;
    const testMatch = specName ? r.test && r.test.toLowerCase().includes(baseName.toLowerCase()) : true;
    return testMatch ? {
      id: d.name,
      success: r.success,
      duration: r.duration,
      passedCount: r.passedTests ? r.passedTests.length : 0,
      failedCount: r.failedTests ? r.failedTests.length : 0,
    } : null;
  }).filter(Boolean);

  const hasRun = results.length > 0;
  const hasAllure = bridge.hasAllureReport();

  res.render('story', { project, story: { name: req.params.storyName, content, plan, planName, spec, specName, results, hasRun, hasAllure } });
});

// Helper to stream CLI command output asynchronously to client
function streamCommand(res, req, bridge, command) {
  if (bridge.isRunning) {
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.write("Erreur : Un pipeline de test est déjà en cours d'exécution sur ce projet. Veuillez patienter.\n");
    return res.end();
  }

  res.setHeader('Content-Type', 'text/plain; charset=utf-8');
  res.setHeader('Transfer-Encoding', 'chunked');

  let child;
  try {
    child = bridge.runAsync(
      command,
      (data) => {
        res.write(data);
      },
      (success) => {
        res.write(`\n\n--- [FINISHED: ${success ? 'SUCCESS' : 'FAILED'}] ---\n`);
        res.end();
      }
    );
  } catch (err) {
    res.write(`Error: ${err.message}\n`);
    return res.end();
  }

  // Prevent zombies: kill child process if user cancels/disconnects request
  req.on('close', () => {
    if (child && !child.killed) {
      child.kill('SIGINT');
    }
  });
}

router.post('/:storyName/plan', (req, res) => {
  const projectId = req.query.project;
  const project = projectId ? pm.get(projectId) : pm.getAll()[0];
  if (!project) return res.status(404).send('Project not found');

  const bridge = pm.getBridge(project.id);
  const command = `node ai-qa-workflow.js plan "${req.params.storyName}"`;
  streamCommand(res, req, bridge, command);
});

router.post('/:storyName/generate', (req, res) => {
  const projectId = req.query.project;
  const project = projectId ? pm.get(projectId) : pm.getAll()[0];
  if (!project) return res.status(404).send('Project not found');

  const bridge = pm.getBridge(project.id);
  const baseName = req.params.storyName.replace(/\.md$/i, '');
  const plans = bridge.listTestPlans();
  const planName = plans.find(p => p.toLowerCase().includes(baseName.toLowerCase()));
  if (!planName) {
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.write('Error: No test plan found. Run plan first.\n');
    return res.end();
  }

  const command = `node ai-qa-workflow.js generate "${planName}"`;
  streamCommand(res, req, bridge, command);
});

router.post('/:storyName/execute', (req, res) => {
  const projectId = req.query.project;
  const project = projectId ? pm.get(projectId) : pm.getAll()[0];
  if (!project) return res.status(404).send('Project not found');

  const bridge = pm.getBridge(project.id);
  const baseName = req.params.storyName.replace(/\.md$/i, '');
  const specs = bridge.listTestSpecs();
  const specName = specs.find(sp => sp.toLowerCase().includes(baseName.toLowerCase()));
  if (!specName) {
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.write(`Error: No test spec found for "${req.params.storyName}". Generate one first.\n`);
    return res.end();
  }

  const testName = specName.replace(/\.spec\.ts$/i, '');
  const command = `node ai-qa-workflow.js execute "${testName}"`;
  streamCommand(res, req, bridge, command);
});

router.post('/:storyName/full-pipeline', (req, res) => {
  const projectId = req.query.project;
  const project = projectId ? pm.get(projectId) : pm.getAll()[0];
  if (!project) return res.status(404).send('Project not found');

  const bridge = pm.getBridge(project.id);
  const command = `node ai-qa-workflow.js run "${req.params.storyName}"`;
  streamCommand(res, req, bridge, command);
});

module.exports = router;
