/* ============================================================
   Screen 5 — Geografiya (Regional Analytics)
   ============================================================ */

const MAP_LAYERS = [
  { id: 'density',   uz: 'Murojaat zichligi',   ru: 'Плотность',     unit: '' },
  { id: 'dominant',  uz: 'Asosiy mavzu',         ru: 'Доминир. тема', unit: '' },
  { id: 'sentiment', uz: 'Sentiment',            ru: 'Тональность',   unit: '' },
  { id: 'unresolved',uz: 'Hal etilmagan ulush',  ru: 'Нерешён. доля', unit: '%' },
  { id: 'response',  uz: 'O‘rt. javob vaqti',    ru: 'Сред. ответ',   unit: 'daq' },
];

function ScreenGeo() {
  const [layer, setLayer] = useState('density');
  const [selected, setSelected] = useState('tas');
  const [sort, setSort] = useState({ col: 'total', dir: 'desc' });

  // Live data
  const byRegion = useApi('/api/stats/by-region', { pollMs: 20000 });
  const regionDetail = useApi(`/api/regions/${selected}`, { pollMs: 15000 });

  // Build regionStats keyed by region id from API rows.
  // Add derived fields (dominantTopic, unresolvedPct, sentScore as %, avgResp daq).
  const regionStats = useMemo(() => {
    const out = {};
    const rows = byRegion.data?.items || [];
    const rowsById = Object.fromEntries(rows.map(r => [r.id, r]));
    REGIONS.forEach(r => {
      const b = rowsById[r.id] || {};
      const total = b.total || 0;
      const sentScoreNorm = total > 0 ? ((b.sent_score || 0) / total) * 100 : 0;
      const unresolvedPct = total > 0 ? ((b.open || 0) / total) * 100 : 0;
      // detail panel carries top_topics — use it for the *selected* region only
      let dominantTopic = 'logistic';
      let dominantCount = 0;
      if (r.id === selected && regionDetail.data?.top_topics?.length) {
        dominantTopic = regionDetail.data.top_topics[0].id;
        dominantCount = regionDetail.data.top_topics[0].n;
      }
      out[r.id] = {
        total,
        open: b.open || 0,
        urgent: b.urgent || 0,
        dominantTopic,
        dominantCount,
        sentScore: sentScoreNorm,
        unresolvedPct,
        avgResp: Math.round((b.avg_resp_sec ?? 0) / 60) || 0,
        farmers: b.farmers || 0,
        today: b.today || 0,
        week: b.this_week || 0,
        weekPrev: b.prev_week || 0,
      };
    });
    return out;
  }, [byRegion.data, selected, regionDetail.data]);

  // color function per layer
  const allTotals = Object.values(regionStats).map(s => s.total);
  const maxT = Math.max(...allTotals), minT = Math.min(...allTotals);
  const allUnres = Object.values(regionStats).map(s => s.unresolvedPct);
  const allResp = Object.values(regionStats).map(s => s.avgResp);

  const layerValues = useMemo(() => {
    const out = {};
    REGIONS.forEach(r => {
      const s = regionStats[r.id];
      if (layer === 'density')    out[r.id] = s.total;
      else if (layer === 'unresolved') out[r.id] = s.unresolvedPct;
      else if (layer === 'response')   out[r.id] = s.avgResp;
      else if (layer === 'sentiment')  out[r.id] = s.sentScore;
      else if (layer === 'dominant')   out[r.id] = s.dominantTopic;
    });
    return out;
  }, [layer]);

  const layerColor = (v, r) => {
    if (layer === 'dominant') {
      return TOPIC_BY_ID[v]?.color || 'var(--bg-sunken)';
    }
    if (layer === 'sentiment') {
      // diverging
      const max = Math.max(...Object.values(layerValues).map(x => Math.abs(x)));
      const t = v / max;
      if (t >= 0) return `oklch(${(0.92 - t * 0.30).toFixed(3)} ${(0.02 + Math.abs(t) * 0.10).toFixed(3)} 155)`;
      return `oklch(${(0.92 - Math.abs(t) * 0.30).toFixed(3)} ${(0.02 + Math.abs(t) * 0.13).toFixed(3)} 25)`;
    }
    if (layer === 'unresolved') {
      const t = (v - Math.min(...allUnres)) / (Math.max(...allUnres) - Math.min(...allUnres));
      return `oklch(${(0.92 - t * 0.30).toFixed(3)} ${(0.02 + t * 0.11).toFixed(3)} 30)`;
    }
    if (layer === 'response') {
      const t = (v - Math.min(...allResp)) / (Math.max(...allResp) - Math.min(...allResp));
      return `oklch(${(0.92 - t * 0.30).toFixed(3)} ${(0.02 + t * 0.10).toFixed(3)} 75)`;
    }
    // density
    const t = (v - minT) / (maxT - minT);
    return `oklch(${(0.92 - t * 0.38).toFixed(3)} ${(0.02 + t * 0.10).toFixed(3)} 195)`;
  };

  // National averages (across the 14 regions)
  const nat = useMemo(() => {
    const stats = Object.values(regionStats);
    const n = REGIONS.length;
    const sum = (k) => stats.reduce((a, s) => a + (s[k] || 0), 0);
    const avg = (k) => sum(k) / n;
    return {
      total: avg('total'),
      open: avg('open'),
      urgent: avg('urgent'),
      avgResp: avg('avgResp'),
      sentScore: avg('sentScore'),
      unresolvedPct: avg('unresolvedPct'),
      farmers: avg('farmers'),
    };
  }, [regionStats]);

  const sel = REGION_BY_ID[selected];
  const selStats = regionStats[selected];

  // Top 5 topics for selected region (from /api/regions/:id)
  const top5 = useMemo(() => {
    const items = regionDetail.data?.top_topics || [];
    return items.map(t => ({ topic: TOPIC_BY_ID[t.id] || { id: t.id, uz: t.uz, color: t.color }, n: t.n }));
  }, [regionDetail.data]);

  // Top farmers in region
  const regionFarmers = useMemo(() => {
    return (regionDetail.data?.top_farmers || []).map(f => ({
      id: f.id, name: f.name, inquiries: f.inquiries,
    }));
  }, [regionDetail.data]);

  // 30-day time series for region
  const regionTime = useMemo(() => {
    const arr = new Array(30).fill(0);
    const daily = regionDetail.data?.daily || [];
    const today = new Date();
    const byDay = Object.fromEntries(daily.map(d => [d.day, d.n]));
    for (let i = 0; i < 30; i++) {
      const d = new Date(today.getTime() - (29 - i) * 86400000);
      const key = d.toISOString().slice(0, 10);
      arr[i] = byDay[key] || 0;
    }
    return arr;
  }, [regionDetail.data]);

  // Leaderboard
  const lb = useMemo(() => {
    const arr = REGIONS.map(r => ({
      ...r,
      ...regionStats[r.id],
    }));
    arr.sort((a, b) => {
      const av = a[sort.col], bv = b[sort.col];
      if (av < bv) return sort.dir === 'asc' ? -1 : 1;
      if (av > bv) return sort.dir === 'asc' ? 1 : -1;
      return 0;
    });
    return arr;
  }, [sort, regionStats]);

  // Bubble data — used by the SentimentQuadrants component
  const bubbleData = REGIONS.map(r => {
    const s = regionStats[r.id] || {};
    const dom = s.dominantTopic ? TOPIC_BY_ID[s.dominantTopic] : null;
    return {
      label: r.code,
      fullLabel: r.uz,
      x: s.total || 0,
      y: s.sentScore || 0,
      r: s.open || 0,
      color: dom?.color || 'var(--ink-4)',
    };
  });

  // Radar values (normalize 0..100)
  const radarAxes = ['Hajm', 'Shoshilinch', 'Sent. ijobiy', 'Tezkor javob', 'Hal etish', 'Fermerlar'];
  const norm = (v, min, max) => Math.max(0, Math.min(100, ((v - min) / (max - min)) * 100));
  const reg = norm(selStats.total, 0, maxT);
  const urg = norm(selStats.urgent, 0, Math.max(...Object.values(regionStats).map(s => s.urgent)));
  const sent = norm(selStats.sentScore, -30, 30);
  const resp = 100 - norm(selStats.avgResp, Math.min(...allResp), Math.max(...allResp));
  const reso = 100 - norm(selStats.unresolvedPct, Math.min(...allUnres), Math.max(...allUnres));
  const farm = norm(selStats.farmers, 0, Math.max(...Object.values(regionStats).map(s => s.farmers)));

  const natReg = norm(nat.total, 0, maxT);
  const natUrg = norm(nat.urgent, 0, Math.max(...Object.values(regionStats).map(s => s.urgent)));
  const natSent = norm(nat.sentScore, -30, 30);
  const natResp = 100 - norm(nat.avgResp, Math.min(...allResp), Math.max(...allResp));
  const natReso = 100 - norm(nat.unresolvedPct, Math.min(...allUnres), Math.max(...allUnres));
  const natFarm = norm(nat.farmers, 0, Math.max(...Object.values(regionStats).map(s => s.farmers)));

  const sortBy = (col) => setSort(s => ({ col, dir: s.col === col && s.dir === 'desc' ? 'asc' : 'desc' }));
  const sortArrow = (col) => sort.col !== col ? '' : (sort.dir === 'asc' ? '↑' : '↓');

  return (
    <div className="page" style={{ maxWidth: '100%' }}>
      <div className="page-head">
        <div>
          <div className="page-crumbs">
            <span>Asosiy</span><span>/</span><span style={{ color: 'var(--ink-2)' }}>Geografiya</span>
            <span>/</span><span style={{ color: 'var(--ink-2)' }}>{sel.uz}</span>
          </div>
          <h1 className="page-title">Geografiya<span className="ru">География · 14 viloyat tahlili</span></h1>
        </div>
        <div className="page-actions">
          <button className="btn"><Icon name="download" size={12} /> PNG xarita</button>
          <button className="btn btn-primary"><Icon name="doc" size={12} /> Hududiy hisobot</button>
        </div>
      </div>

      {/* Map + side panel */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 380px', gap: 16, marginBottom: 16, alignItems: 'start' }}>
       <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
        <Panel
          title="Oʻzbekiston intercaktiv xaritasi"
          sub={`14 viloyat · ${MAP_LAYERS.find(l => l.id === layer).uz}`}
          num="01"
          actions={
            <>
              <div className="seg">
                {MAP_LAYERS.map(l => (
                  <button key={l.id} className={layer === l.id ? 'on' : ''} onClick={() => setLayer(l.id)}>{l.uz}</button>
                ))}
              </div>
              <button className="btn btn-ghost btn-sm"><Icon name="download" size={12} /></button>
              <button className="btn btn-ghost btn-sm"><Icon name="expand" size={12} /></button>
            </>
          }
        >
          <div style={{ background: 'var(--bg)', padding: 6, borderRadius: 4 }}>
            <UzMap
              values={layerValues}
              height={420}
              colorFn={layerColor}
              selected={selected}
              onClick={setSelected}
              showLabels={true}
              layerLabel=""
            />
          </div>

          {/* Layer extremes — top 5 + bottom 5 by current layer */}
          <LayerExtremes layer={layer} values={layerValues} regions={REGIONS} />

          {/* Legend */}
          <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px solid var(--line)' }}>
            {layer === 'dominant' ? (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px 12px', fontSize: 10.5 }}>
                {TOPICS.map(t => (
                  <span key={t.id} style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                    <span style={{ width: 10, height: 10, background: t.color, borderRadius: 2 }} />
                    {t.uz}
                  </span>
                ))}
              </div>
            ) : (
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, fontSize: 10.5, color: 'var(--ink-3)' }}>
                <span>{layer === 'sentiment' ? 'salbiy' : 'past'}</span>
                <div style={{ flex: 1, height: 8, borderRadius: 1, background: layer === 'sentiment'
                  ? 'linear-gradient(90deg, oklch(0.55 0.13 25), oklch(0.92 0.02 30), oklch(0.55 0.10 155))'
                  : layer === 'unresolved' ? 'linear-gradient(90deg, oklch(0.92 0.02 30), oklch(0.55 0.14 30))'
                  : layer === 'response'   ? 'linear-gradient(90deg, oklch(0.92 0.02 75), oklch(0.55 0.13 75))'
                  : 'linear-gradient(90deg, oklch(0.92 0.02 195), oklch(0.55 0.12 195))'
                }} />
                <span>{layer === 'sentiment' ? 'ijobiy' : 'yuqori'}</span>
                <span className="mono" style={{ marginLeft: 8, color: 'var(--ink-4)' }}>
                  {layer === 'density' ? `${formatNum(minT)} – ${formatNum(maxT)}` :
                   layer === 'sentiment' ? `${Math.min(...Object.values(layerValues)).toFixed(0)}% – ${Math.max(...Object.values(layerValues)).toFixed(0)}%` :
                   layer === 'unresolved' ? `${Math.min(...allUnres).toFixed(1)}% – ${Math.max(...allUnres).toFixed(1)}%` :
                   `${Math.min(...allResp)}–${Math.max(...allResp)} daq`}
                </span>
              </div>
            )}
          </div>
        </Panel>

        <RegionalInsightsStrip regions={REGIONS} regionStats={regionStats} nat={nat} />

        <NationalPulse />
       </div>

        {/* Region side panel */}
        <div className="panel" style={{ overflow: 'hidden', alignSelf: 'start' }}>
          <div style={{ padding: 18, borderBottom: '1px solid var(--line)', background: 'var(--bg-sunken)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <div>
                <div style={{ fontSize: 10.5, fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>VILOYAT</div>
                <div style={{ fontFamily: 'var(--font-serif)', fontSize: 20, fontWeight: 500, letterSpacing: '-0.01em', marginTop: 2 }}>{sel.uz}</div>
                <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{sel.ru} · <span className="mono">{sel.code}</span></div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div className="mono" style={{ fontSize: 11, color: 'var(--ink-2)' }}>aholi</div>
                <div className="mono" style={{ fontSize: 14, fontWeight: 500 }}>{sel.pop}M</div>
              </div>
            </div>
          </div>

          {/* KPIs */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 1, background: 'var(--line)', borderBottom: '1px solid var(--line)' }}>
            <MiniKpi label="Murojaat" value={formatNum(selStats.total)} hint={`milliy: ${formatNum(Math.round(nat.total))}`} vs={selStats.total - nat.total} />
            <MiniKpi label="Ochiq" value={formatNum(selStats.open)} hint={`milliy: ${formatNum(Math.round(nat.open))}`} vs={selStats.open - nat.open} inverse />
            <MiniKpi label="Shoshilinch" value={formatNum(selStats.urgent)} hint={`milliy: ${formatNum(Math.round(nat.urgent))}`} vs={selStats.urgent - nat.urgent} inverse />
            <MiniKpi label="Javob (daq)" value={selStats.avgResp} hint={`milliy: ${nat.avgResp.toFixed(0)}`} vs={selStats.avgResp - nat.avgResp} inverse />
            <MiniKpi label="Sentiment" value={`${selStats.sentScore >= 0 ? '+' : ''}${selStats.sentScore.toFixed(1)}`} hint={`milliy: ${nat.sentScore.toFixed(1)}`} vs={selStats.sentScore - nat.sentScore} />
            <MiniKpi label="Fermerlar" value={selStats.farmers} hint={`milliy: ${nat.farmers.toFixed(0)}`} vs={selStats.farmers - nat.farmers} />
          </div>

          {/* Top 5 topics */}
          <div style={{ padding: 14, borderBottom: '1px solid var(--line)' }}>
            <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 8 }}>Top 5 mavzu</div>
            <div>
              {top5.map((t, i) => {
                const max = top5[0].n;
                return (
                  <div key={t.topic.id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '4px 0' }}>
                    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 9.5, color: 'var(--ink-4)', width: 14 }}>{i + 1}</span>
                    <TopicMark topicId={t.topic.id} size={14} />
                    <span style={{ fontSize: 11.5, flex: 1 }}>{t.topic.uz}</span>
                    <div style={{ width: 70 }}><MiniBar value={t.n} max={max} color={t.topic.color} height={5} /></div>
                    <span className="mono" style={{ fontSize: 11, width: 36, textAlign: 'right' }}>{t.n}</span>
                  </div>
                );
              })}
            </div>
          </div>

          {/* Top farmers */}
          <div style={{ padding: 14, borderBottom: '1px solid var(--line)' }}>
            <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 8 }}>Eng faol fermerlar</div>
            {regionFarmers.map(f => (
              <div key={f.id} style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '4px 0', fontSize: 11.5 }}>
                <Avatar name={f.name} size={20} />
                <span style={{ flex: 1 }}>{f.name}</span>
                <span className="mono" style={{ color: 'var(--ink-3)', fontSize: 10.5 }}>{f.inquiries} murojaat</span>
              </div>
            ))}
          </div>

          {/* Time series */}
          <div style={{ padding: 14, borderBottom: '1px solid var(--line)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6 }}>
              <span style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--ink-3)' }}>30 kunlik hajm</span>
              <span style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--ink-4)' }}>jami {regionTime.reduce((a, b) => a + b, 0)}</span>
            </div>
            <Sparkline data={regionTime} width={344} height={42} color="var(--accent)" fill strokeWidth={1.5} />
          </div>

          {/* Radar */}
          <div style={{ padding: 14, paddingTop: 10 }}>
            <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 6 }}>
              Milliy o‘rtacha bilan taqqoslash
            </div>
            <div style={{ display: 'flex', justifyContent: 'center' }}>
              <Radar
                size={220}
                max={100}
                axes={radarAxes}
                series={[
                  { label: 'Milliy', values: [natReg, natUrg, natSent, natResp, natReso, natFarm], color: 'var(--ink-4)', dashed: true, fillOpacity: 0.08 },
                  { label: sel.uz, values: [reg, urg, sent, resp, reso, farm], color: 'var(--accent)' },
                ]}
              />
            </div>
            <div style={{ display: 'flex', justifyContent: 'center', gap: 16, fontSize: 10.5, marginTop: 4 }}>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                <span style={{ width: 16, height: 2, background: 'var(--ink-4)', borderTop: '1px dashed' }} />Milliy o'rtacha
              </span>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
                <span style={{ width: 16, height: 2, background: 'var(--accent)' }} />{sel.uz}
              </span>
            </div>
          </div>
        </div>
      </div>

      {/* Leaderboard + bubble chart */}
      <div className="grid-2-1" style={{ marginBottom: 16 }}>
        <Panel
          title="Viloyatlar reytingi"
          sub="ustun nomini bosing → saralash"
          num="04"
          body={false}
        >
          <table className="tbl">
            <thead>
              <tr>
                <th style={{ width: 28, textAlign: 'right' }}>#</th>
                <th onClick={() => sortBy('uz')} style={{ cursor: 'pointer' }}>Viloyat {sortArrow('uz')}</th>
                <th onClick={() => sortBy('total')} style={{ cursor: 'pointer', width: 160 }}>Hajm {sortArrow('total')}</th>
                <th onClick={() => sortBy('open')} style={{ cursor: 'pointer', width: 140 }}>Ochiq {sortArrow('open')}</th>
                <th onClick={() => sortBy('urgent')} style={{ cursor: 'pointer', width: 110 }}>Shosh. {sortArrow('urgent')}</th>
                <th onClick={() => sortBy('sentScore')} style={{ cursor: 'pointer', width: 130 }}>Sent. {sortArrow('sentScore')}</th>
                <th onClick={() => sortBy('avgResp')} style={{ cursor: 'pointer', width: 110 }}>Javob {sortArrow('avgResp')}</th>
                <th onClick={() => sortBy('unresolvedPct')} style={{ cursor: 'pointer', width: 130 }}>Hal etilmagan {sortArrow('unresolvedPct')}</th>
                <th onClick={() => sortBy('farmers')} style={{ cursor: 'pointer', width: 90 }}>Fermer {sortArrow('farmers')}</th>
              </tr>
            </thead>
            <tbody>
              {lb.map((r, i) => (
                <tr key={r.id} style={{ cursor: 'pointer', background: selected === r.id ? 'var(--bg-sunken)' : '' }} onClick={() => setSelected(r.id)}>
                  <td style={{ textAlign: 'right', fontFamily: 'var(--font-mono)', color: 'var(--ink-4)', fontSize: 10 }}>{i + 1}</td>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <span className="mono" style={{ fontSize: 9.5, color: 'var(--ink-4)', background: 'var(--bg-sunken)', padding: '1px 4px', borderRadius: 2 }}>{r.code}</span>
                      <span style={{ fontSize: 11.5, fontWeight: selected === r.id ? 600 : 400 }}>{r.uz}</span>
                    </div>
                  </td>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <div style={{ flex: 1 }}><MiniBar value={r.total} max={maxT} color="var(--accent)" height={5} /></div>
                      <span className="mono" style={{ fontSize: 11, width: 44, textAlign: 'right' }}>{formatNum(r.total)}</span>
                    </div>
                  </td>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <div style={{ flex: 1 }}><MiniBar value={r.open} max={Math.max(...lb.map(x => x.open))} color="var(--amber)" height={5} /></div>
                      <span className="mono" style={{ fontSize: 11, width: 36, textAlign: 'right' }}>{r.open}</span>
                    </div>
                  </td>
                  <td>
                    <span className={`chip ${r.urgent > nat.urgent * 1.2 ? 'chip-rose' : 'chip-'}`} style={{ fontSize: 10 }}>{r.urgent}</span>
                  </td>
                  <td>
                    <span className="mono" style={{ fontSize: 11, color: r.sentScore >= 0 ? 'var(--jade)' : 'var(--rose)' }}>
                      {r.sentScore >= 0 ? '+' : ''}{r.sentScore.toFixed(1)}
                    </span>
                  </td>
                  <td>
                    <span className="mono" style={{ fontSize: 11, color: r.avgResp < nat.avgResp ? 'var(--jade)' : 'var(--ink-2)' }}>
                      {r.avgResp} daq
                    </span>
                  </td>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <div style={{ flex: 1 }}><MiniBar value={r.unresolvedPct} max={Math.max(...allUnres)} color="var(--rose)" height={5} /></div>
                      <span className="mono" style={{ fontSize: 10.5, width: 38, textAlign: 'right' }}>{r.unresolvedPct.toFixed(1)}%</span>
                    </div>
                  </td>
                  <td className="mono" style={{ fontSize: 11 }}>{r.farmers}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Panel>

        <Panel title="Hajm × Sentiment" sub="14 viloyat · diqqat: yuqori hajm + salbiy" num="05">
          <SentimentQuadrants data={bubbleData} />
        </Panel>
      </div>
    </div>
  );
}

function MiniKpi({ label, value, hint, vs, inverse }) {
  const positive = inverse ? vs < 0 : vs > 0;
  return (
    <div style={{ padding: '10px 12px', background: 'var(--panel)' }}>
      <div style={{ fontSize: 9.5, color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{label}</div>
      <div className="mono" style={{ fontSize: 18, fontWeight: 500, letterSpacing: '-0.02em', marginTop: 1 }}>{value}</div>
      <div style={{ fontSize: 9.5, color: 'var(--ink-4)', display: 'flex', justifyContent: 'space-between' }}>
        <span className="mono">{hint}</span>
        {vs !== 0 && (
          <span className="mono" style={{ color: positive ? 'var(--jade)' : 'var(--rose)' }}>
            {vs > 0 ? '↑' : '↓'} {typeof vs === 'number' ? Math.abs(vs).toFixed(vs % 1 === 0 ? 0 : 1) : ''}
          </span>
        )}
      </div>
    </div>
  );
}

function NationalPulse() {
  // Last 30 days of country-wide totals, from the API.
  const { data } = useApi('/api/stats/by-day?days=30', { pollMs: 30000 });
  // Bucket API rows (per topic per day) → daily totals
  const totals = useMemo(() => {
    const items = data?.items || [];
    const today = new Date();
    const keys = [];
    for (let i = 29; i >= 0; i--) {
      const d = new Date(today.getTime() - i * 86400000);
      keys.push(d.toISOString().slice(0, 10));
    }
    const sumByDay = {};
    items.forEach(r => { sumByDay[r.day] = (sumByDay[r.day] || 0) + r.n; });
    return keys.map(k => sumByDay[k] || 0);
  }, [data]);
  const dayDates = useMemo(() => {
    const today = new Date();
    return Array.from({ length: 30 }, (_, i) => new Date(today.getTime() - (29 - i) * 86400000));
  }, []);
  const total = totals.reduce((a, b) => a + b, 0);
  const peakIdx = totals.indexOf(Math.max(...totals));
  const dipIdx  = totals.indexOf(Math.min(...totals));
  const formatDay = (i) => {
    const d = dayDates[i];
    return `${String(d.getDate()).padStart(2, '0')}.${String(d.getMonth() + 1).padStart(2, '0')}`;
  };
  const half = Math.floor(totals.length / 2);
  const recent = totals.slice(half).reduce((a, b) => a + b, 0);
  const prior  = totals.slice(0, half).reduce((a, b) => a + b, 0) || 1;
  const delta  = ((recent - prior) / prior) * 100;
  const up = delta >= 0;

  return (
    <Panel title="Milliy pulse" sub="14 viloyat jami · 30 kun" num="03">
      <div style={{ display: 'grid', gridTemplateColumns: '160px 1fr', gap: 18, alignItems: 'center' }}>
        <div>
          <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-4)' }}>
            Jami 30 kun
          </div>
          <div className="mono" style={{ fontSize: 24, fontWeight: 500, marginTop: 2 }}>{formatNum(total)}</div>
          <div style={{ fontSize: 11, color: up ? 'oklch(0.45 0.10 155)' : 'oklch(0.50 0.14 25)', fontFamily: 'var(--font-mono)', fontWeight: 600, marginTop: 2 }}>
            {up ? '↑' : '↓'} {Math.abs(delta).toFixed(1)}% <span style={{ color: 'var(--ink-4)', fontWeight: 400 }}>· oxirgi 15 kun</span>
          </div>
        </div>
        <div>
          <Sparkline data={totals} width={520} height={48} color="var(--accent)" fill strokeWidth={1.5} dot />
        </div>
      </div>
      <div style={{ marginTop: 12, paddingTop: 10, borderTop: '1px solid var(--line)', display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 20, fontSize: 11 }}>
        <div>
          <div style={{ fontSize: 9.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Peak</div>
          <div className="mono" style={{ fontWeight: 500, marginTop: 2 }}>{formatNum(totals[peakIdx])} <span style={{ color: 'var(--ink-4)', fontWeight: 400 }}>· {formatDay(peakIdx)}</span></div>
        </div>
        <div>
          <div style={{ fontSize: 9.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Dip</div>
          <div className="mono" style={{ fontWeight: 500, marginTop: 2 }}>{formatNum(totals[dipIdx])} <span style={{ color: 'var(--ink-4)', fontWeight: 400 }}>· {formatDay(dipIdx)}</span></div>
        </div>
        <div>
          <div style={{ fontSize: 9.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: '0.06em' }}>Oʻrtacha</div>
          <div className="mono" style={{ fontWeight: 500, marginTop: 2 }}>{Math.round(total / totals.length)} <span style={{ color: 'var(--ink-4)', fontWeight: 400 }}>· /kun</span></div>
        </div>
      </div>
    </Panel>
  );
}

function RegionalInsightsStrip({ regions, regionStats, nat }) {
  // Card 1: most active region this week (by week count)
  // Card 2: biggest week-over-week mover (signed)
  // Card 3: worst sentiment region
  // Card 4: fastest avg response region
  const byWeek = [...regions].sort((a, b) => regionStats[b.id].week - regionStats[a.id].week);
  const mostActive = byWeek[0];

  const movers = regions.map(r => {
    const s = regionStats[r.id];
    const prev = s.weekPrev || 0;
    const delta = prev > 0 ? ((s.week - prev) / prev) * 100 : s.week > 0 ? 100 : 0;
    return { r, delta, abs: Math.abs(delta) };
  }).sort((a, b) => b.abs - a.abs);
  const biggestMover = movers[0];

  const worstSent = [...regions].sort((a, b) => regionStats[a.id].sentScore - regionStats[b.id].sentScore)[0];
  const fastestResp = [...regions].sort((a, b) => regionStats[a.id].avgResp - regionStats[b.id].avgResp)[0];

  const cards = [
    {
      title: 'Bu hafta eng faol',
      value: mostActive.code,
      subValue: `${formatNum(regionStats[mostActive.id].week)} ta`,
      sub: mostActive.uz,
      tone: 'accent',
    },
    {
      title: 'Eng katta o‘zgarish',
      value: `${biggestMover.delta >= 0 ? '+' : ''}${biggestMover.delta.toFixed(0)}%`,
      subValue: biggestMover.r.code,
      sub: `${biggestMover.r.uz} · bu hafta vs o‘tgan`,
      tone: biggestMover.delta >= 0 ? 'jade' : 'rose',
    },
    {
      title: 'Eng salbiy sentiment',
      value: `${regionStats[worstSent.id].sentScore >= 0 ? '+' : ''}${regionStats[worstSent.id].sentScore.toFixed(1)}`,
      subValue: worstSent.code,
      sub: `${worstSent.uz} · milliy: ${nat.sentScore.toFixed(1)}`,
      tone: 'rose',
    },
    {
      title: 'Eng tez javob',
      value: `${regionStats[fastestResp.id].avgResp}`,
      subValue: 'daq',
      sub: `${fastestResp.r ? fastestResp.r.code : fastestResp.code} · ${fastestResp.uz}`,
      tone: 'jade',
    },
  ];

  const toneColor = {
    accent: 'var(--accent-ink)',
    jade:   'oklch(0.45 0.10 155)',
    rose:   'oklch(0.50 0.14 25)',
  };

  return (
    <Panel title="Bugungi hududiy xulosa" sub="14 viloyat boʻyicha 4 ko‘rsatkich" num="02">
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 1, background: 'var(--line)' }}>
        {cards.map((c, i) => (
          <div key={i} style={{ background: 'var(--panel)', padding: '12px 14px' }}>
            <div style={{ fontSize: 9.5, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--ink-4)' }}>
              {c.title}
            </div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginTop: 4 }}>
              <span className="mono" style={{ fontSize: 22, fontWeight: 500, color: toneColor[c.tone] }}>{c.value}</span>
              {c.subValue && (
                <span className="mono" style={{ fontSize: 11, color: 'var(--ink-3)' }}>{c.subValue}</span>
              )}
            </div>
            <div style={{ fontSize: 10.5, color: 'var(--ink-3)', marginTop: 4, lineHeight: 1.3 }}>
              {c.sub}
            </div>
          </div>
        ))}
      </div>
    </Panel>
  );
}

function LayerExtremes({ layer, values, regions }) {
  // Sort regions by current layer value
  const labels = {
    density:    { unit: 'ta', best: 'Eng faol',  worst: 'Eng tinch',  invert: false },
    sentiment:  { unit: '%',  best: 'Eng ijobiy', worst: 'Eng salbiy', invert: false },
    unresolved: { unit: '%',  best: 'Yaxshi',     worst: 'Diqqat',     invert: true },
    response:   { unit: 'daq',best: 'Tez',        worst: 'Sekin',      invert: true },
    dominant:   null, // skip — categorical, not numeric
  };
  const cfg = labels[layer];
  if (!cfg) return null;

  const sorted = regions
    .map(r => ({ r, v: values[r.id] ?? 0 }))
    .filter(d => Number.isFinite(d.v))
    .sort((a, b) => cfg.invert ? a.v - b.v : b.v - a.v);
  const top = sorted.slice(0, 5);
  const bot = sorted.slice(-5).reverse();
  const max = Math.max(1, ...sorted.map(d => Math.abs(d.v)));

  const Row = ({ d, rank, tone }) => {
    const pct = Math.abs(d.v) / max;
    const fmt = (v) => layer === 'density' ? formatNum(v) : layer === 'response' ? `${Math.round(v)}` : `${v.toFixed(1)}`;
    return (
      <div style={{
        display: 'grid',
        gridTemplateColumns: '20px 38px 1fr 56px',
        gap: 8,
        alignItems: 'center',
        padding: '4px 0',
      }}>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--ink-4)' }}>{rank}</span>
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10.5, fontWeight: 600, color: 'var(--ink)' }}>{d.r.code}</span>
        <div style={{ position: 'relative', height: 6, background: 'oklch(0.96 0.004 90)', borderRadius: 1, overflow: 'hidden' }}>
          <div style={{
            position: 'absolute', left: 0, top: 0, bottom: 0,
            width: `${pct * 100}%`,
            background: tone === 'good' ? 'oklch(0.55 0.10 155)' : tone === 'bad' ? 'oklch(0.58 0.14 25)' : 'var(--accent)',
            opacity: 0.75,
          }} />
        </div>
        <span className="mono" style={{ fontSize: 10.5, textAlign: 'right', color: 'var(--ink-2)' }}>
          {fmt(d.v)} <span style={{ color: 'var(--ink-4)', fontSize: 9 }}>{cfg.unit}</span>
        </span>
      </div>
    );
  };

  return (
    <div style={{ marginTop: 12, paddingTop: 12, borderTop: '1px solid var(--line)', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24 }}>
      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
          <span style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'oklch(0.45 0.10 155)' }}>
            ↑ {cfg.best} 5
          </span>
          <span style={{ fontSize: 9.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-4)' }}>viloyat</span>
        </div>
        {top.map((d, i) => <Row key={d.r.id} d={d} rank={String(i + 1).padStart(2, '0')} tone="good" />)}
      </div>
      <div>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
          <span style={{ fontSize: 10, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'oklch(0.50 0.14 25)' }}>
            ↓ {cfg.worst} 5
          </span>
          <span style={{ fontSize: 9.5, fontFamily: 'var(--font-mono)', color: 'var(--ink-4)' }}>viloyat</span>
        </div>
        {bot.map((d, i) => <Row key={d.r.id} d={d} rank={String(regions.length - i).padStart(2, '0')} tone="bad" />)}
      </div>
    </div>
  );
}

