<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>OpenHW CVA6 Tier CI Dashboard</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
  <style>
    :root {
      --pass-color: #198754;
      --fail-color: #dc3545;
      --skip-color: #6c757d;
      --na-color: #e9ecef;
    }
    body { background: #f5f6fa; }

    /* Navbar - light background so logo is visible */
    .top-navbar { background: #fff; border-bottom: 1px solid #dee2e6; }
    .navbar-brand { font-weight: 700; letter-spacing: -0.5px; display: flex; align-items: center; color: #212529; }
    .navbar-brand img { height: 32px; margin-right: 12px; }

    .status-card { border-left: 4px solid; transition: transform 0.15s; }
    .status-card:hover { transform: translateY(-2px); }
    .status-card.pass { border-left-color: var(--pass-color); }
    .status-card.fail { border-left-color: var(--fail-color); }
    .status-card.unknown { border-left-color: var(--skip-color); }
    .badge-pass { background-color: var(--pass-color); }
    .badge-fail { background-color: var(--fail-color); }
    .badge-skip { background-color: var(--skip-color); }

    /* Test Matrix */
    .matrix-table th.suite-header {
      font-size: 0.72rem; writing-mode: vertical-lr; text-align: left;
      padding: 8px 4px; white-space: nowrap;
    }
    .matrix-table td.matrix-td {
      text-align: center; vertical-align: middle;
      min-width: 42px; height: 42px; padding: 2px;
    }
    .matrix-icon {
      display: inline-flex; align-items: center; justify-content: center;
      width: 32px; height: 32px; border-radius: 6px;
      font-size: 0.85rem; font-weight: 600;
      text-decoration: none; color: inherit;
    }
    .matrix-icon.pass { background: #d1e7dd; color: #0a3622; }
    .matrix-icon.fail { background: #f8d7da; color: #58151c; }
    .matrix-icon.na   { background: var(--na-color); color: #adb5bd; }
    .matrix-icon:hover { opacity: 0.8; }
    a.matrix-icon:hover { text-decoration: none; }

    /* Workflow selector */
    .wf-selector .btn { font-size: 0.82rem; padding: 0.3rem 0.9rem; }
    .wf-selector .btn-check:checked + .btn-outline-primary {
      background-color: #0d6efd; color: #fff;
    }

    /* Trend charts */
    .chart-container { position: relative; height: 260px; }

    /* Run history */
    .job-table { font-size: 0.85rem; }
    .job-table td, .job-table th { padding: 0.35rem 0.5rem; }

    @media (max-width: 768px) {
      .matrix-table th.suite-header { font-size: 0.6rem; }
      .matrix-icon { width: 26px; height: 26px; font-size: 0.75rem; }
    }
  </style>
</head>
<body>

<!-- ============================================================ -->
<!-- Section 1: Navbar - white background -->
<!-- ============================================================ -->
<nav class="navbar navbar-expand-lg top-navbar shadow-sm">
  <div class="container-fluid">
    <span class="navbar-brand">
      <img src="assets/openhw-landscape.svg"
           alt="OpenHW Foundation" height="32">
      CVA6 Tier CI Dashboard
    </span>
    <span class="navbar-text text-muted" style="font-size:0.85rem">
      Generated: {{ generated_at }}
    </span>
  </div>
</nav>

<div class="container-fluid px-3 px-lg-4 py-4">

<!-- ============================================================ -->
<!-- Section 2: Overview Cards -->
<!-- ============================================================ -->
<section class="mb-4">
  <h5 class="text-muted mb-3">Latest Run Status</h5>
  <div class="row g-3">
    {% for wf in workflows %}
    <div class="col-md-4">
      <div class="card status-card shadow-sm {{ 'pass' if wf.latest.conclusion == 'success' else ('fail' if wf.latest.conclusion == 'failure' else 'unknown') }}">
        <div class="card-body">
          <div class="d-flex justify-content-between align-items-start mb-2">
            <h6 class="card-title mb-0">{{ wf.display_name }}</h6>
            {% if wf.latest.conclusion == 'success' %}
              <span class="badge badge-pass">PASS</span>
            {% elif wf.latest.conclusion == 'failure' %}
              <span class="badge badge-fail">FAIL</span>
            {% else %}
              <span class="badge badge-skip">{{ wf.latest.conclusion|upper }}</span>
            {% endif %}
          </div>
          <div class="text-muted" style="font-size:0.8rem">
            <div>
              <strong>Branch:</strong> {{ wf.latest.head_branch }}
              &middot; <code>{{ wf.latest.head_sha }}</code>
            </div>
            <div>
              <strong>Jobs:</strong>
              <span class="text-success">{{ wf.latest.passed_jobs }} passed</span>
              {% if wf.latest.failed_jobs > 0 %}
                / <span class="text-danger">{{ wf.latest.failed_jobs }} failed</span>
              {% endif %}
              {% if wf.latest.skipped_jobs > 0 %}
                / <span class="text-secondary">{{ wf.latest.skipped_jobs }} skipped</span>
              {% endif %}
              ({{ wf.latest.total_jobs }} total)
            </div>
            <div>
              <strong>Duration:</strong> {{ wf.latest.duration_display }}
              &middot; <strong>Run:</strong> #{{ wf.latest.run_number }}
            </div>
          </div>
          <div class="mt-2">
            <a href="{{ wf.latest.html_url }}" class="btn btn-outline-secondary btn-sm" target="_blank" rel="noopener">
              View on GitHub &rarr;
            </a>
          </div>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</section>

<!-- ============================================================ -->
<!-- Section 3: Config x TestSuite Matrix with workflow selector -->
<!-- ============================================================ -->
<section class="mb-4">
  <div class="d-flex flex-wrap align-items-center gap-3 mb-3">
    <h5 class="text-muted mb-0">Test Coverage Matrix</h5>
    <!-- Workflow selector -->
    <div class="wf-selector btn-group" role="group" aria-label="Select workflow">
      {% for wf in workflows %}
      <input type="radio" class="btn-check" name="matrixWf" id="wf-{{ wf.key }}"
             value="{{ wf.key }}" autocomplete="off"
             {{ 'checked' if wf.key == default_matrix_wf else '' }}
             onchange="renderMatrix(this.value)">
      <label class="btn btn-outline-primary" for="wf-{{ wf.key }}">{{ wf.display_name }}</label>
      {% endfor %}
    </div>
    <span id="matrixStats" class="text-muted" style="font-size:0.8rem"></span>
  </div>

  {% if matrix_data %}
  <div class="card shadow-sm">
    <div class="card-body p-2">
      <div class="d-flex align-items-center gap-3 mb-2 px-2" style="font-size:0.8rem">
        <span class="text-muted">Legend:</span>
        <span><span class="matrix-icon pass" style="width:16px;height:16px;font-size:0.65rem">&#10003;</span> Pass</span>
        <span><span class="matrix-icon fail" style="width:16px;height:16px;font-size:0.65rem">&#10007;</span> Fail</span>
        <span><span class="matrix-icon na" style="width:16px;height:16px;font-size:0.65rem">&ndash;</span> Not in matrix</span>
      </div>
      <div class="table-responsive">
        <table class="table table-sm matrix-table mb-0" id="matrixTable">
          <thead id="matrixHead"></thead>
          <tbody id="matrixBody"></tbody>
        </table>
      </div>
    </div>
  </div>
  {% else %}
  <div class="alert alert-secondary">No CI run data available yet.</div>
  {% endif %}
</section>

<!-- ============================================================ -->
<!-- Section 4: Trend Charts -->
<!-- ============================================================ -->
<section class="mb-4">
  <h5 class="text-muted mb-3">Trends (Last {{ trend_count }} Runs)</h5>
  <div class="row g-3">
    {% for wf in workflows %}
    <div class="col-lg-4">
      <div class="card shadow-sm">
        <div class="card-header py-2" style="font-size:0.85rem">{{ wf.display_name }}</div>
        <div class="card-body p-2">
          <div class="chart-container">
            <canvas id="chart-{{ wf.key }}"></canvas>
          </div>
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</section>

<!-- ============================================================ -->
<!-- Section 5: Run History Accordions -->
<!-- ============================================================ -->
<section class="mb-4">
  <h5 class="text-muted mb-3">Run History</h5>
  <div class="accordion" id="historyAccordion">
    {% for wf in workflows %}
    <div class="accordion-item">
      <h2 class="accordion-header">
        <button class="accordion-button {{ '' if loop.first else 'collapsed' }}" type="button"
                data-bs-toggle="collapse" data-bs-target="#collapse-{{ wf.key }}">
          {{ wf.display_name }}
          <span class="badge bg-secondary ms-2">{{ wf.runs|length }} runs</span>
        </button>
      </h2>
      <div id="collapse-{{ wf.key }}" class="accordion-collapse collapse {{ 'show' if loop.first else '' }}"
           data-bs-parent="#historyAccordion">
        <div class="accordion-body p-2">
          {% if wf.runs %}
          <div class="accordion" id="runsAccordion-{{ wf.key }}">
            {% for run in wf.runs[:20] %}
            <div class="accordion-item">
              <h2 class="accordion-header">
                <button class="accordion-button collapsed py-2" type="button"
                        data-bs-toggle="collapse" data-bs-target="#run-{{ wf.key }}-{{ run.id }}"
                        style="font-size:0.85rem">
                  {% if run.conclusion == 'success' %}
                    <span class="badge badge-pass me-2">PASS</span>
                  {% elif run.conclusion == 'failure' %}
                    <span class="badge badge-fail me-2">FAIL</span>
                  {% else %}
                    <span class="badge badge-skip me-2">{{ run.conclusion|upper }}</span>
                  {% endif %}
                  #{{ run.run_number }}
                  &middot; {{ run.head_branch }}
                  &middot; <code>{{ run.head_sha }}</code>
                  &middot; {{ run.duration_display }}
                  <span class="ms-auto text-muted" style="font-size:0.75rem">{{ run.created_at_display }}</span>
                </button>
              </h2>
              <div id="run-{{ wf.key }}-{{ run.id }}" class="accordion-collapse collapse"
                   data-bs-parent="#runsAccordion-{{ wf.key }}">
                <div class="accordion-body p-2">
                  <div class="mb-2" style="font-size:0.8rem">
                    <a href="{{ run.html_url }}" target="_blank" rel="noopener">View on GitHub</a>
                    &middot; Event: {{ run.event }}
                    &middot; Jobs: {{ run.passed_jobs }}/{{ run.total_jobs }} passed
                  </div>
                  {% if run.jobs %}
                  <div class="table-responsive">
                    <table class="table table-sm table-hover job-table mb-0">
                      <thead class="table-light">
                        <tr>
                          <th>Arch</th>
                          <th>Config</th>
                          <th>Test Suite</th>
                          <th>Status</th>
                          <th>Duration</th>
                        </tr>
                      </thead>
                      <tbody>
                        {% for job in run.jobs %}
                        <tr>
                          <td>{{ job.arch|upper }}</td>
                          <td><code>{{ job.config }}</code></td>
                          <td>{{ job.testcase }}</td>
                          <td>
                            {% if job.conclusion == 'success' %}
                              <span class="badge badge-pass">PASS</span>
                            {% elif job.conclusion == 'failure' %}
                              <span class="badge badge-fail">FAIL</span>
                            {% else %}
                              <span class="badge badge-skip">{{ job.conclusion|upper }}</span>
                            {% endif %}
                          </td>
                          <td>{{ job.duration_display }}</td>
                        </tr>
                        {% endfor %}
                      </tbody>
                    </table>
                  </div>
                  {% else %}
                  <div class="text-muted">No job data available.</div>
                  {% endif %}
                </div>
              </div>
            </div>
            {% endfor %}
          </div>
          {% else %}
          <div class="text-muted">No run history available.</div>
          {% endif %}
        </div>
      </div>
    </div>
    {% endfor %}
  </div>
</section>

</div><!-- /container -->

<!-- ============================================================ -->
<!-- Section 6: Footer -->
<!-- ============================================================ -->
<footer class="bg-dark text-light py-3 mt-4">
  <div class="container-fluid px-4">
    <div class="row">
      <div class="col-md-6">
        <small class="text-light opacity-75">
          &copy; {{ year }} <a href="https://www.openhwgroup.org/" class="text-light" target="_blank" rel="noopener">OpenHW Group</a>
          &middot; CVA6 Tier CI Dashboard
        </small>
      </div>
      <div class="col-md-6 text-md-end">
        <small class="text-light opacity-75">
          Generated: {{ generated_at }}
          &middot; <a href="https://github.com/{{ repo }}" class="text-light" target="_blank" rel="noopener">Source</a>
        </small>
      </div>
    </div>
  </div>
</footer>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
// ============================================================
// Matrix data (all workflows combined) - injected by Jinja2
// ============================================================
const matrixData   = {{ matrix_data_json|safe }};
const matrixConfigs = {{ matrix_configs_json|safe }};
const matrixSuites  = {{ matrix_suites_json|safe }};

/**
 * Render the test matrix table for a given workflow.
 * Only shows configs x suites that the selected workflow covers.
 */
function renderMatrix(wfKey) {
  const thead = document.getElementById('matrixHead');
  const tbody = document.getElementById('matrixBody');
  const stats = document.getElementById('matrixStats');
  if (!thead || !tbody) return;

  // Determine which suites this workflow covers
  const activeSuites = matrixSuites.filter(suite =>
    matrixConfigs.some(cfg =>
      matrixData[cfg] && matrixData[cfg][suite] && matrixData[cfg][suite][wfKey]
    )
  );

  // Determine which configs this workflow covers
  const activeConfigs = matrixConfigs.filter(cfg =>
    activeSuites.some(suite =>
      matrixData[cfg] && matrixData[cfg][suite] && matrixData[cfg][suite][wfKey]
    )
  );

  // Count pass/fail
  let pass = 0, fail = 0, total = 0;

  // Build header
  let headHtml = '<tr><th style="writing-mode:horizontal-tb; min-width:200px; font-size:0.8rem">Config</th>';
  activeSuites.forEach(s => {
    headHtml += '<th class="suite-header">' + s + '</th>';
  });
  headHtml += '</tr>';
  thead.innerHTML = headHtml;

  // Build body
  let bodyHtml = '';
  activeConfigs.forEach(cfg => {
    bodyHtml += '<tr>';
    bodyHtml += '<td class="text-nowrap fw-medium" style="font-size:0.78rem; padding:6px 8px; vertical-align:middle">' + cfg + '</td>';
    activeSuites.forEach(suite => {
      const cell = matrixData[cfg] && matrixData[cfg][suite] && matrixData[cfg][suite][wfKey];
      if (cell) {
        total++;
        const c = cell.conclusion;
        if (c === 'success') {
          pass++;
          bodyHtml += '<td class="matrix-td"><a href="' + cell.html_url + '" target="_blank" rel="noopener" class="matrix-icon pass" title="' + cfg + ' / ' + suite + ': PASS">&#10003;</a></td>';
        } else if (c === 'failure') {
          fail++;
          bodyHtml += '<td class="matrix-td"><a href="' + cell.html_url + '" target="_blank" rel="noopener" class="matrix-icon fail" title="' + cfg + ' / ' + suite + ': FAIL">&#10007;</a></td>';
        } else {
          bodyHtml += '<td class="matrix-td"><span class="matrix-icon na" title="' + cfg + ' / ' + suite + ': ' + c + '">?</span></td>';
        }
      } else {
        bodyHtml += '<td class="matrix-td"><span class="matrix-icon na" title="' + cfg + ' / ' + suite + ': not in matrix">&ndash;</span></td>';
      }
    });
    bodyHtml += '</tr>';
  });
  tbody.innerHTML = bodyHtml;

  // Update stats
  if (stats) {
    stats.textContent = activeConfigs.length + ' configs \u00d7 ' + activeSuites.length + ' suites \u2014 '
      + pass + ' passed' + (fail > 0 ? ', ' + fail + ' failed' : '') + ' (' + total + ' jobs)';
  }
}

// Initial render
renderMatrix('{{ default_matrix_wf }}');

// ============================================================
// Chart.js Trend Charts
// ============================================================
const chartData = {{ chart_data_json|safe }};

Object.keys(chartData).forEach(key => {
  const wf = chartData[key];
  const ctx = document.getElementById('chart-' + key);
  if (!ctx || !wf.labels.length) return;

  new Chart(ctx, {
    type: 'line',
    data: {
      labels: wf.labels,
      datasets: [
        {
          label: 'Pass Rate (%)',
          data: wf.pass_rates,
          borderColor: '#198754',
          backgroundColor: 'rgba(25, 135, 84, 0.1)',
          fill: true,
          tension: 0.3,
          yAxisID: 'y',
          pointRadius: 3,
        },
        {
          label: 'Duration (min)',
          data: wf.durations,
          borderColor: '#0d6efd',
          backgroundColor: 'rgba(13, 110, 253, 0.1)',
          fill: false,
          tension: 0.3,
          yAxisID: 'y1',
          pointRadius: 3,
          borderDash: [5, 3],
        }
      ]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      interaction: { mode: 'index', intersect: false },
      plugins: {
        legend: { position: 'bottom', labels: { boxWidth: 12, font: { size: 11 } } },
        tooltip: {
          callbacks: {
            title: function(items) { return 'Run #' + items[0].label; }
          }
        }
      },
      scales: {
        y: {
          type: 'linear', position: 'left',
          min: 0, max: 100,
          title: { display: true, text: 'Pass Rate (%)', font: { size: 11 } },
          ticks: { font: { size: 10 } }
        },
        y1: {
          type: 'linear', position: 'right',
          min: 0,
          title: { display: true, text: 'Duration (min)', font: { size: 11 } },
          ticks: { font: { size: 10 } },
          grid: { drawOnChartArea: false }
        },
        x: {
          ticks: { font: { size: 10 }, maxRotation: 45 }
        }
      }
    }
  });
});
</script>
</body>
</html>
