/* global React, window */
// RankingPage — eine Datenquelle, drei visuelle Varianten, voll responsiv.
// Layout via CSS-Klassen (siehe ranking.css); variantenspezifische Farben/
// Schriften kommen inline aus dem VARIANTS-Objekt.

const KLAX_VARIANTS = {
  playful: {
    name: "Spielerisch",
    bg: "#fef3e2",
    surface: "#ffffff",
    ink: "#2a1f1a",
    inkSoft: "#6b574a",
    accent: "#ff7a59",
    accent2: "#ffc94a",
    rule: "#f1d9b8",
    font: "'Fredoka', 'Quicksand', system-ui, sans-serif",
    fontTitle: "'Fredoka', system-ui, sans-serif",
    fontMono: "'Geist Mono', ui-monospace, monospace",
    barTrack: "#f6e6c8",
    barRadius: 999,
    rankColor: (rank, total) => {
      const t = (rank - 1) / Math.max(1, total - 1);
      const hue = 25 + t * 240;
      return `oklch(0.72 0.16 ${hue})`;
    },
    barFill: (rank, total) => {
      const t = (rank - 1) / Math.max(1, total - 1);
      const h1 = 25 + t * 240;
      const h2 = 55 + t * 240;
      return `linear-gradient(90deg, oklch(0.78 0.17 ${h1}), oklch(0.84 0.16 ${h2}))`;
    },
    bikeColor: "#2a1f1a",
    bikeStroke: 3,
    showRider: true,
    riderAccent: "#ff7a59",
  },
  sport: {
    name: "Sportlich",
    bg: "#f4f6f1",
    surface: "#ffffff",
    ink: "#0a1208",
    inkSoft: "#536154",
    accent: "#67a514",
    accent2: "#ed7c00",
    rule: "#d8e0cb",
    font: "'Space Grotesk', system-ui, sans-serif",
    fontTitle: "'Archivo Black', 'Space Grotesk', system-ui, sans-serif",
    fontMono: "'Geist Mono', ui-monospace, monospace",
    barTrack: "#e7ecdc",
    barRadius: 999,
    rankColor: (rank) => (rank <= 3 ? "#ed7c00" : "#0a1208"),
    barFill: () =>
      "linear-gradient(90deg, #d62828 0%, #ed7c00 22%, #f7c100 50%, #a5c031 78%, #67a514 100%)",
    // Skaliert den Gradient so, dass JEDE Stange einen Ausschnitt aus
    // dem GANZEN Bahn-Verlauf zeigt: Top-Klassen enden in Grün,
    // mittlere in Gelb, hintere bleiben im Rot/Orange-Bereich.
    barFillFullRange: true,
    bikeColor: "#0a1208",
    bikeStroke: 2.5,
    showRider: false,
    riderAccent: null,
  },
  minimal: {
    name: "Reduziert",
    bg: "#f7f5f0",
    surface: "#f7f5f0",
    ink: "#161616",
    inkSoft: "#7a766c",
    accent: "#5d3a1e",
    accent2: "#161616",
    rule: "#ddd7c8",
    font: "'Geist Mono', ui-monospace, monospace",
    fontTitle: "'Instrument Serif', 'Times New Roman', serif",
    fontMono: "'Geist Mono', ui-monospace, monospace",
    barTrack: "#ece6d6",
    barRadius: 0,
    rankColor: () => "#161616",
    barFill: () => "#161616",
    bikeColor: "#161616",
    bikeStroke: 1.6,
    showRider: false,
    riderAccent: null,
  },
};

