// Leaderboard component — supports table, card, chart layouts
const { useState, useMemo, useRef, useEffect } = React;

function orgLogo(org) {
  const map = {
    "OpenAI": "assets/logos/openai.svg",
    "Anthropic": "assets/logos/anthropic.svg",
    "Google DeepMind": "assets/logos/google-deepmind.png",
    "Mistral": "assets/logos/mistral.svg",
    "xAI": "assets/logos/xai.svg",
    "Meta": "assets/logos/meta.svg",
    "Alibaba": "assets/logos/qwen.svg",
    "DeepSeek": "assets/logos/deepseek.svg",
    "Xiaomi": "assets/logos/xiaomi.svg",
  };
  return map[org] || null;
}

function orgInitials(org) {
  return org.split(/\s+/).map((w) => w[0]).join("").slice(0, 2).toUpperCase();
}

// deterministic pseudo-CI margin (±) for a model on a given metric
function ciFor(m, dsFilter) {
  const key = m.id + "|" + dsFilter;
  let h = 0;
  for (let i = 0; i < key.length; i++) h = (h * 31 + key.charCodeAt(i)) >>> 0;
  return 0.8 + (h % 170) / 100; // ~0.8 .. 2.49
}

function CIMarker({ style, score, ci, color }) {
  const lo = Math.max(0, score - ci);
  const hi = Math.min(100, score + ci);
  const left = `${lo}%`;
  const width = `${hi - lo}%`;
  if (style === "band") {
    // diagonal hatch in a darker shade of the bar's own color;
    // for already-dark bars, lighten instead so the hatch stays visible
    const stripe = (() => {
      const c = (color || "").replace("#", "");
      if (c.length !== 6) return "rgba(0,0,0,0.42)";
      let r = parseInt(c.slice(0, 2), 16), g = parseInt(c.slice(2, 4), 16), b = parseInt(c.slice(4, 6), 16);
      const lum = 0.299 * r + 0.587 * g + 0.114 * b;
      if (lum < 70) {
        // pale: lift toward white
        r = Math.round(r + (255 - r) * 0.6);
        g = Math.round(g + (255 - g) * 0.6);
        b = Math.round(b + (255 - b) * 0.6);
      } else {
        // dark: scale toward black
        r = Math.round(r * 0.55);
        g = Math.round(g * 0.55);
        b = Math.round(b * 0.55);
      }
      return `rgb(${r},${g},${b})`;
    })();
    const hatch = `repeating-linear-gradient(45deg, ${stripe} 0, ${stripe} 3px, transparent 3px, transparent 6px)`;
    return <span className="ci-band" style={{ left, width, backgroundImage: hatch }} />;
  }
  if (style === "caps") {
    return (
      <span className="ci-caps" style={{ left, width }}>
        <span className="ci-cap ci-cap--l" />
        <span className="ci-cap ci-cap--r" />
      </span>
    );
  }
  // whiskers (default)
  return (
    <span className="ci-whisker" style={{ left, width }}>
      <span className="ci-cap ci-cap--l" />
      <span className="ci-cap ci-cap--r" />
    </span>
  );
}