function SentimentQuadrants({ data }) {
  const volumes = data.map(d => d.x).slice().sort((a, b) => a - b);
  const medianVol = volumes[Math.floor(volumes.length / 2)];
  const cells = {
    highPos: { title: 'Yuqori hajm + Ijobiy', sub: 'sogʻlom faollik', tone: 'jade',  items: [] },
    highNeg: { title: 'Yuqori hajm + Salbiy', sub: 'diqqat talab',    tone: 'rose',  items: [] },
    lowPos:  { title: 'Past hajm + Ijobiy',   sub: 'tinch hudud',     tone: 'muted', items: [] },
    lowNeg:  { title: 'Past hajm + Salbiy',   sub: 'kuzatuvda',       tone: 'amber', items: [] },
  };
  data.forEach(d => {
    const hi = d.x >= medianVol;
    const pos = d.y >= 0;
    const key = hi && pos ? 'highPos' : hi && !pos ? 'highNeg' : !hi && pos ? 'lowPos' : 'lowNeg';
    cells[key].items.push(d);
  });
  // Sort: highNeg by most negative + volume; others by volume desc
  cells.highNeg.items.sort((a, b) => (a.y - b.y) || (b.x - a.x));
  cells.highPos.items.sort((a, b) => b.x - a.x);
  cells.lowPos.items.sort((a, b) => b.x - a.x);
  cells.lowNeg.items.sort((a, b) => (a.y - b.y) || (b.x - a.x));

  const toneStyles = {
    jade:  { border: 'oklch(0.85 0.06 155)', accent: 'oklch(0.45 0.10 155)', bg: 'oklch(0.97 0.018 155)' },
    rose:  { border: 'oklch(0.84 0.07 25)',  accent: 'oklch(0.50 0.14 25)',  bg: 'oklch(0.975 0.018 25)'  },
    amber: { border: 'oklch(0.85 0.06 80)',  accent: 'oklch(0.55 0.12 80)',  bg: 'oklch(0.98 0.018 80)'   },
    muted: { border: 'var(--line)',           accent: 'var(--ink-3)',        bg: 'var(--bg-sunken)'        },
  };

  const Cell = ({ keyName }) => {
    const c = cells[keyName];
    const t = toneStyles[c.tone];
    const attention = keyName === 'highNeg';
    return (
      <div style={{
        background: t.bg,
        border: `1px solid ${t.border}`,
        borderRadius: 6,
        padding: '12px 14px',
        display: 'flex',
        flexDirection: 'column',
        minHeight: 150,
      }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 10 }}>
          <div>
            <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', color: t.accent, display: 'inline-flex', alignItems: 'center', gap: 6 }}>
              {attention && <span style={{ width: 6, height: 6, background: t.accent, borderRadius: '50%' }} />}
              {c.title}
            </div>
            <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--ink-4)', marginTop: 2 }}>{c.sub}</div>
          </div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--ink-3)' }}>{c.items.length} viloyat</div>
        </div>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
          {c.items.length === 0 && (
            <span style={{ fontSize: 11, color: 'var(--ink-4)', fontStyle: 'italic' }}>—</span>
          )}
          {c.items.map(it => (
            <div key={it.label} title={it.fullLabel} style={{
              display: 'inline-flex',
              alignItems: 'center',
              gap: 8,
              padding: '6px 10px',
              background: 'var(--panel)',
              border: '1px solid var(--line)',
              borderRadius: 4,
              fontFamily: 'var(--font-mono)',
              fontSize: 11,
            }}>
              <span style={{ width: 6, height: 6, background: it.color, borderRadius: 1 }} />
              <span style={{ fontWeight: 600, color: 'var(--ink)' }}>{it.label}</span>
              <span style={{ color: t.accent, fontWeight: 600 }}>
                {it.y >= 0 ? '+' : ''}{it.y.toFixed(0)}
              </span>
              <span style={{ color: 'var(--ink-4)' }}>· {formatNum(it.x)}</span>
            </div>
          ))}
        </div>
      </div>
    );
  };

  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <Cell keyName="highPos" />
        <Cell keyName="highNeg" />
        <Cell keyName="lowPos"  />
        <Cell keyName="lowNeg"  />
      </div>
      <div style={{
        marginTop: 12, paddingTop: 10, borderTop: '1px solid var(--line)',
        display: 'flex', justifyContent: 'space-between', fontSize: 10.5, color: 'var(--ink-4)', fontFamily: 'var(--font-mono)',
      }}>
        <span>chip: <span style={{ color: 'var(--ink-2)' }}>kod · sentiment · hajm</span></span>
        <span>hajm median: <span style={{ color: 'var(--ink-2)' }}>{formatNum(medianVol)}</span></span>
      </div>
    </div>
  );
}

window.ScreenGeo = ScreenGeo;
