const express = require('express');
const fs = require('fs');
const path = require('path');
const cors = require('cors');
const { enrichTestCase } = require('./lib/enrich');
const { generateReport } = require('./scripts/generate-report');
const { generateTestPlan } = require('./scripts/generate-test-plan');
const { loadTestcases } = require('./lib/load-testcases');
const { saveTestcases } = require('./lib/save-testcases');

const app = express();
const PORT = process.env.PORT || 4321;

const DATA_FILE = path.join(__dirname, '..', 'editor', 'data', 'testcases.json'); // legacy transition only

app.use(cors());
app.use(express.json({ limit: '10mb' }));
app.use(express.static(path.join(__dirname, '..', 'web')));

// Get all testcases - primary source is now the YAML tree under testcases/
app.get('/api/testcases', (req, res) => {
  try {
    const testcases = loadTestcases();
    res.json(testcases);
  } catch (e) {
    res.status(500).json({ error: 'Could not read testcases data' });
  }
});

// Save all testcases - writes to YAML files (source of truth) + legacy JSON during transition
app.post('/api/testcases', (req, res) => {
  try {
    const testcases = req.body;
    if (!Array.isArray(testcases)) {
      return res.status(400).json({ error: 'Body must be an array of testcases' });
    }

    // Primary: persist to YAML tree
    saveTestcases(testcases);

    // Transition: still write the legacy JSON so other tools don't break yet (best effort)
    try {
      const legacyDir = path.dirname(DATA_FILE);
      if (!fs.existsSync(legacyDir)) {
        fs.mkdirSync(legacyDir, { recursive: true });
      }
      fs.writeFileSync(DATA_FILE, JSON.stringify(testcases, null, 2), 'utf8');
    } catch (legacyErr) {
      console.warn('Warning: Could not write legacy JSON file:', legacyErr.message);
      // Continue anyway - YAML is the source of truth now
    }

    res.json({ success: true, count: testcases.length, source: 'yaml+json' });
  } catch (e) {
    res.status(500).json({ error: 'Failed to save data' });
  }
});

// Enrich a single test case with smart defaults (used by the editor "Reset suggestions" button)
app.post('/api/enrich', (req, res) => {
  try {
    const test = req.body;
    if (!test || !test.id) {
      return res.status(400).json({ error: 'Test object with id is required' });
    }
    const enriched = enrichTestCase(test);
    res.json(enriched);
  } catch (e) {
    res.status(500).json({ error: 'Enrichment failed' });
  }
});

// ==================== EXPORT ENDPOINTS ====================

// Full automation report (timestamped qa_automation.html)
app.get('/api/export/report', (req, res) => {
  try {
    const generatedPath = generateReport();
    const html = fs.readFileSync(generatedPath, 'utf8');

    const filename = path.basename(generatedPath);
    res.setHeader('Content-Type', 'text/html');
    res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
    res.send(html);
  } catch (e) {
    res.status(500).send('Error generating report: ' + e.message);
  }
});

// Simple summary HTML (lightweight)
app.get('/api/export/summary', (req, res) => {
  try {
    const tests = loadTestcases();
    const total = tests.length;
    const automated = tests.filter(t => t.status === 'automated').length;
    const autoPct = ((automated / total) * 100).toFixed(1);

    const html = `<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>Test Plan Summary</title>
<style>body{font-family:system-ui;background:#0b1120;color:#e2e8f0;padding:40px} .card{background:#1e2937;padding:24px;border-radius:12px}</style>
</head><body>
<h1>Test Automation Summary</h1>
<div class="card">
  <h2>${total} Test Cases</h2>
  <h3 style="color:#4ade80">${automated} Automated (${autoPct}%)</h3>
  <p>Generated on ${new Date().toLocaleString()}</p>
</div>
</body></html>`;

    res.setHeader('Content-Type', 'text/html');
    res.setHeader('Content-Disposition', 'attachment; filename="QA-Automation-Summary-Report.html"');
    res.send(html);
  } catch (e) {
    res.status(500).send('Error: ' + e.message);
  }
});

// ==================== TEST PLANS (Persistent & Editable) ====================

const PLANS_DIR = path.join(__dirname, '..', 'output', 'testplans', 'plans');

// Ensure plans dir
if (!fs.existsSync(PLANS_DIR)) fs.mkdirSync(PLANS_DIR, { recursive: true });

function computeAutomationSummary(tests) {
  const total = tests.length;
  let automated = 0, partial = 0, manual = 0;

  tests.forEach(t => {
    const status = t.automation_status || t.status || 'manual';
    if (status === 'automated') automated++;
    else if (status === 'partial') partial++;
    else manual++;
  });

  const automatable = automated + partial;
  const automatable_percentage = total > 0 ? Math.round((automatable / total) * 100 * 10) / 10 : 0;

  return {
    total,
    automated,
    partial,
    manual,
    automatable_percentage
  };
}