function Leaderboard({ layout, teal, barColor, orgColors, ciStyle }) {
  const [selectedOrgs, setSelectedOrgs] = useState(() => new Set(window.ORGS));
  const [bestOnly, setBestOnly] = useState(true);
  const [dsFilter, setDsFilter] = useState("Overall");

  const rows = useMemo(() => {
    let r = window.MODELS.slice();
    const getScore = (m) => dsFilter === "Overall" ? m.overall : m.scores[dsFilter];
    r = r.map((m) => ({ ...m, _score: getScore(m) }));

    r = r.filter((m) => selectedOrgs.has(m.org));

    if (bestOnly) {
      const bestByOrg = new Map();
      for (const m of r) {
        const cur = bestByOrg.get(m.org);
        if (!cur || m._score > cur._score) bestByOrg.set(m.org, m);
      }
      r = Array.from(bestByOrg.values());
    }
    r.sort((a, b) => b._score - a._score);
    return r;
  }, [selectedOrgs, bestOnly, dsFilter]);

  const maxScore = Math.max(...rows.map((r) => r._score), 1);

  return (
    <section className="lb-wrap" id="leaderboard">
      <div className="lb-head">
        <div>
          <div className="eyebrow">Leaderboard</div>
        </div>
      </div>

      <div className="lb-filters">
        <FilterGroup
          label="View"
          value={bestOnly ? "Best by company" : "All"}
          options={["Best by company", "All"]}
          onChange={(v) => setBestOnly(v === "Best by company")} />
        
        <CompanyFilter
          selected={selectedOrgs}
          onChange={setSelectedOrgs} />
        
        <DatasetFilter
          value={dsFilter}
          options={["Overall", ...window.DATASETS]}
          onChange={setDsFilter} />
        
        <div className="lb-filter-meta">
          X models · X datapoints
        </div>
      </div>

      {layout === "table" && <TableView rows={rows} dsFilter={dsFilter} maxScore={maxScore} teal={teal} barColor={barColor} orgColors={orgColors} ciStyle={ciStyle} />}
      {layout === "cards" && <CardView rows={rows} dsFilter={dsFilter} maxScore={maxScore} teal={teal} />}
      {layout === "chart" && <ChartView rows={rows} dsFilter={dsFilter} maxScore={maxScore} teal={teal} />}
    </section>);

}

function CompanyFilter({ selected, onChange }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

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

  const toggleOrg = (org) => {
    const next = new Set(selected);
    if (next.has(org)) next.delete(org); else next.add(org);
    onChange(next);
  };

  const allOn = selected.size === window.ORGS.length;
  const noneOn = selected.size === 0;
  const summary = allOn
    ? "All companies"
    : noneOn
    ? "None selected"
    : selected.size === 1
    ? Array.from(selected)[0]
    : `${selected.size} companies`;

  return (
    <div className="filter-group">
      <div className="filter-label">Company</div>
      <div className="company-dd" ref={ref}>
        <button
          type="button"
          className={"dd-trigger" + (open ? " is-open" : "")}
          onClick={() => setOpen((v) => !v)}>
          <span>{summary}</span>
          <span className="dd-caret" aria-hidden="true">▾</span>
        </button>
        {open && (
          <div className="dd-menu">
            {window.ORGS.map((org) => (
              <button
                key={org}
                type="button"
                className="dd-item"
                onClick={() => toggleOrg(org)}>
                <span className={"dd-check" + (selected.has(org) ? " is-on" : "")} aria-hidden="true">
                  {selected.has(org) ? "✓" : ""}
                </span>
                {orgLogo(org) ? (
                  <img className="dd-logo" data-org={org} src={orgLogo(org)} alt="" aria-hidden="true" />
                ) : (
                  <span className="org-mark" aria-hidden="true">{orgInitials(org)}</span>
                )}
                <span>{org}</span>
              </button>
            ))}
            <div className="dd-sep" />
            <div className="dd-actions">
              <button type="button" className="dd-link" onClick={() => onChange(new Set(window.ORGS))}>Select all</button>
              <button type="button" className="dd-link" onClick={() => onChange(new Set())}>Clear</button>
            </div>
          </div>
        )}
      </div>
    </div>);

}

function FilterGroup({ label, value, options, onChange }) {
  return (
    <div className="filter-group">
      <div className="filter-label">{label}</div>
      <div className="filter-opts">
        {options.map((opt) =>
        <button
          key={opt}
          className={"filter-chip" + (value === opt ? " is-active" : "")}
          onClick={() => onChange(opt)}>
          
            {opt}
          </button>
        )}
      </div>
    </div>);

}

