/* global React, ReactDOM */
const { useState, useMemo, useRef, useEffect } = React;

// ---------- helpers ----------
function srcColor(meta, intensity, dark) {
  // intensity 0..1
  const { hue, chroma } = meta;
  if (intensity <= 0.001) {
    return dark ? "oklch(0.18 0 0)" : "oklch(0.965 0 0)";
  }
  // map intensity to lightness band
  const L = dark
    ? 0.22 + intensity * 0.42   // 0.22 -> 0.64
    : 0.96 - intensity * 0.42;  // 0.96 -> 0.54
  const C = chroma * (0.25 + 0.75 * intensity);
  return `oklch(${L.toFixed(3)} ${C.toFixed(3)} ${hue})`;
}
function srcInk(meta, intensity, dark) {
  if (intensity < 0.45) return dark ? "oklch(0.78 0.02 0)" : "oklch(0.22 0.01 0)";
  return dark ? "oklch(0.97 0.02 0)" : "oklch(0.99 0.01 0)";
}
function srcAccent(meta, dark) {
  return `oklch(${dark ? 0.7 : 0.5} ${meta.chroma} ${meta.hue})`;
}

function formatTWh(v) {
  if (v == null) return "—";
  if (Math.abs(v) >= 1000) return (v / 1000).toFixed(1) + "k";
  if (Math.abs(v) >= 100) return Math.round(v).toString();
  if (Math.abs(v) >= 10) return v.toFixed(0);
  return v.toFixed(1);
}

// ---------- header chrome ----------
function TerminalHeader({ country, onChange, countries, mode, setMode, dark }) {
  return (
    <div className="ept-head">
      <div className="ept-head-row ept-head-top">
        <div className="ept-brand">
          <span className="ept-brand-dot" />
          <span className="ept-brand-name">THE ENERGY MIX</span>
        </div>
      </div>

      <div className="ept-head-row ept-head-main">
        <div className="ept-country ept-country-center">
          <CountrySearch
            value={country.code}
            onChange={onChange}
            options={countries}
          />
        </div>

        <div className="ept-controls">
          <SegToggle
            label="UNIT"
            value={mode}
            options={[
              { v: "pct", l: "%" },
              { v: "abs", l: "TWh" },
            ]}
            onChange={setMode}
          />
        </div>
      </div>

      <CountryStats country={country} dark={dark} />
    </div>
  );
}

