/* global React, Units */
// =========================================================
// Instruments for weather enthusiasts — shared look with the station page
// (/ms): 24 h wind rose, wall barometer with a "set hand" (pressure 3 h ago)
// and 24 h extremes. Data come from station.raw (every API field, last 24 h).
// Wrapped in an IIFE so helpers don't leak into the shared global scope.
// =========================================================
(function () {
  const isNum = (v) => v != null && !isNaN(v);
  const fmt = (v, d = 1) => window.fmtNum(v, d);
  // Bearing 0° = up (north), clockwise — same convention as the dial labels.
  const polar = (cx, cy, deg, r) => [cx + r * Math.sin(deg * Math.PI / 180), cy - r * Math.cos(deg * Math.PI / 180)];
  const timeOf = (r) => window.StationData.parseDatum(r.Datum);
  const last24 = (station) => {
    const cut = Date.now() - 24 * 3600e3;
    return (station?.raw || []).filter((r) => r.Datum && timeOf(r).getTime() >= cut);
  };
  const hm = (d) => d ? d.toLocaleTimeString('cs-CZ', { hour: '2-digit', minute: '2-digit' }) : '—';
  // "14:20" today, "včera 22:10" otherwise.
  const when = (d) => {
    if (!d) return '—';
    const day = (x) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime();
    return day(d) === day(new Date()) ? hm(d) : 'včera ' + hm(d);
  };
  const windU = (ms) => (window.Units ? window.Units.wind(ms) : ms);
  const windL = () => (window.Units ? window.Units.windLabel() : 'm/s');
  const Empty = ({ text }) => <div className="ins-empty"><i className="bi bi-hourglass-split"></i>{text}</div>;

  // ── Wind rose ─────────────────────────────────────────────
  // 16 sectors; each petal is stacked by speed class (Beaufort 1 | 2 | 3 | 4 | 5+),
  // one hue (accent) in rising opacity. Triangle on the rim = where it blows from now.
  const CLASSES = [1.6, 3.4, 5.5, 8.0];
  const OPAC = [0.28, 0.45, 0.62, 0.8, 1];
  const DIRS16 = ['S', 'SSV', 'SV', 'VSV', 'V', 'VJV', 'JV', 'JJV', 'J', 'JJZ', 'JZ', 'ZJZ', 'Z', 'ZSZ', 'SZ', 'SSZ'];

  window.WindRoseWidget = function WindRoseWidget({ station }) {
    const recs = last24(station);
    const sectors = Array.from({ length: 16 }, () => ({ cls: [0, 0, 0, 0, 0], n: 0, sum: 0, max: 0 }));
    let calm = 0, total = 0;
    for (const r of recs) {
      const v = r.Vitr, d = r.VitrSmer;
      if (!isNum(v)) continue;
      total++;
      if (v < 0.3 || !isNum(d)) { calm++; continue; }
      const s = sectors[Math.round((((d % 360) + 360) % 360) / 22.5) % 16];
      let c = 0;
      while (c < CLASSES.length && v >= CLASSES[c]) c++;
      s.cls[c]++; s.n++; s.sum += v; s.max = Math.max(s.max, isNum(r.VitrNarazy) ? r.VitrNarazy : v);
    }
    if (!total) return <Empty text="Čekám na data ze stanice…" />;
    const dirNow = station?.latest?.VitrSmer;
    const cx = 100, cy = 100, r0 = 13, R = 78;
    const maxF = Math.max(0.01, ...sectors.map((s) => s.n / total));
    const rad = (f) => r0 + (f / maxF) * (R - r0);
    const half = 11.25 - 1.4;
    const arc = (a1, a2, ri, ro) => {
      const [x1, y1] = polar(cx, cy, a1, ri), [x2, y2] = polar(cx, cy, a1, ro);
      const [x3, y3] = polar(cx, cy, a2, ro), [x4, y4] = polar(cx, cy, a2, ri);
      return `M${x1},${y1} L${x2},${y2} A${ro},${ro} 0 0 1 ${x3},${y3} L${x4},${y4} A${ri},${ri} 0 0 0 ${x1},${y1} Z`;
    };
    const prevailing = sectors.reduce((b, s, i) => (s.n > sectors[b].n ? i : b), 0);
    const u = windL();
    const lim = (v) => fmt(windU(v), u === 'm/s' ? 1 : 0);
    return (
      <div className="ins-rose">
        <svg viewBox="0 0 200 200" className="ins-rose-svg" role="img"
             aria-label={`Větrná růžice za 24 h, převládá ${DIRS16[prevailing]}`}>
          {[0.25, 0.5, 0.75, 1].map((k) => (
            <circle key={k} cx={cx} cy={cy} r={rad(k * maxF)} fill="none" stroke="var(--border)" strokeWidth="1" />
          ))}
          {[0, 45, 90, 135].map((a) => {
            const [x1, y1] = polar(cx, cy, a, R), [x2, y2] = polar(cx, cy, a + 180, R);
            return <line key={a} x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--border)" strokeWidth="1" />;
          })}
          <text x={polar(cx, cy, 22.5, R)[0] + 2} y={polar(cx, cy, 22.5, R)[1] - 2} fontSize="7.5"
                fill="var(--muted)" fontFamily="var(--mono)" opacity="0.7">{Math.round(maxF * 100)} %</text>
          {sectors.map((s, i) => {
            if (!s.n) return null;
            const a = i * 22.5;
            let cum = 0;
            return (
              <g key={i}>
                <title>{`${DIRS16[i]}: ${Math.round(s.n / total * 100)} % času · průměr ${fmt(windU(s.sum / s.n), 1)} · max náraz ${fmt(windU(s.max), 1)} ${u}`}</title>
                {s.cls.map((cnt, c) => {
                  if (!cnt) return null;
                  const fIn = cum / total; cum += cnt; const fOut = cum / total;
                  let ri = rad(fIn), ro = rad(fOut);
                  if (ro - ri > 2.5) { ri += c ? 0.75 : 0; ro -= 0.75; }
                  return <path key={c} d={arc(a - half, a + half, ri, ro)} fill="var(--accent)" fillOpacity={OPAC[c]} />;
                })}
              </g>
            );
          })}
          <circle cx={cx} cy={cy} r={r0 - 2} fill="var(--card-strong)" stroke="var(--border)" strokeWidth="1" />
          {calm / total >= 0.03 && (
            <text x={cx} y={cy + 2.5} textAnchor="middle" fontSize="7" fill="var(--muted)" fontFamily="var(--mono)">
              {Math.round(calm / total * 100)}%<title>Bezvětří (pod 0,3 m/s)</title>
            </text>
          )}
          {[['S', 0], ['V', 90], ['J', 180], ['Z', 270]].map(([l, a]) => {
            const [x, y] = polar(cx, cy, a, R + 12);
            return <text key={l} x={x} y={y + 3.5} textAnchor="middle" fontSize="10" fontWeight="600"
                         fill={l === 'S' ? 'var(--accent)' : 'var(--muted)'} fontFamily="var(--mono)">{l}</text>;
          })}
          {isNum(dirNow) && !(isNum(station?.latest?.Vitr) && station.latest.Vitr < 0.3) && (() => {
            const [tx, ty] = polar(cx, cy, dirNow, R + 3);
            const [lx, ly] = polar(cx, cy, dirNow - 7, R + 11), [rx, ry] = polar(cx, cy, dirNow + 7, R + 11);
            const [ix, iy] = polar(cx, cy, dirNow, r0);
            return (
              <g>
                <line x1={tx} y1={ty} x2={ix} y2={iy} stroke="var(--accent)" strokeWidth="1.5" opacity=".5" />
                <path d={`M${tx},${ty} L${lx},${ly} L${rx},${ry} Z`} fill="var(--text)" stroke="var(--card-strong)" strokeWidth="1.5" />
                <title>{`Teď fouká od ${window.windDir ? window.windDir(dirNow) : ''} (${Math.round(dirNow)}°)`}</title>
              </g>
            );
          })()}
        </svg>
        <div className="ins-rose-foot">
          <span className="ins-rose-prev">převládá <b>{DIRS16[prevailing]}</b> · {Math.round(sectors[prevailing].n / total * 100)} %
            {calm / total >= 0.03 && <> · bezvětří {Math.round(calm / total * 100)} %</>}</span>
          <span className="ins-rose-legend" aria-hidden="true">
            {OPAC.map((op, c) => (
              <span key={c}><i style={{ background: 'var(--accent)', opacity: op }} />
                {c === 0 ? '<' + lim(CLASSES[0]) : (c === CLASSES.length ? '≥' : '') + lim(CLASSES[c - 1])}
              </span>
            ))}
            <span className="ins-unit">{u}</span>
          </span>
        </div>
      </div>
    );
  };

  // ── Barometer ─────────────────────────────────────────────
  // 950–1050 hPa, the old dial words, and a muted "set hand" showing the
  // pressure 3 h ago (on a real barometer you set it by hand).
  const B_MIN = 950, B_MAX = 1050, B_START = -120, B_SWEEP = 240;
  const WORDS = [[965, 'Bouřka'], [982, 'Déšť'], [1000, 'Proměnlivo'], [1018, 'Pěkně'], [1035, 'Sucho']];

  // Met Office tendency classes; under 0.5 hPa/3 h counts as steady (sensor noise).
  function tendency(d) {
    const a = Math.abs(d), verb = d > 0 ? 'stoupá' : 'klesá';
    if (a < 0.5) return { label: 'ustálený', icon: 'arrow-right' };
    const icon = d > 0 ? 'arrow-up-right' : 'arrow-down-right';
    if (a <= 1.5) return { label: 'pomalu ' + verb, icon };
    if (a <= 3.5) return { label: verb, icon };
    if (a <= 6) return { label: 'rychle ' + verb, icon };
    return { label: 'velmi rychle ' + verb, icon };
  }
  function valueAgo(recs, key, hours) {
    if (!recs.length) return null;
    const target = timeOf(recs[recs.length - 1]).getTime() - hours * 3600e3;
    let best = null, bd = Infinity;
    for (const r of recs) {
      if (!isNum(r[key])) continue;
      const d = Math.abs(timeOf(r).getTime() - target);
      if (d < bd) { bd = d; best = r[key]; }
    }
    return bd <= 10 * 60e3 ? best : null;
  }

  window.BarometerWidget = function BarometerWidget({ station }) {
    const recs = last24(station);
    const p = station?.latest?.TlakRel;
    if (!isNum(p)) return <Empty text="Čekám na tlak ze stanice…" />;
    const before = valueAgo(recs, 'TlakRel', 3);
    const first = recs.find((r) => isNum(r.TlakRel));
    const d24 = first ? p - first.TlakRel : null;
    const tr = isNum(before) ? tendency(p - before) : null;
    const cx = 100, cy = 96, R = 74;
    const ang = (v) => B_START + (Math.max(B_MIN, Math.min(B_MAX, v)) - B_MIN) / (B_MAX - B_MIN) * B_SWEEP;
    const ticks = [];
    for (let v = B_MIN; v <= B_MAX; v += 2) {
      const major = v % 10 === 0;
      const [x1, y1] = polar(cx, cy, ang(v), R), [x2, y2] = polar(cx, cy, ang(v), R - (major ? 7 : 3.5));
      ticks.push(<line key={v} x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--muted)" strokeWidth={major ? 1.2 : 0.7} opacity={major ? 0.85 : 0.4} />);
    }
    const needle = (v, len, w, stroke, op) => {
      const [x, y] = polar(cx, cy, ang(v), len), [bx, by] = polar(cx, cy, ang(v) + 180, 10);
      return <line x1={bx} y1={by} x2={x} y2={y} stroke={stroke} strokeWidth={w} strokeLinecap="round" opacity={op} />;
    };
    const arcPath = (a1, a2, r) => {
      const [x1, y1] = polar(cx, cy, a1, r), [x2, y2] = polar(cx, cy, a2, r);
      return `M${x1},${y1} A${r},${r} 0 ${Math.abs(a2 - a1) > 180 ? 1 : 0} ${a2 > a1 ? 1 : 0} ${x2},${y2}`;
    };
    const sgn = (v) => (v > 0 ? '+' : '') + fmt(v, 1);
    return (
      <div className="ins-baro">
        <svg viewBox="0 0 200 150" className="ins-baro-svg" role="img"
             aria-label={`Barometr ${fmt(p, 1)} hPa${isNum(before) ? `, před 3 h ${fmt(before, 1)} hPa` : ''}`}>
          <path d={arcPath(B_START, B_START + B_SWEEP, R)} fill="none" stroke="var(--border)" strokeWidth="1" />
          {ticks}
          {[960, 980, 1000, 1020, 1040].map((v) => {
            const [x, y] = polar(cx, cy, ang(v), R + 10);
            return <text key={v} x={x} y={y + 3} textAnchor="middle" fontSize="7.5" fill="var(--muted)" opacity=".75" fontFamily="var(--mono)">{v}</text>;
          })}
          {WORDS.map(([v, w]) => {
            const [x, y] = polar(cx, cy, ang(v), R - 19);
            return <text key={w} x={x} y={y + 3} textAnchor="middle" fontSize="7.5" fontStyle="italic" fill="var(--muted)" fontFamily="var(--serif)">{w}</text>;
          })}
          {isNum(before) && Math.abs(p - before) >= 0.3 && (
            <path d={arcPath(ang(before), ang(p), R - 11)} fill="none" stroke="var(--accent)" strokeWidth="3" strokeLinecap="round" opacity=".35" />
          )}
          {isNum(before) && needle(before, R - 9, 1.4, 'var(--muted)', 0.6)}
          {needle(p, R - 6, 2.2, 'var(--accent)', 1)}
          <circle cx={cx} cy={cy} r="5" fill="var(--accent)" stroke="var(--card-strong)" strokeWidth="2" />
          <text x={cx} y={cy + 30} textAnchor="middle" fontSize="17" fontWeight="600" fill="var(--text)" fontFamily="var(--sans)">{fmt(p, 1)}</text>
          <text x={cx} y={cy + 42} textAnchor="middle" fontSize="8" fill="var(--muted)" fontFamily="var(--mono)">hPa</text>
        </svg>
        <div className="ins-baro-foot">
          {tr && <span className="ins-trend"><i className={`bi bi-${tr.icon}`}></i>{tr.label} · {sgn(p - before)} hPa/3 h</span>}
          {isNum(d24) && <span className="ins-note">za 24 h {sgn(d24)} hPa</span>}
        </div>
      </div>
    );
  };

  // ── Extremes 24 h ─────────────────────────────────────────
  window.ExtremesWidget = function ExtremesWidget({ station }) {
    const recs = last24(station);
    if (!recs.length) return <Empty text="Čekám na data ze stanice…" />;
    const at = (key, cmp) => {
      let bi = -1;
      recs.forEach((r, i) => { const v = r[key]; if (isNum(v) && (bi < 0 || cmp(v, recs[bi][key]))) bi = i; });
      return bi;
    };
    const u = windL();
    const items = [];
    const tMax = at('TeplotaVnejsi', (a, b) => a > b), tMin = at('TeplotaVnejsi', (a, b) => a < b);
    if (tMax >= 0) items.push({ k: 'Nejtepleji', icon: 'thermometer-sun', v: `${fmt(recs[tMax].TeplotaVnejsi, 1)} °C`, t: timeOf(recs[tMax]) });
    if (tMin >= 0) items.push({ k: 'Nejchladněji', icon: 'thermometer-snow', v: `${fmt(recs[tMin].TeplotaVnejsi, 1)} °C`, t: timeOf(recs[tMin]) });
    const g = at('VitrNarazy', (a, b) => a > b);
    if (g >= 0) items.push({ k: 'Nejsilnější náraz', icon: 'speedometer2', v: `${fmt(windU(recs[g].VitrNarazy), 1)} ${u}${isNum(recs[g].VitrSmer) && window.windDir ? ' ' + window.windDir(recs[g].VitrSmer) : ''}`, t: timeOf(recs[g]) });
    const s = at('SlunZareni', (a, b) => a > b);
    if (s >= 0 && recs[s].SlunZareni > 0) items.push({ k: 'Nejvíc slunce', icon: 'brightness-high', v: `${fmt(recs[s].SlunZareni, 0)} W/m²`, t: timeOf(recs[s]) });
    const uv = at('UVindex', (a, b) => a > b);
    if (uv >= 0 && recs[uv].UVindex > 0) items.push({ k: 'Max UV', icon: 'sun', v: fmt(recs[uv].UVindex, 1), t: timeOf(recs[uv]) });
    const rr = at('calculatedRain', (a, b) => a > b);
    const sum = recs.reduce((a, r) => a + (r.calculatedRain > 0 ? r.calculatedRain : 0), 0);
    if (recs.some((r) => isNum(r.SrazkyDen))) {
      items.push(rr >= 0 && recs[rr].calculatedRain > 0
        ? { k: 'Srážky 24 h', icon: 'cloud-rain', v: `${fmt(sum, 1)} mm`, t: timeOf(recs[rr]), tl: `nejvíc ${fmt(recs[rr].calculatedRain * 12, 1)} mm/h` }
        : { k: 'Srážky 24 h', icon: 'cloud-rain', v: '0 mm', tl: 'nepršelo' });
    }
    const p = recs.filter((r) => isNum(r.TlakRel));
    if (p.length > 1) {
      const d = p[p.length - 1].TlakRel - p[0].TlakRel;
      items.push({ k: 'Tlak za 24 h', icon: 'arrows-collapse', v: `${d > 0 ? '+' : ''}${fmt(d, 1)} hPa`, tl: d > 1 ? 'stoupá' : d < -1 ? 'klesá' : 'beze změny' });
    }
    return (
      <div className="ins-ext">
        {items.map((it) => (
          <div className="ins-ext-item" key={it.k}>
            <span className="ins-ext-k" title={it.k}><i className={`bi bi-${it.icon}`}></i>{it.k}</span>
            <span className="ins-ext-v">{it.v}</span>
            <span className="ins-ext-t">{it.t ? when(it.t) : ''}{it.tl ? (it.t ? ' · ' : '') + it.tl : ''}</span>
          </div>
        ))}
      </div>
    );
  };
})();
