import { getPortalThemeCSS } from './portal-theme.js';
import { buildNavbar } from './portal-navbar.js';
import { buildSvgBarChart } from './svg-charts/bar-chart.js';
import { buildSvgDualLineChart } from './svg-charts/line-chart.js';
import { buildSvgPieChart } from './svg-charts/pie-chart.js';
import { CHART_COLORS } from './svg-charts/chart-utils.js';
import { computeVelocity } from './data-aggregators/velocity-aggregator.js';
import { computeBurndown } from './data-aggregators/burndown-aggregator.js';
import { detectBottlenecks } from './data-aggregators/bottleneck-detector.js';
import { computeAccuracy } from './data-aggregators/accuracy-aggregator.js';
/**
 * Generate the full analytics.html page for the Planu portal.
 * Returns an HTML string ready to write to disk.
 */
export function generateAnalyticsPage(specs, metrics) {
    const navbar = buildNavbar('analytics', '', ['analytics', 'dashboard']);
    const kpiHtml = buildKpiSection(specs);
    const burndownHtml = buildBurndownSection(specs);
    const velocityHtml = buildVelocitySection(specs);
    const accuracyHtml = buildAccuracySection(specs, metrics);
    const distributionHtml = buildDistributionSection(specs);
    const bottleneckHtml = buildBottleneckSection(specs);
    return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>Analytics — Planu</title>
<style>
${getPortalThemeCSS()}
${ANALYTICS_CSS}
</style>
</head>
<body>
${navbar}
<main class="analytics-main">
  <h1 class="analytics-title">📈 Analytics</h1>
  ${kpiHtml}
  <div class="analytics-charts-row">
    <section class="planu-card analytics-section">
      <h2>Burn-down</h2>
      ${burndownHtml}
    </section>
    <section class="planu-card analytics-section">
      <h2>Velocity</h2>
      ${velocityHtml}
    </section>
  </div>
  <section class="planu-card analytics-section">
    <h2>Estimated vs Actual Hours</h2>
    ${accuracyHtml}
  </section>
  <section class="planu-card analytics-section">
    <h2>Distribution</h2>
    ${distributionHtml}
  </section>
  <section class="planu-card analytics-section">
    <h2>Bottlenecks</h2>
    ${bottleneckHtml}
  </section>
</main>
</body>
</html>`;
}
// --- Section builders ---
function buildKpiSection(specs) {
    if (specs.length === 0) {
        return '<p class="analytics-empty">No specs available.</p>';
    }
    const total = specs.length;
    const done = specs.filter((s) => s.status === 'done').length;
    const pct = total > 0 ? Math.round((done / total) * 100) : 0;
    const accuracyRecords = computeAccuracy(specs);
    const avgAccuracy = accuracyRecords.length > 0
        ? Math.round(accuracyRecords.reduce((s, r) => s + r.accuracy, 0) / accuracyRecords.length)
        : 0;
    const totalHours = specs.reduce((s, sp) => s + sp.estimation.devHours, 0);
    const velocity = computeVelocity(specs);
    const avgVelocity = velocity.length > 0
        ? Math.round(velocity.reduce((s, v) => s + v.count, 0) / velocity.length)
        : 0;
    const kpis = [
        { label: 'Total Specs', value: String(total), icon: '📋' },
        { label: 'Done', value: String(done), icon: '✅' },
        { label: 'Completion', value: `${pct}%`, icon: '📊' },
        { label: 'Avg Accuracy', value: `${avgAccuracy}%`, icon: '🎯' },
        { label: 'Total Hours', value: String(totalHours), icon: '⏱️' },
        { label: 'Avg Velocity', value: `${avgVelocity}/mo`, icon: '🚀' },
    ];
    const cards = kpis
        .map((k) => `<div class="kpi-card planu-card">
  <div class="kpi-icon">${k.icon}</div>
  <div class="kpi-value">${escapeHtml(k.value)}</div>
  <div class="kpi-label">${escapeHtml(k.label)}</div>
</div>`)
        .join('\n');
    return `<div class="kpi-row">${cards}</div>`;
}
function buildBurndownSection(specs) {
    const points = computeBurndown(specs);
    if (points.length === 0) {
        return '<p class="analytics-empty">Insufficient data for burndown.</p>';
    }
    const series1 = points.map((p, i) => ({ x: i, y: p.remaining, label: p.date }));
    const series2 = points.map((p, i) => ({ x: i, y: p.ideal }));
    return buildSvgDualLineChart(series1, series2, {
        title: 'Remaining vs Ideal',
        label1: 'Remaining',
        label2: 'Ideal',
        showDots: false,
    });
}
function buildVelocitySection(specs) {
    const velocity = computeVelocity(specs);
    if (velocity.length === 0) {
        return '<p class="analytics-empty">No completed specs with dates.</p>';
    }
    const data = velocity.map((v, i) => ({
        label: v.period,
        value: v.count,
        color: CHART_COLORS[i % CHART_COLORS.length],
    }));
    return buildSvgBarChart(data, { title: 'Specs Completed per Month' });
}
function buildAccuracySection(specs, _metrics) {
    const records = computeAccuracy(specs);
    if (records.length === 0) {
        return '<p class="analytics-empty">No completed specs with estimation data.</p>';
    }
    const estimated = records.map((r) => ({
        label: r.specId,
        value: r.estimated,
        color: CHART_COLORS[0],
    }));
    const actual = records.map((r) => ({
        label: r.specId,
        value: r.actual,
        color: CHART_COLORS[1],
    }));
    const estSvg = buildSvgBarChart(estimated, { title: 'Estimated Hours' });
    const actSvg = buildSvgBarChart(actual, { title: 'Actual Hours' });
    return `<div class="analytics-charts-row">${estSvg}${actSvg}</div>`;
}
function buildDistributionSection(specs) {
    if (specs.length === 0) {
        return '<p class="analytics-empty">No specs to distribute.</p>';
    }
    const byType = countBy(specs, (s) => s.type);
    const byRisk = countBy(specs, (s) => s.risk);
    const byDifficulty = countBy(specs, (s) => String(s.difficulty));
    const typePie = buildSvgPieChart(mapToPieSlices(byType));
    const riskPie = buildSvgPieChart(mapToPieSlices(byRisk));
    const diffPie = buildSvgPieChart(mapToPieSlices(byDifficulty));
    return `<div class="distribution-row">
  <div class="distribution-col">
    <h3>By Type</h3>${typePie}
  </div>
  <div class="distribution-col">
    <h3>By Risk</h3>${riskPie}
  </div>
  <div class="distribution-col">
    <h3>By Difficulty</h3>${diffPie}
  </div>
</div>`;
}
function buildBottleneckSection(specs) {
    const bottlenecks = detectBottlenecks(specs);
    if (bottlenecks.length === 0) {
        return '<p class="analytics-empty">No bottlenecks detected. 🎉</p>';
    }
    const rows = bottlenecks.map((b) => {
        const badgeClass = b.staleDays > 30 ? 'planu-badge-danger' : 'planu-badge-warning';
        return `<tr>
  <td>${escapeHtml(b.specId)}</td>
  <td>${escapeHtml(b.title)}</td>
  <td><span class="planu-badge planu-badge-muted">${escapeHtml(b.status)}</span></td>
  <td><span class="planu-badge ${badgeClass}">${b.staleDays}d</span></td>
</tr>`;
    });
    return `<table class="bottleneck-table">
<thead>
  <tr><th>ID</th><th>Title</th><th>Status</th><th>Stale</th></tr>
</thead>
<tbody>
${rows.join('\n')}
</tbody>
</table>`;
}
// --- Helpers ---
function countBy(arr, key) {
    const map = new Map();
    for (const item of arr) {
        const k = key(item);
        map.set(k, (map.get(k) ?? 0) + 1);
    }
    return map;
}
function mapToPieSlices(counts) {
    return Array.from(counts.entries()).map(([label, value], i) => ({
        label,
        value,
        color: CHART_COLORS[i % CHART_COLORS.length] ?? '#e94560',
    }));
}
function escapeHtml(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;');
}
const ANALYTICS_CSS = `
  .analytics-main {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 16px 40px;
  }
  .analytics-title { font-size: 1.5rem; color: var(--planu-primary); margin-bottom: 20px; }
  .analytics-empty { color: #9ca3af; font-style: italic; padding: 12px 0; }
  .analytics-section { margin-bottom: 24px; }
  .analytics-section h2 {
    font-size: 1.05rem;
    color: var(--planu-secondary);
    margin-bottom: 14px;
    border-bottom: 1px solid var(--planu-border);
    padding-bottom: 6px;
  }
  .analytics-charts-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-bottom: 24px;
  }
  @media (max-width: 700px) { .analytics-charts-row { grid-template-columns: 1fr; } }
  .kpi-row {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 12px;
    margin-bottom: 24px;
  }
  @media (max-width: 900px) { .kpi-row { grid-template-columns: repeat(3, 1fr); } }
  @media (max-width: 500px) { .kpi-row { grid-template-columns: repeat(2, 1fr); } }
  .kpi-card { text-align: center; padding: 14px 10px; }
  .kpi-icon { font-size: 1.6rem; margin-bottom: 4px; }
  .kpi-value { font-size: 1.5rem; font-weight: 700; color: var(--planu-primary); }
  .kpi-label { font-size: 0.75rem; color: #6b7280; margin-top: 2px; }
  .distribution-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
  }
  @media (max-width: 700px) { .distribution-row { grid-template-columns: 1fr; } }
  .distribution-col h3 { font-size: 0.9rem; color: #4b5563; margin-bottom: 8px; text-align: center; }
  .bottleneck-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
  .bottleneck-table th {
    background: #f3f4f6;
    text-align: left;
    padding: 8px 10px;
    font-size: 0.8rem;
    color: #6b7280;
  }
  .bottleneck-table td { padding: 8px 10px; border-bottom: 1px solid #f3f4f6; }
  @media print { .analytics-charts-row { grid-template-columns: 1fr; } }
`;
//# sourceMappingURL=analytics-page.js.map