function CountrySearch({ value, onChange, options }) {
  const current = options.find((c) => c.code === value);
  const [query, setQuery] = useState("");
  const [open, setOpen] = useState(false);
  const [active, setActive] = useState(0);
  const ref = useRef(null);

  useEffect(() => {
    function onDoc(e) {
      if (ref.current && !ref.current.contains(e.target)) {
        setOpen(false);
        setQuery("");
      }
    }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return options;
    return options.filter(
      (c) => c.name.toLowerCase().includes(q) || c.code.toLowerCase().includes(q)
    );
  }, [query, options]);

  function pick(c) {
    onChange(c.code);
    setQuery("");
    setOpen(false);
    setActive(0);
  }

  function onKey(e) {
    if (e.key === "ArrowDown") { e.preventDefault(); setActive((i) => Math.min(filtered.length - 1, i + 1)); setOpen(true); }
    else if (e.key === "ArrowUp") { e.preventDefault(); setActive((i) => Math.max(0, i - 1)); }
    else if (e.key === "Enter") { e.preventDefault(); if (filtered[active]) pick(filtered[active]); }
    else if (e.key === "Escape") { setOpen(false); setQuery(""); }
  }

  return (
    <div className="ept-search" ref={ref}>
      <span className="ept-search-label">COUNTRY</span>
      <div className="ept-search-wrap">
        <span className="ept-search-icon">⌕</span>
        <input
          type="text"
          className="ept-search-input"
          placeholder={current ? `${current.code} · ${current.name}` : "Search country…"}
          value={query}
          onChange={(e) => { setQuery(e.target.value); setOpen(true); setActive(0); }}
          onFocus={() => setOpen(true)}
          onKeyDown={onKey}
          spellCheck={false}
          autoComplete="off"
        />
        {query && (
          <button className="ept-search-x" onClick={() => { setQuery(""); ref.current?.querySelector("input")?.focus(); }}>×</button>
        )}
      </div>
      {open && filtered.length > 0 && (
        <ul className="ept-search-list" role="listbox">
          {filtered.map((c, i) => (
            <li
              key={c.code}
              role="option"
              aria-selected={c.code === value}
              className={
                "ept-search-item " +
                (i === active ? "is-active " : "") +
                (c.code === value ? "is-current " : "")
              }
              onMouseEnter={() => setActive(i)}
              onMouseDown={(e) => { e.preventDefault(); pick(c); }}
            >
              <span className="ept-search-code">{c.code}</span>
              <span className="ept-search-name">{c.name}</span>
              {c.code === value && <span className="ept-search-tag">CURRENT</span>}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

function SegToggle({ value, onChange, options, label }) {
  return (
    <div className="ept-seg">
      <span className="ept-seg-label">{label}</span>
      <div className="ept-seg-track">
        {options.map((o) => (
          <button
            key={o.v}
            className={"ept-seg-btn " + (value === o.v ? "is-on" : "")}
            onClick={() => onChange(o.v)}
          >
            {o.l}
          </button>
        ))}
      </div>
    </div>
  );
}

function Clock() {
  const [t, setT] = useState(() => new Date());
  useEffect(() => {
    const id = setInterval(() => setT(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const hh = String(t.getUTCHours()).padStart(2, "0");
  const mm = String(t.getUTCMinutes()).padStart(2, "0");
  const ss = String(t.getUTCSeconds()).padStart(2, "0");
  return (
    <span>
      <span className="ept-clock-pulse" /> {hh}:{mm}:{ss} UTC · LIVE
    </span>
  );
}

function CountryStats({ country, dark }) {
  const stats = useMemo(() => computeStats(country), [country]);
  return (
    <div className="ept-stats">
      <Stat label="TOTAL PRIMARY" value={`${(country.total_primary_twh / 1000).toFixed(1)}k`} unit="TWh" />
      <Stat label="IMPORT DEP." value={stats.importDep.toFixed(0)} unit="%" tone={stats.importDep > 60 ? "warn" : ""} />
      <Stat label="FOSSIL SHARE" value={stats.fossil.toFixed(0)} unit="%" tone={stats.fossil > 70 ? "warn" : ""} />
      <Stat label="DOMINANT" value={stats.dominant.name} unit={stats.dominant.share.toFixed(0) + "%"} />
    </div>
  );
}
function Stat({ label, value, unit, tone }) {
  return (
    <div className={"ept-stat ept-tone-" + (tone || "n")}>
      <div className="ept-stat-label">{label}</div>
      <div className="ept-stat-val">
        <span className="ept-stat-num">{value}</span>
        <span className="ept-stat-unit">{unit}</span>
      </div>
    </div>
  );
}

function computeStats(country) {
  const total = country.energy_sources.reduce(
    (a, s) => a + Object.values(s.abs).reduce((b, v) => b + (v || 0), 0),
    0
  );
  const importedTwh = country.energy_sources.reduce((a, s) => {
    const sum = Object.values(s.abs).reduce((b, v) => b + (v || 0), 0);
    return a + (sum * Math.max(0, s.imports)) / 100;
  }, 0);
  const importDep = total ? (importedTwh / total) * 100 : 0;

  const fossilSrc = ["Coal", "Oil", "Gas"];
  const fossilTwh = country.energy_sources
    .filter((s) => fossilSrc.includes(s.name))
    .reduce((a, s) => a + Object.values(s.abs).reduce((b, v) => b + (v || 0), 0), 0);
  const fossil = total ? (fossilTwh / total) * 100 : 0;

  const lowSrc = ["Renewables", "Nuclear"];
  const lowTwh = country.energy_sources
    .filter((s) => lowSrc.includes(s.name))
    .reduce((a, s) => a + Object.values(s.abs).reduce((b, v) => b + (v || 0), 0), 0);
  const lowC = total ? (lowTwh / total) * 100 : 0;

  let dominant = { name: "—", share: 0 };
  country.energy_sources.forEach((s) => {
    const sum = Object.values(s.abs).reduce((b, v) => b + (v || 0), 0);
    const share = total ? (sum / total) * 100 : 0;
    if (share > dominant.share) dominant = { name: s.name.toUpperCase(), share };
  });

  // fragility score: import dep + concentration penalty
  let score = 0;
  if (importDep > 70) score += 4; else if (importDep > 50) score += 3; else if (importDep > 30) score += 2; else score += 1;
  if (dominant.share > 50) score += 3; else if (dominant.share > 35) score += 2; else score += 1;
  if (fossil > 75) score += 3; else if (fossil > 55) score += 2; else if (fossil > 35) score += 1;
  score = Math.min(10, score);
  let label = "MODERATE", tone = "warn";
  if (score >= 8) { label = "HIGH"; tone = "bad"; }
  else if (score <= 4) { label = "LOW"; tone = "ok"; }

  return { importDep, fossil, lowC, dominant, fragility: { score, label, tone } };
}

// ---------- table ----------
function EnergyProfileTable({ data, mode, dark, hovered, setHovered, sectors, sourceMeta, compact }) {
  const sorted = useMemo(() => [...data.energy_sources], [data]);

  const colTotals = useMemo(() => {
    const t = {};
    sectors.forEach((sec) => {
      t[sec.key] = data.energy_sources.reduce((a, s) => a + (s.sectors[sec.key] || 0), 0);
    });
    return t;
  }, [data, sectors]);

  return (
    <div className={"ept-table " + (compact ? "is-compact" : "")}>
      <div className="ept-table-head">
        <div className="ept-th ept-th-source">SOURCE</div>
        {sectors.map((sec) => (
          <div key={sec.key} className="ept-th ept-th-sec">
            <span className="ept-th-glyph">{sec.glyph}</span>
            <span className="ept-th-label">{sec.label}</span>
          </div>
        ))}
        <div className="ept-th ept-th-split">SUPPLY · DOM / IMP</div>
      </div>

      {sorted.map((s, idx) => (
        <SourceRow
          key={s.name}
          source={s}
          sectors={sectors}
          meta={sourceMeta[s.name]}
          mode={mode}
          dark={dark}
          countryName={data.name}
          totalPrimary={data.total_primary_twh}
          hovered={hovered}
          setHovered={setHovered}
          rowIndex={idx}
        />
      ))}

      <div className="ept-foot">
        <div className="ept-th ept-th-source ept-foot-cell">Σ SECTOR DEMAND</div>
        {sectors.map((sec) => (
          <div key={sec.key} className="ept-foot-cell ept-foot-num">
            {Math.round(colTotals[sec.key])}<span className="ept-unit">%</span>
          </div>
        ))}
        <div className="ept-foot-cell" />
      </div>
    </div>
  );
}

function SourceRow({ source, sectors, meta, mode, dark, countryName, totalPrimary, hovered, setHovered, rowIndex }) {
  const sectorVals = sectors.map((sec) => source.sectors[sec.key] || 0);
  const dominantIdx = sectorVals.indexOf(Math.max(...sectorVals));
  const accentBar = srcAccent(meta, dark);
  const totalAbs = Object.values(source.abs).reduce((a, b) => a + (b || 0), 0);
  const sharePct = totalPrimary > 0 ? (totalAbs / totalPrimary) * 100 : 0;

  return (
    <div
      className={
        "ept-row " +
        (hovered && hovered.row === source.name ? "is-active " : "")
      }
      style={{ "--src-accent": accentBar }}
    >
      <div className="ept-cell ept-cell-source">
        <span className="ept-src-bar" style={{ background: accentBar }} />
        <span className="ept-src-code">{meta.code}</span>
        <span className="ept-src-name">{source.name}</span>
        <span className="ept-src-total">
          {mode === "pct"
            ? <>{sharePct >= 10 ? Math.round(sharePct) : sharePct.toFixed(1)}<span className="ept-unit">%</span></>
            : <>{formatTWh(totalAbs)}<span className="ept-unit">TWh</span></>}
        </span>
      </div>

      {sectors.map((sec, i) => {
        const v = source.sectors[sec.key] || 0;
        const abs = source.abs[sec.key] || 0;
        const isHidden = source.name === "Electricity" && sec.key === "power";
        const intensity = isHidden ? 0 : Math.min(1, v / 100);
        const bg = isHidden ? "transparent" : srcColor(meta, intensity, dark);
        const ink = srcInk(meta, intensity, dark);
        const isDominant = !isHidden && i === dominantIdx && v > 0;
        if (isHidden) {
          return (
            <div key={sec.key} className="ept-cell ept-cell-num is-hidden" title="Electricity is generated by other sources, not consumed by the power sector">
              <span className="ept-hidden-mark">—</span>
            </div>
          );
        }
        return (
          <div
            key={sec.key}
            className={
              "ept-cell ept-cell-num " +
              (v === 0 ? "is-zero " : "") +
              (isDominant ? "is-dominant " : "")
            }
            style={{ background: bg, color: ink }}
            onMouseEnter={() =>
              setHovered({
                row: source.name,
                col: sec.key,
                v,
                abs,
                source: source.name,
                sector: sec.label,
                country: countryName,
                mode,
                dominant: isDominant,
                meta,
              })
            }
            onMouseLeave={() => setHovered(null)}
          >
            <span className="ept-num">
              {mode === "pct" ? (v ? (v >= 10 ? Math.round(v) : v.toFixed(1)) : "·") : (abs ? formatTWh(abs) : "·")}
              {v > 0 && <span className="ept-unit-inline">{mode === "pct" ? "%" : ""}</span>}
            </span>
            {v > 0 && (
              <span
                className="ept-bar"
                style={{ width: `${Math.max(2, intensity * 100)}%`, background: srcAccent(meta, dark) }}
              />
            )}
          </div>
        );
      })}

      <SupplyCell source={source} meta={meta} dark={dark} />
    </div>
  );
}

function SupplyCell({ source, meta, dark }) {
  const dom = Math.max(0, Math.min(100, source.domestic));
  const imp = Math.max(0, Math.min(100, source.imports));
  const netExport = source.imports < 0;
  return (
    <div className="ept-cell ept-cell-supply">
      <div className="ept-supply-bar">
        <span className="ept-supply-dom" style={{ width: `${dom}%`, background: srcAccent(meta, dark) }} />
        <span className="ept-supply-imp" style={{ width: `${imp}%` }} />
      </div>
      <div className="ept-supply-nums">
        <span className="ept-supply-num"><b>{Math.round(dom)}</b><span className="ept-unit">D</span></span>
        <span className="ept-supply-sep">/</span>
        <span className={"ept-supply-num"}>
          <b>{netExport ? "↑" + Math.abs(source.imports) : Math.round(imp)}</b><span className="ept-unit">{netExport ? "EXP" : "I"}</span>
        </span>
      </div>
    </div>
  );
}



// ---------- tooltip ----------
function Tooltip({ hovered, containerRef }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    function move(e) {
      const rect = containerRef.current?.getBoundingClientRect();
      if (!rect) return;
      setPos({ x: e.clientX - rect.left, y: e.clientY - rect.top });
    }
    window.addEventListener("mousemove", move);
    return () => window.removeEventListener("mousemove", move);
  }, [containerRef]);
  if (!hovered) return null;
  const above = pos.y > 220;
  return (
    <div
      className="ept-tooltip"
      style={{
        left: pos.x + 14,
        top: above ? pos.y - 14 : pos.y + 14,
        transform: above ? "translateY(-100%)" : "none",
      }}
    >
      <div className="ept-tt-head">
        <span className="ept-tt-code">{hovered.meta.code}</span>
        <span className="ept-tt-source">{hovered.source}</span>
        <span className="ept-tt-sep">→</span>
        <span className="ept-tt-sector">{hovered.sector}</span>
      </div>
      <div className="ept-tt-big">
        <span className="ept-tt-num">{hovered.mode === "pct" ? hovered.v : formatTWh(hovered.abs)}</span>
        <span className="ept-tt-unit">{hovered.mode === "pct" ? "%" : "TWh"}</span>
      </div>
      <div className="ept-tt-line">
        <span className="ept-tt-dim">In {hovered.country}, </span>
        <b>{hovered.source}</b>
        <span className="ept-tt-dim"> supplies </span>
        <b>{hovered.v}%</b>
        <span className="ept-tt-dim"> of </span>
        <b>{hovered.sector.toLowerCase()}</b>
        <span className="ept-tt-dim"> energy demand.</span>
      </div>
      {hovered.dominant && (
        <div className="ept-tt-flag">DOMINANT — primary energy source for this sector</div>
      )}
    </div>
  );
}

// ---------- legend ----------
function Legend({ dark, sourceMeta }) {
  return (
    <div className="ept-legend">
      <div className="ept-legend-grp">
        <span className="ept-legend-label">INTENSITY</span>
        <div className="ept-legend-ramp">
          {[0, 0.2, 0.4, 0.6, 0.8, 1].map((v) => (
            <span
              key={v}
              className="ept-legend-step"
              style={{ background: srcColor({ hue: 240, chroma: 0.13 }, v, dark) }}
            />
          ))}
          <span className="ept-legend-tick">0%</span>
          <span className="ept-legend-tick ept-legend-tick-end">100%</span>
        </div>
      </div>
      <div className="ept-legend-grp">
        <span className="ept-legend-label">SOURCES</span>
        <div className="ept-legend-srcs">
          {Object.entries(sourceMeta).map(([name, m]) => (
            <span key={name} className="ept-legend-src">
              <span className="ept-legend-dot" style={{ background: srcAccent(m, dark) }} />
              {name}
            </span>
          ))}
        </div>
      </div>

    </div>
  );
}

// ---------- compare panel ----------
function ComparePanel({ a, b, sourceMeta, sectors, mode, dark, hovered, setHovered, sortBy }) {
  return (
    <div className="ept-compare">
      <div className="ept-compare-col">
        <div className="ept-compare-tag">{a.code} · {a.name}</div>
        <EnergyProfileTable
          data={a}
          mode={mode}
          sortBy={sortBy}
          dark={dark}
          hovered={hovered}
          setHovered={setHovered}
          sectors={sectors}
          sourceMeta={sourceMeta}
          compact
        />
      </div>
      <div className="ept-compare-col">
        <div className="ept-compare-tag">{b.code} · {b.name}</div>
        <EnergyProfileTable
          data={b}
          mode={mode}
          sortBy={sortBy}
          dark={dark}
          hovered={hovered}
          setHovered={setHovered}
          sectors={sectors}
          sourceMeta={sourceMeta}
          compact
        />
      </div>
    </div>
  );
}

// ---------- exposure exports ----------
Object.assign(window, {
  EnergyProfileTable,
  TerminalHeader,
  Tooltip,
  Legend,
  ComparePanel,
  computeStats,
  srcAccent,
  srcColor,
  formatTWh,
});