function getPlanPath(planId) {
  return path.join(PLANS_DIR, `${planId}.json`);
}

// Create a new Test Plan from selected IDs
app.post('/api/test-plans', (req, res) => {
  try {
    const { ids = [], name = 'Manual Test Plan' } = req.body;

    if (!Array.isArray(ids) || ids.length === 0) {
      return res.status(400).json({ error: 'No test IDs provided' });
    }

    // Use the proper loader instead of the broken legacy JSON file
    const allTests = loadTestcases();
    const selectedTests = allTests.filter(t => ids.includes(t.id));

    if (selectedTests.length === 0) {
      return res.status(400).json({ error: 'No valid tests found' });
    }

    const planId = Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);
    const now = new Date().toISOString();

    const plan = {
      id: planId,
      name: name || 'Manual Test Plan',
      createdAt: now,
      updatedAt: now,
      tests: selectedTests.map(t => ({
        ...t,
        severity: 'High',
        expectedResult: t.description || '',
        actualResult: '',
        testerStatus: 'N/A',
        comments: ''
      }))
    };

    plan.automation_summary = computeAutomationSummary(plan.tests);

    fs.writeFileSync(getPlanPath(planId), JSON.stringify(plan, null, 2));

    res.json({ success: true, planId, name: plan.name });
  } catch (e) {
    res.status(500).json({ error: 'Failed to create Test Plan: ' + e.message });
  }
});

// Get a plan
app.get('/api/test-plans/:id', (req, res) => {
  try {
    const planPath = getPlanPath(req.params.id);
    if (!fs.existsSync(planPath)) return res.status(404).json({ error: 'Plan not found' });

    const plan = JSON.parse(fs.readFileSync(planPath, 'utf8'));
    if (!plan.automation_summary && plan.tests) {
      plan.automation_summary = computeAutomationSummary(plan.tests);
    }
    res.json(plan);
  } catch (e) {
    res.status(500).json({ error: 'Error loading plan' });
  }
});

// Save/update a plan (for auto-save from tester editor)
app.post('/api/test-plans/:id', (req, res) => {
  try {
    const planPath = getPlanPath(req.params.id);
    if (!fs.existsSync(planPath)) return res.status(404).json({ error: 'Plan not found' });

    const existing = JSON.parse(fs.readFileSync(planPath, 'utf8'));
    const updated = {
      ...existing,
      ...req.body,
      updatedAt: new Date().toISOString()
    };

    updated.automation_summary = computeAutomationSummary(updated.tests || []);

    fs.writeFileSync(planPath, JSON.stringify(updated, null, 2));
    res.json({ success: true });
  } catch (e) {
    res.status(500).json({ error: 'Failed to save plan' });
  }
});

// Delete a plan
app.delete('/api/test-plans/:id', (req, res) => {
  try {
    const planPath = getPlanPath(req.params.id);
    if (!fs.existsSync(planPath)) {
      return res.status(404).json({ error: 'Plan not found' });
    }

    fs.unlinkSync(planPath);
    res.json({ success: true });
  } catch (e) {
    res.status(500).json({ error: 'Failed to delete plan' });
  }
});

// List all plans (for future tester portal)
app.get('/api/test-plans', (req, res) => {
  try {
    const files = fs.readdirSync(PLANS_DIR).filter(f => f.endsWith('.json'));
    const plans = files.map(file => {
      const data = JSON.parse(fs.readFileSync(path.join(PLANS_DIR, file), 'utf8'));
      return {
        id: data.id,
        name: data.name,
        createdAt: data.createdAt,
        updatedAt: data.updatedAt,
        testCount: data.tests ? data.tests.length : 0
      };
    }).sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));

    res.json(plans);
  } catch (e) {
    res.json([]);
  }
});

// Raw JSON
app.get('/api/export/json', (req, res) => {
  res.setHeader('Content-Disposition', 'attachment; filename="testcases.json"');
  res.sendFile(DATA_FILE);
});

// Export Automated Playwright Tests (uses the generator script)
app.post('/api/export/automated-tests', (req, res) => {
  try {
    const { group } = req.body;

    if (!group) {
      return res.status(400).json({ error: 'Group is required for now' });
    }

    const { execSync } = require('child_process');
    const scriptPath = path.join(__dirname, 'scripts', 'generate-playwright-tests.js');

    // Generate for the specific group
    execSync(`node ${scriptPath} --group ${group}`, { stdio: 'inherit' });

    res.json({
      success: true,
      message: `Automated tests generated for group ${group}`,
      group
    });
  } catch (e) {
    console.error(e);
    res.status(500).json({ error: 'Failed to export automated tests: ' + e.message });
  }
});

// Health
app.get('/api/health', (req, res) => res.json({ status: 'ok' }));

app.listen(PORT, () => {
  console.log(`\n🚀 Autotest Editor running at http://localhost:${PORT}`);
  console.log(`   Primary data source: YAML files under testcases/ and testplans/\n`);
});
