{% extends "pxy_dashboard/partials/base.html" %}
{% load static %}

{% block title %}SAMI · Explorer{% endblock title %}

{% block extra_css %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.min.css">
<style>
  .form-inline .form-control { min-width: 200px; }
  .metric { font-variant-numeric: tabular-nums; }
  .chart-wrap { position: relative; height: 340px; }
  .sami-img { max-width: 100%; border-radius: .5rem; box-shadow: 0 0.25rem 0.75rem rgba(0,0,0,.05); }
  .table thead th { white-space: nowrap; }
</style>
{% endblock extra_css %}

{% block pagetitle %}
  {% include "pxy_dashboard/partials/page-title.html" with pagetitle="SAMI" title="Explorer" %}
{% endblock pagetitle %}

{% block content %}
<div class="row">
  <div class="col-12">
    <div class="card mb-3">
      <div class="card-body">
        <form id="runForm" class="row gy-2 gx-2 align-items-end">
          <div class="col-12 col-md-4">
            <label class="form-label">Indicator</label>
            <input id="indicator" class="form-control" placeholder="imss_wages_2023" value="imss_wages_2023">
          </div>
          <div class="col-12 col-md-6">
            <label class="form-label">Cities (comma-separated)</label>
            <input id="cities" class="form-control" placeholder="CDMX,GDL,MTY,PUE">
          </div>
          <div class="col-12 col-md-2">
            <button id="btnRun" type="submit" class="btn btn-primary w-100">Run SAMI</button>
          </div>
          <div class="col-12">
            <small class="text-muted">Calls <code>/api/sami/run</code> and displays results interactively.</small>
          </div>
        </form>
      </div>
    </div>

    <div id="results" class="card d-none">
      <div class="card-body">
        <div class="d-flex flex-wrap justify-content-between mb-3">
          <div>
            <h4 class="header-title mb-0">Results</h4>
            <small id="meta" class="text-muted">—</small>
          </div>
          <div class="d-flex gap-2">
            <a id="dlCsv" class="btn btn-outline-secondary btn-sm" download="sami_residuals.csv">Download CSV</a>
            <a id="openPng" class="btn btn-outline-secondary btn-sm" target="_blank">Open chart PNG</a>
          </div>
        </div>

        <div class="row g-3">
          <div class="col-12 col-lg-5">
            <div class="row g-2">
              <div class="col-4">
                <div class="text-muted small">β (scaling)</div>
                <div id="beta" class="metric fs-5">—</div>
              </div>
              <div class="col-4">
                <div class="text-muted small">R²</div>
                <div id="r2" class="metric fs-5">—</div>
              </div>
              <div class="col-4">
                <div class="text-muted small">n (cities)</div>
                <div id="nobs" class="metric fs-5">—</div>
              </div>
            </div>
            <hr>
            <!-- NEW: Interactive scatter -->
            <div class="chart-wrap mb-3">
              <canvas id="scatterChart"></canvas>
            </div>
            <!-- Existing: Ranking bars -->
            <div class="chart-wrap">
              <canvas id="barChart"></canvas>
            </div>
          </div>

          <div class="col-12 col-lg-7">
            <div class="mb-2 text-muted small">Model scatter (server-rendered)</div>
            <img id="chartPng" class="sami-img" alt="SAMI scatter" src="">
          </div>
        </div>

        <hr>
        <div class="table-responsive">
          <table id="tbl" class="table table-sm table-hover align-middle">
            <thead>
              <tr>
                <th scope="col">Rank</th>
                <th scope="col">City</th>
                <th scope="col">SAMI (z)</th>
              </tr>
            </thead>
            <tbody></tbody>
          </table>
        </div>

      </div>
    </div>
  </div>
</div>
{% endblock content %}

{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<script>
(function(){
  const form   = document.getElementById('runForm');
  const btn    = document.getElementById('btnRun');
  const indInp = document.getElementById('indicator');
  const cityInp= document.getElementById('cities');
  const meta   = document.getElementById('meta');
  const betaEl = document.getElementById('beta');
  const r2El   = document.getElementById('r2');
  const nobsEl = document.getElementById('nobs');
  const img    = document.getElementById('chartPng');
  const openPng= document.getElementById('openPng');
  const dlCsv  = document.getElementById('dlCsv');
  const card   = document.getElementById('results');
  const tbody  = document.querySelector('#tbl tbody');

  let barChart = null;
  let scatterChart = null; // NEW

  function parseCities(txt){
    return (txt || '')
      .split(/[,\n]/g)
      .map(s=>s.trim())
      .filter(Boolean);
  }

  function mkCsv(residuals){
    const rows = [['rank','city','sami_z']];
    residuals.forEach(r => rows.push([r.rank, r.city, r.sami]));
    const csv = rows.map(r => r.join(',')).join('\n');
    return 'data:text/csv;charset=utf-8,' + encodeURIComponent(csv);
  }

  function toLog(v){ return (v>0) ? Math.log(v) : null; } // in case server didn’t include logs

  form.addEventListener('submit', async (e)=>{
    e.preventDefault();
    const indicator = indInp.value.trim();
    const cities = parseCities(cityInp.value);

    if (!indicator || !cities.length){
      alert('Please provide indicator and at least one city.');
      return;
    }

    btn.disabled = true;
    btn.textContent = 'Running…';

    try{
      const resp = await fetch('/api/sami/run', {
        method: 'POST',
        headers: { 'Content-Type':'application/json' },
        body: JSON.stringify({ indicator, cities })
      });
      if (!resp.ok){
        const t = await resp.text();
        throw new Error(`HTTP ${resp.status}: ${t}`);
      }
      const data = await resp.json();

      // Meta & metrics
      meta.textContent = `indicator: ${data.indicator} · run ${String(data.run_id||'').slice(0,8)}…`;
      betaEl.textContent = (data.beta!=null) ? Number(data.beta).toFixed(3) : '—';
      r2El.textContent   = (data.r2!=null)   ? Number(data.r2).toFixed(3)   : '—';
      nobsEl.textContent = (data.residuals||[]).length;

      // PNG
      const abs = (u)=> !u ? '' : (u.startsWith('http') ? u : (window.location.origin + u));
      img.src = abs(data.chart_url || '');
      openPng.href = abs(data.chart_url || '#');

      // --- NEW: Interactive scatter (uses `points[]`, `alpha`, `beta`) ---
      const pts = Array.isArray(data.points) ? data.points : [];
      if (scatterChart){ scatterChart.destroy(); }
      if (pts.length >= 2){
        const scatter = pts
          .map(p => ({
            x: (p.log_N ?? toLog(p.N)),
            y: (p.log_value ?? toLog(p.value)),
            city: p.city
          }))
          .filter(p => Number.isFinite(p.x) && Number.isFinite(p.y));

        if (scatter.length >= 2){
          const xs = scatter.map(p=>p.x);
          const minX = Math.min(...xs), maxX = Math.max(...xs);
          const alpha = (typeof data.alpha === 'number') ? data.alpha : 0;
          const beta  = (typeof data.beta  === 'number') ? data.beta  : 1;
          const line = [
            { x: minX, y: alpha + beta*minX },
            { x: maxX, y: alpha + beta*maxX },
          ];

          const ctxS = document.getElementById('scatterChart');
          scatterChart = new Chart(ctxS, {
            type: 'scatter',
            data: {
              datasets: [
                {
                  label: 'Cities',
                  data: scatter,
                  pointRadius: 4,
                  pointHoverRadius: 6,
                  borderWidth: 0
                },
                {
                  type: 'line',
                  label: 'OLS fit',
                  data: line,
                  borderWidth: 2,
                  pointRadius: 0
                }
              ]
            },
            options: {
              maintainAspectRatio: false,
              plugins: {
                legend: { display: false },
                tooltip: {
                  callbacks: {
                    label: ctx => {
                      const d = ctx.raw;
                      return ` ${d.city}: (${ctx.parsed.x.toFixed(3)}, ${ctx.parsed.y.toFixed(3)})`;
                    }
                  }
                }
              },
              scales: {
                x: { type: 'linear', title: { display: true, text: 'log(N)' } },
                y: { title: { display: true, text: 'log(value)' } }
              }
            }
          });
        }
      }
      // --- end interactive scatter ---

      // Ranking bar chart (sorted by rank ascending)
      const res = Array.from(data.residuals || []).sort((a,b)=> Number(a.rank)-Number(b.rank));
      const labels = res.map(r => `${r.rank}. ${r.city}`);
      const values = res.map(r => Number(r.sami||0));

      if (barChart){ barChart.destroy(); }
      const ctx = document.getElementById('barChart');
      barChart = new Chart(ctx, {
        type: 'bar',
        data: {
          labels,
          datasets: [{
            label: 'SAMI (z)',
            data: values,
            borderWidth: 1
          }]
        },
        options: {
          maintainAspectRatio: false,
          plugins: {
            legend: { display: false },
            tooltip: {
              callbacks: {
                label: (ctx)=> ` ${ctx.parsed.y.toFixed(2)} z`
              }
            }
          },
          scales: {
            x: { ticks: { maxRotation: 0, autoSkip: true } },
            y: { beginAtZero: true }
          }
        }
      });

      // Table
      tbody.innerHTML = '';
      res.forEach(r => {
        const tr = document.createElement('tr');
        tr.innerHTML = `
          <td class="text-muted">${r.rank}</td>
          <td>${r.city}</td>
          <td class="fw-semibold">${Number(r.sami||0).toFixed(2)}</td>
        `;
        tbody.appendChild(tr);
      });

      // CSV
      dlCsv.href = mkCsv(res);

      // Show card
      card.classList.remove('d-none');

    } catch(err){
      console.error(err);
      alert('SAMI run failed. See console for details.');
    } finally {
      btn.disabled = false;
      btn.textContent = 'Run SAMI';
    }
  });

})();
</script>
{% endblock extra_js %}