// ── Live-Counter Hook ──
function useCountUp(target, durationMs, key) {
  const [value, setValue] = React.useState(0);
  React.useEffect(() => {
    setValue(0);
    let raf;
    const start = performance.now();
    const tick = (now) => {
      const t = Math.min(1, (now - start) / durationMs);
      const eased = 1 - Math.pow(1 - t, 3);
      setValue(Math.round(target * eased));
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target, durationMs, key]);
  return value;
}

// ── Verbleibende Tage / Status ──
function useActionStatus() {
  const action = window.KLAX_ACTION;
  const now = new Date();
  const start = new Date(action.startDate + "T00:00:00");
  const end = new Date(action.endDate + "T23:59:59");
  const day = 86400000;
  if (now < start) return { phase: "before", days: Math.ceil((start - now) / day) };
  if (now > end)   return { phase: "after", days: 0 };
  return { phase: "during", days: Math.ceil((end - now) / day) };
}

const fmt = new Intl.NumberFormat("de-DE");

// ── Eine Klassenzeile ──
function ClassRow({ idx, total, klass, km, maxKm, variant, tweaks }) {
  const v = KLAX_VARIANTS[variant];
  const rank = idx + 1;
  const fraction = Math.max(0.03, km / maxKm);
  const [phase, setPhase] = React.useState("start");

  const stagger = 80 + idx * 35;
  const growMs = (900 + fraction * 700) / tweaks.speed;

  React.useEffect(() => {
    setPhase("start");
    const t1 = setTimeout(() => setPhase("grow"), stagger);
    const t2 = setTimeout(() => setPhase("done"), stagger + growMs + 20);
    return () => { clearTimeout(t1); clearTimeout(t2); };
  }, [tweaks.replayKey, stagger, growMs]);

  const grown = phase !== "start";
  const animatedFraction = grown ? fraction : 0;

  const mode = tweaks.bikeMode;
  const wheelsSpinning = mode === "spinning" ? true : phase === "grow";

  let bikeLeftFraction = animatedFraction;
  let barWidthFraction = animatedFraction;
  if (mode === "trailing") {
    bikeLeftFraction = Math.min(1, animatedFraction + (grown ? 0.03 : 0));
  }

  const isTop3 = rank <= 3;
  const rankLabel = variant === "minimal" ? String(rank).padStart(2, "0") : rank;

  // variant-spezifische Inline-Styles (Farben, Schrift)
  const rankStyle = {
    playful: {
      background: v.rankColor(rank, total),
      color: "#fff",
      fontFamily: v.fontTitle,
      fontWeight: 600,
      borderRadius: 999,
      width: "var(--klax-rank-w)",
      height: "var(--klax-rank-w)",
      display: "grid",
      placeItems: "center",
      boxShadow: isTop3 ? "0 4px 0 rgba(0,0,0,.08)" : "none",
    },
    sport: {
      fontFamily: v.fontTitle,
      color: isTop3 ? v.accent2 : v.ink,
      fontSize: isTop3 ? "var(--klax-rank-fs-big)" : "var(--klax-rank-fs)",
      lineHeight: 1,
      letterSpacing: "-0.02em",
    },
    minimal: {
      fontFamily: v.fontMono,
      color: v.inkSoft,
      letterSpacing: "0.06em",
      fontSize: "var(--klax-rank-fs-mono)",
    },
  }[variant];

  const nameStyle = {
    playful:  { fontFamily: v.font,      fontWeight: 500, color: v.ink },
    sport:    { fontFamily: v.font,      fontWeight: 600, color: v.ink, letterSpacing: "-0.01em" },
    minimal:  { fontFamily: v.fontTitle, fontStyle: "italic", color: v.ink, letterSpacing: "0.005em", fontSize: "var(--klax-name-fs-serif)" },
  }[variant];

  const kmStyle = {
    playful: { fontFamily: v.fontMono,  fontWeight: 600, color: v.ink },
    sport:   { fontFamily: v.fontTitle, color: v.ink,    letterSpacing: "-0.02em" },
    minimal: { fontFamily: v.fontMono,  color: v.ink,    letterSpacing: "0.04em" },
  }[variant];

  return (
    <div
      className={`klax-row klax-row--${variant} ${tweaks.compact ? "klax-row--compact" : ""}`}
      data-rank={rank}
    >
      {tweaks.showRank && (
        <div className="klax-rank" style={rankStyle}>
          {rankLabel}
        </div>
      )}

      <div className="klax-name" style={nameStyle}>
        {klass.name}
      </div>

      <div className="klax-bar-lane">
        <div
          className="klax-bar-track"
          style={{
            background: v.barTrack,
            borderRadius: v.barRadius,
          }}
        />
        <div
          className="klax-bar-fill"
          style={{
            background: v.barFill(rank, total),
            backgroundSize: v.barFillFullRange
              ? `${100 / fraction}% 100%`
              : undefined,
            backgroundPosition: "left center",
            borderRadius: v.barRadius,
            width: `${barWidthFraction * 100}%`,
            transition: `width ${growMs}ms cubic-bezier(.22,.61,.36,1)`,
            boxShadow: variant === "playful" && isTop3 ? "0 3px 0 rgba(0,0,0,.06)" : "none",
          }}
        />
        <div
          className="klax-bike-holder"
          style={{
            left: `${bikeLeftFraction * 100}%`,
            transition: `left ${growMs}ms cubic-bezier(.22,.61,.36,1)`,
          }}
        >
          <Bike
            color={v.bikeColor}
            bgColor={v.bg}
            strokeWidth={v.bikeStroke}
            spinning={wheelsSpinning}
            spinSpeed={0.55 / tweaks.speed}
            showRider={v.showRider}
            accentColor={v.riderAccent}
          />
        </div>
      </div>

      <div className="klax-km" style={kmStyle}>
        {fmt.format(km)}
        <span className="klax-km-unit">km</span>
      </div>
    </div>
  );
}

// ── Header ──
function Header({ variant, totalKm, status, replayKey }) {
  const v = KLAX_VARIANTS[variant];
  const counted = useCountUp(totalKm, 2200, replayKey);
  // Stadtradeln rechnet 138 g CO₂ je geradelter Kilometer ein.
  const co2Kg = Math.round(totalKm * 0.138);
  const countedCo2 = useCountUp(co2Kg, 2200, replayKey);
  const action = window.KLAX_ACTION;

  const daysLabel =
    status.phase === "before" ? "bis Start" :
    status.phase === "during" ? (status.days === 1 ? "Tag noch" : "Tage noch") :
    "beendet";

  if (variant === "playful") {
    return (
      <header
        className="klax-header klax-header--playful"
        style={{
          background: `radial-gradient(120% 80% at 0% 0%, ${v.accent2}33, transparent 60%),
                       radial-gradient(120% 80% at 100% 0%, ${v.accent}33, transparent 55%),
                       ${v.bg}`,
          borderBottom: `2px dashed ${v.rule}`,
          color: v.ink,
        }}
      >
        <div className="klax-eyebrow" style={{ fontFamily: v.font, color: v.inkSoft }}>
          {action.school}
        </div>
        <h1 className="klax-title" style={{ fontFamily: v.fontTitle, color: v.ink }}>
          Klassen-<span style={{ color: v.accent }}>Ranking</span>
        </h1>
        <div className="klax-header-bottom">
          <div className="klax-stats-row">
            <div className="klax-stat">
              <div className="klax-counter-num" style={{ fontFamily: v.fontMono, color: v.ink }}>
                {fmt.format(counted)}
                <span className="klax-stat-unit" style={{ color: v.inkSoft }}>km</span>
              </div>
              <div className="klax-stat-label" style={{ fontFamily: v.font, color: v.inkSoft }}>
                Kilometer gesamt
              </div>
            </div>
            <div className="klax-stat-divider" style={{ background: v.rule }} />
            <div className="klax-stat">
              <div className="klax-counter-num" style={{ fontFamily: v.fontMono, color: v.ink }}>
                {fmt.format(countedCo2)}
                <span className="klax-stat-unit" style={{ color: v.inkSoft }}>kg</span>
              </div>
              <div className="klax-stat-label" style={{ fontFamily: v.font, color: v.inkSoft }}>
                CO₂ vermieden
              </div>
            </div>
          </div>
          <div className="klax-days klax-days--playful" style={{ background: v.ink, color: "#fff", fontFamily: v.fontTitle }}>
            <div className="klax-days-num">{status.phase === "after" ? "–" : status.days}</div>
            <div className="klax-days-label">{daysLabel}</div>
          </div>
        </div>
      </header>
    );
  }

  if (variant === "sport") {
    return (
      <header className="klax-header klax-header--sport">
        <div className="klax-header-band" style={{ background: v.accent, color: "#fff" }}>
          <div
            aria-hidden="true"
            className="klax-header-pattern"
          />
          <div className="klax-eyebrow" style={{ fontFamily: v.font, opacity: 0.85 }}>
            {action.school} · Berlin
          </div>
          <h1 className="klax-title klax-title--sport" style={{ fontFamily: v.fontTitle }}>
            Klassen-Ranking
          </h1>
          <div className="klax-header-bottom">
            <div className="klax-stats-row">
              <div className="klax-stat">
                <div className="klax-counter-num" style={{ fontFamily: v.fontTitle }}>
                  {fmt.format(counted)}
                </div>
                <div className="klax-stat-label klax-stat-label--sport" style={{ fontFamily: v.font }}>
                  Kilometer gesamt
                </div>
              </div>
              <div className="klax-stat-divider klax-stat-divider--sport" />
              <div className="klax-stat">
                <div className="klax-counter-num" style={{ fontFamily: v.fontTitle }}>
                  {fmt.format(countedCo2)}
                  <span className="klax-stat-unit">kg</span>
                </div>
                <div className="klax-stat-label klax-stat-label--sport" style={{ fontFamily: v.font }}>
                  CO₂ vermieden
                </div>
              </div>
            </div>
            <div className="klax-days klax-days--sport" style={{ background: v.accent2, color: "#fff", fontFamily: v.fontTitle }}>
              <div className="klax-days-num">{status.phase === "after" ? "–" : status.days}</div>
              <div className="klax-days-label">
                {status.phase === "before" ? "BIS START" : status.phase === "during" ? "TAGE" : "ENDE"}
              </div>
            </div>
          </div>
        </div>
        <div className="klax-header-strip" style={{ fontFamily: v.font }}>
          <span>Stadtradeln 20.05.–09.06.2026</span>
          <span style={{ color: v.accent2 }}>● live</span>
        </div>
      </header>
    );
  }

  // minimal
  return (
    <header className="klax-header klax-header--minimal" style={{ borderBottom: `1px solid ${v.rule}` }}>
      <div className="klax-eyebrow" style={{ fontFamily: v.fontMono, color: v.inkSoft }}>
        {action.school} · Stadtradeln 2026
      </div>
      <h1 className="klax-title klax-title--minimal" style={{ fontFamily: v.fontTitle, color: v.ink }}>
        Klassen-<em style={{ color: v.accent, fontStyle: "italic" }}>ranking</em>
      </h1>
      <div className="klax-minimal-stats" style={{ borderTop: `1px solid ${v.rule}` }}>
        <div>
          <div className="klax-eyebrow" style={{ fontFamily: v.fontMono, color: v.inkSoft }}>
            Gesamt
          </div>
          <div className="klax-counter-num" style={{ fontFamily: v.fontTitle, color: v.ink }}>
            {fmt.format(counted)}
            <span className="klax-counter-unit" style={{ fontFamily: v.fontMono, color: v.inkSoft }}>km</span>
          </div>
        </div>
        <div>
          <div className="klax-eyebrow" style={{ fontFamily: v.fontMono, color: v.inkSoft }}>
            CO₂ vermieden
          </div>
          <div className="klax-counter-num" style={{ fontFamily: v.fontTitle, color: v.ink }}>
            {fmt.format(countedCo2)}
            <span className="klax-counter-unit" style={{ fontFamily: v.fontMono, color: v.inkSoft }}>kg</span>
          </div>
        </div>
        <div style={{ textAlign: "right" }}>
          <div className="klax-eyebrow" style={{ fontFamily: v.fontMono, color: v.inkSoft }}>
            {status.phase === "before" ? "Bis Start" : status.phase === "during" ? "Verbleibend" : "Status"}
          </div>
          <div className="klax-counter-num" style={{ fontFamily: v.fontTitle, color: v.ink }}>
            {status.phase === "after" ? "–" : status.days}
            <span className="klax-counter-unit" style={{ fontFamily: v.fontMono, color: v.inkSoft }}>Tage</span>
          </div>
        </div>
      </div>
    </header>
  );
}

// ── Page ──
function RankingPage({ variant, tweaks }) {
  const v = KLAX_VARIANTS[variant];
  const status = useActionStatus();
  const classes = React.useMemo(
    () => [...window.KLAX_CLASSES].sort((a, b) => b.km - a.km),
    []
  );
  const totalKm = classes.reduce((s, c) => s + c.km, 0);
  // Safeguard: vor Aktionsstart sind alle km=0 → maxKm=0 wuerde NaN in
  // fraction = km/maxKm verursachen. Fallback auf 1 zeigt minimale Balken.
  const maxKm = Math.max(1, classes[0]?.km || 0);

  return (
    <div
      className={`klax-page klax-page--${variant} ${tweaks.compact ? "klax-page--compact" : ""}`}
      style={{ background: v.bg, color: v.ink, fontFamily: v.font, "--klax-ink-soft": v.inkSoft }}
    >
      <Header variant={variant} totalKm={totalKm} status={status} replayKey={tweaks.replayKey} />
      <main className="klax-list">
        {classes.map((c, i) => (
          <ClassRow
            key={c.name}
            idx={i}
            total={classes.length}
            klass={c}
            km={c.km}
            maxKm={maxKm}
            variant={variant}
            tweaks={tweaks}
          />
        ))}
        <div
          className="klax-footnote"
          style={{ fontFamily: v.fontMono, color: v.inkSoft }}
        >
          {window.KLAX_SCRAPED_AT
            ? `Aktualisiert: ${new Date(window.KLAX_SCRAPED_AT).toLocaleString("de-DE", {
                day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit",
              })} · Quelle: stadtradeln.de`
            : "Quelle: stadtradeln.de"}
        </div>
      </main>
    </div>
  );
}

window.RankingPage = RankingPage;
window.KLAX_VARIANTS = KLAX_VARIANTS;