function DatasetFilter({ value, options, onChange }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    const onKey = (e) => { if (e.key === "Escape") setOpen(false); };
    document.addEventListener("mousedown", onDown);
    document.addEventListener("keydown", onKey);
    return () => { document.removeEventListener("mousedown", onDown); document.removeEventListener("keydown", onKey); };
  }, [open]);
  return (
    <div className="filter-group">
      <div className="filter-label">Dataset</div>
      <div className="company-dd" ref={ref}>
        <button
          type="button"
          className={"dd-trigger" + (open ? " is-open" : "")}
          onClick={() => setOpen((v) => !v)}>
          <span>{value}</span>
          <span className="dd-caret" aria-hidden="true">▾</span>
        </button>
        {open && (
          <div className="dd-menu">
            {options.map((opt) => (
              <button
                key={opt}
                type="button"
                className={"dd-item" + (value === opt ? " is-active" : "")}
                onClick={() => { onChange(opt); setOpen(false); }}>
                <span>{opt}</span>
              </button>
            ))}
          </div>
        )}
      </div>
    </div>);

}

function TableView({ rows, dsFilter, maxScore, teal, barColor, orgColors, ciStyle }) {
  const [expanded, setExpanded] = useState(false);
  const [openId, setOpenId] = useState(null);
  const [hoverId, setHoverId] = useState(null);
  const colorFor = (m) =>
    barColor !== "teal" && orgColors && orgColors[m.org] ? orgColors[m.org] : teal;
  const subScores = (m) =>
    ["Overall", ...window.DATASETS]
      .filter((d) => d !== dsFilter)
      .map((d) => ({
        label: d,
        value: d === "Overall" ? m.overall : m.scores[d],
      }));
  const initial = 10;
  const visible = expanded ? rows : rows.slice(0, initial);
  const hidden = Math.max(0, rows.length - initial);
  return (
    <div className="lb-table-wrap">
      <table className="lb-table">
        <thead>
          <tr>
            <th className="col-rank">#</th>
            <th className="col-model">Model</th>
            <th className="col-score">{dsFilter === "Overall" ? "Overall" : dsFilter}</th>
          </tr>
        </thead>
        <tbody>
          {visible.map((m, i) =>
          <React.Fragment key={m.id}>
            <tr
              className={"lb-row lb-row--clickable" + (openId === m.id ? " is-open" : "")}
              onClick={() => setOpenId(openId === m.id ? null : m.id)}
              onMouseEnter={() => setHoverId(m.id)}
              onMouseLeave={() => setHoverId(null)}>
              <td className="col-rank mono">{String(i + 1).padStart(2, "0")}</td>
              <td className="col-model">
                <div className="model-name-row">
                  <span className="lb-caret" aria-hidden="true">{openId === m.id ? "▾" : "▸"}</span>
                  <span className="model-name">{m.name}</span>
                  {orgLogo(m.org) ? (
                    <img className="org-logo" data-org={m.org} src={orgLogo(m.org)} alt={m.org} title={m.org} />
                  ) : (
                    <span className="org-mark" data-org={m.org} title={m.org} aria-hidden="true">{orgInitials(m.org)}</span>
                  )}
                </div>
              </td>
              <td className="col-score">
                <div className="score-cell">
                  <span className="score-num mono">{m._score.toFixed(1)}</span>
                  <div className="score-bar">
                    <div
                    className="score-bar-fill"
                    style={{ width: `${m._score}%`, background: colorFor(m) }} />
                    {ciStyle && ciStyle !== "off" && hoverId === m.id && (
                      <CIMarker style={ciStyle} score={m._score} ci={ciFor(m, dsFilter)} color={colorFor(m)} />
                    )}
                  </div>
                </div>
              </td>
            </tr>
            {openId === m.id && subScores(m).map((s, si, arr) => (
              <tr
                key={m.id + s.label}
                className={"lb-subrow" + (si === arr.length - 1 ? " is-last" : "")}>
                <td className="col-rank"></td>
                <td className="col-model">
                  <span className="lb-sub-label">{s.label}</span>
                </td>
                <td className="col-score">
                  <div className="score-cell">
                    <span className="score-num mono">{s.value.toFixed(1)}</span>
                    <div className="score-bar">
                      <div
                        className="score-bar-fill"
                        style={{ width: `${s.value}%`, background: colorFor(m) }} />
                    </div>
                  </div>
                </td>
              </tr>
            ))}
          </React.Fragment>
          )}
        </tbody>
      </table>
      {hidden > 0 && (
        <button
          type="button"
          className="lb-expand"
          onClick={() => setExpanded((v) => !v)}>
          {expanded ? "Show less" : "Show all"}
          <span className="lb-expand-caret" aria-hidden="true">{expanded ? "↑" : "↓"}</span>
        </button>
      )}
    </div>);

}

function CardView({ rows, dsFilter, maxScore, teal }) {
  return (
    <div className="lb-cards">
      {rows.map((m, i) =>
      <article key={m.id} className="lb-card">
          <div className="lb-card-top">
            <span className="mono-small dim">#{String(i + 1).padStart(2, "0")}</span>
            <span className="mono-small dim">{m.org}</span>
          </div>
          <h3 className="lb-card-name">{m.name}</h3>
          <div className="lb-card-score">
            <div className="score-label mono-small">{dsFilter === "Overall" ? "Overall" : dsFilter}</div>
            <div className="score-big" style={{ color: teal }}>{m._score.toFixed(1)}</div>
          </div>
          <div className="lb-card-breakdown">
            {window.DATASETS.map((d) =>
          <div key={d} className="bd-row">
                <span className="bd-label">{d}</span>
                <span className="bd-val mono">{m.scores[d].toFixed(1)}</span>
                <div className="bd-bar">
                  <div className="bd-bar-fill" style={{ width: `${m.scores[d]}%`, background: teal }} />
                </div>
              </div>
          )}
          </div>
          <div className="lb-card-foot mono-small dim">Released X</div>
        </article>
      )}
    </div>);

}

function ChartView({ rows, dsFilter, maxScore, teal }) {
  // horizontal bar chart; if dataset === Overall, show one bar per model;
  // otherwise show grouped bars across datasets
  const showBreakdown = dsFilter === "Overall";
  const chartMax = 100;

  return (
    <div className="lb-chart">
      <div className="chart-axis">
        {[0, 25, 50, 75, 100].map((v) =>
        <div key={v} className="axis-tick" style={{ left: `${v}%` }}>
            <div className="axis-line" />
            <div className="axis-label mono-small">{v}</div>
          </div>
        )}
      </div>
      {rows.map((m, i) =>
      <div key={m.id} className="chart-row">
          <div className="chart-row-head">
            <span className="mono-small dim">#{String(i + 1).padStart(2, "0")}</span>
            <span className="chart-model-name">{m.name}</span>
            <span className="mono-small dim">{m.org}</span>
          </div>
          {showBreakdown ?
        <div className="chart-bars-group">
              {window.DATASETS.map((d, j) => {
            const v = m.scores[d];
            return (
              <div key={d} className="chart-bar-row">
                    <div className="chart-bar-label mono-small">{d}</div>
                    <div className="chart-bar-track">
                      <div
                    className="chart-bar-fill"
                    style={{
                      width: `${v / chartMax * 100}%`,
                      background: teal,
                      opacity: 0.45 + 0.25 * (window.DATASETS.length - j)
                    }} />
                  
                      <span className="chart-bar-val mono" style={{ left: `calc(${v / chartMax * 100}% + 8px)` }}>
                        {v.toFixed(1)}
                      </span>
                    </div>
                  </div>);

          })}
            </div> :

        <div className="chart-bar-row chart-bar-row--single">
              <div className="chart-bar-track">
                <div
              className="chart-bar-fill"
              style={{ width: `${m._score / chartMax * 100}%`, background: teal }} />
            
                <span className="chart-bar-val mono" style={{ left: `calc(${m._score / chartMax * 100}% + 8px)` }}>
                  {m._score.toFixed(1)}
                </span>
              </div>
            </div>
        }
        </div>
      )}
    </div>);

}

window.Leaderboard = Leaderboard;