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

const RACE_DATE = window.RACE_DATE;
const WEEKS = window.WEEKS;
const PHASES = window.PHASES;
const TOTAL_KM = window.TOTAL_KM;

// ──────────────────────── persistence ──────────────────────────
const STORAGE_KEY = 'maraton-vali-v1';
const COOKIE_NAME = 'mvk';
const TWO_YEARS = 60 * 60 * 24 * 365 * 2;

function loadChecked() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) return JSON.parse(raw) || {};
  } catch {}
  // fallback: cookie (Safari ITP protection)
  const m = document.cookie.match(new RegExp('(?:^|; )' + COOKIE_NAME + '=([^;]+)'));
  if (m) {
    try { return JSON.parse(decodeURIComponent(m[1])) || {}; } catch {}
  }
  return {};
}
function saveChecked(c) {
  const json = JSON.stringify(c);
  try { localStorage.setItem(STORAGE_KEY, json); } catch {}
  document.cookie = `${COOKIE_NAME}=${encodeURIComponent(json)}; Max-Age=${TWO_YEARS}; Path=/; SameSite=Lax; Secure`;
}

// ──────────────────────── helpers ─────────────────────────────
function useNow(intervalMs = 60_000) {
  const [now, setNow] = useState(() => new Date());
  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), intervalMs);
    return () => clearInterval(t);
  }, [intervalMs]);
  return now;
}

function formatKm(km) {
  if (km >= 100) return Math.round(km).toString();
  if (Number.isInteger(km)) return km.toString();
  return km.toFixed(1).replace(/\.0$/, '');
}

function weekStartDate(weekIndex) {
  // Week 1 starts May 13 2026
  const d = new Date('2026-05-13T00:00:00+03:00');
  d.setDate(d.getDate() + weekIndex * 7);
  return d;
}
function currentWeekIndex(now) {
  const start = new Date('2026-05-13T00:00:00+03:00');
  const diffDays = Math.floor((now - start) / 86400000);
  if (diffDays < 0) return 0;
  const idx = Math.floor(diffDays / 7);
  return Math.min(idx, WEEKS.length - 1);
}

// ──────────────────────── components ──────────────────────────

function TopBar() {
  return (
    <header className="topbar">
      <div className="topbar-left">
        <span className="brand">MARATON</span>
        <span className="brand-sub">/ plan vali</span>
      </div>
      <div className="topbar-right">
        <span className="mono dot-pill"><span className="bullet" /> 11 octombrie 2026 · Cluj</span>
      </div>
    </header>
  );
}

function PillCheck({ checked, onClick, ariaLabel }) {
  return (
    <button
      type="button"
      onClick={onClick}
      aria-label={ariaLabel}
      aria-pressed={checked}
      className={'pill-check' + (checked ? ' is-on' : '')}
    >
      <span className="pill-check-glyph">
        {checked ? (
          <svg viewBox="0 0 16 16" width="14" height="14" aria-hidden>
            <path d="M3.5 8.5l3 3 6-7" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        ) : null}
      </span>
    </button>
  );
}

function Hero({ now, totalChecked, daysParts }) {
  const pct = Math.min(100, (totalChecked / TOTAL_KM) * 100);
  return (
    <section className="hero">
      <div className="hero-row">
        <div className="hero-block hero-days">
          <div className="hero-label mono"><span className="bullet" /> rămase până la start</div>
          <div className="hero-number-wrap">
            <div className="hero-number">{daysParts.d}</div>
            <div className="hero-suffix">
              <div className="hero-unit">{daysParts.d === 1 ? 'zi' : 'zile'}</div>
              <div className="hero-sub mono">{daysParts.h}h {daysParts.m}m</div>
            </div>
          </div>
        </div>

        <div className="hero-rule" aria-hidden />

        <div className="hero-block hero-km">
          <div className="hero-label mono"><span className="bullet" /> kilometri bifați</div>
          <div className="hero-number-wrap">
            <div className="hero-number is-ink">{formatKm(totalChecked)}</div>
            <div className="hero-suffix">
              <div className="hero-unit">km</div>
              <div className="hero-sub mono">din {formatKm(TOTAL_KM)} km plan</div>
            </div>
          </div>
        </div>
      </div>

      <div className="hero-bar" role="progressbar" aria-valuenow={Math.round(pct)} aria-valuemin={0} aria-valuemax={100}>
        <div className="hero-bar-fill" style={{ width: pct + '%' }} />
        <div className="hero-bar-ticks">
          {WEEKS.map((w, i) => (
            <span key={i} className="hero-bar-tick" style={{ left: ((i+1)/WEEKS.length)*100 + '%' }} />
          ))}
        </div>
      </div>
      <div className="hero-bar-foot mono">
        <span>{pct.toFixed(1)}% din plan</span>
        <span>scop: să ajungi sănătos la start, nu doar pregătit pe hârtie</span>
      </div>
    </section>
  );
}

function Quote() {
  return (
    <section className="quote">
      <div className="quote-mark">„</div>
      <p className="quote-text">
        Primele 25–30 km trebuie să pară <em>prea ușoare</em>.<br/>
        Dacă te simți erou la km 12, probabil mergi prea tare.
      </p>
      <div className="quote-cite mono">— strategie pentru ziua cursei</div>
    </section>
  );
}

function ProfileChart({ checkedByWeek, weekIdxNow }) {
  // SVG: weekly km bars rising to peak then tapering
  const w = 1040, h = 240, padL = 40, padR = 16, padT = 24, padB = 56;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;
  const maxKm = Math.max(...WEEKS.map(wk => wk.workouts.reduce((s,x) => s + x.km, 0)));
  const barW = innerW / WEEKS.length;

  return (
    <section className="profile">
      <div className="profile-head">
        <h2 className="section-title">Profilul cursei <span className="section-sub mono">— 21 săptămâni, 560 km</span></h2>
      </div>
      <svg viewBox={`0 0 ${w} ${h}`} className="profile-svg" preserveAspectRatio="xMidYMid meet">
        {/* baseline */}
        <line x1={padL} y1={padT+innerH} x2={padL+innerW} y2={padT+innerH} stroke="#0c1217" strokeWidth="1"/>

        {WEEKS.map((wk, i) => {
          const km = wk.workouts.reduce((s,x)=>s+x.km, 0);
          const checked = (checkedByWeek[i] ?? 0);
          const bh = (km/maxKm) * innerH;
          const ch = (checked/maxKm) * innerH;
          const x = padL + i*barW;
          const ph = PHASES[wk.phase];
          const isNow = i === weekIdxNow;
          return (
            <g key={i}>
              {/* planned bar (outline) */}
              <rect x={x+barW*0.12} y={padT+innerH-bh} width={barW*0.76} height={bh}
                fill={ph.color} opacity="0.55" />
              {/* checked overlay */}
              {ch > 0 && (
                <rect x={x+barW*0.12} y={padT+innerH-ch} width={barW*0.76} height={ch}
                  fill={ph.dot} opacity="0.95" />
              )}
              {/* current-week marker */}
              {isNow && (
                <rect x={x+barW*0.12-1} y={padT+innerH-bh-4} width={barW*0.76+2} height={bh+4}
                  fill="none" stroke="#0c1217" strokeWidth="1.5" strokeDasharray="2 2"/>
              )}
              {/* km label on top of biggest bars */}
              {km >= 24 && (
                <text x={x+barW/2} y={padT+innerH-bh-6} fontSize="10" textAnchor="middle"
                  fill="#0c1217" fontFamily="Geist Mono, monospace">{formatKm(km)}</text>
              )}
              {/* week number axis */}
              <text x={x+barW/2} y={padT+innerH+14} fontSize="9" textAnchor="middle"
                fill="#5a6068" fontFamily="Geist Mono, monospace">{wk.n}</text>
            </g>
          );
        })}

        {/* phase strip */}
        {(() => {
          const groups = [];
          let cur = { phase: WEEKS[0].phase, start: 0, end: 0 };
          for (let i = 1; i < WEEKS.length; i++) {
            if (WEEKS[i].phase === cur.phase) { cur.end = i; }
            else { groups.push(cur); cur = { phase: WEEKS[i].phase, start: i, end: i }; }
          }
          groups.push(cur);
          return groups.map((g, i) => {
            const x = padL + g.start*barW;
            const gw = (g.end - g.start + 1) * barW;
            const ph = PHASES[g.phase];
            return (
              <g key={i}>
                <rect x={x+2} y={padT+innerH+22} width={gw-4} height="14" rx="2" fill={ph.color}
                  stroke={ph.dot} strokeWidth="0.5" opacity="0.7" />
                {gw > 50 && (
                  <text x={x+gw/2} y={padT+innerH+32} fontSize="9" textAnchor="middle"
                    fill="#0c1217" fontFamily="Geist Mono, monospace" letterSpacing="0.04em">
                    {ph.label.toUpperCase()}
                  </text>
                )}
              </g>
            );
          });
        })()}
      </svg>
    </section>
  );
}

function WeekCard({ wk, idx, checkedSet, onToggle, isCurrent, isFuture, isPast }) {
  const ph = PHASES[wk.phase];
  const plannedKm = wk.workouts.reduce((s,x)=>s+x.km, 0);
  const checkedKm = wk.workouts.reduce((s,x,j) => s + (checkedSet.has(`${idx}-${j}`) ? x.km : 0), 0);
  const doneAll = checkedKm === plannedKm;

  return (
    <article className={'wcard' + (isCurrent ? ' is-now' : '') + (doneAll ? ' is-done' : '')}>
      <div className="wcard-head">
        <div className="wcard-n">
          <span className="wcard-n-num">{String(wk.n).padStart(2,'0')}</span>
          {isCurrent && <span className="wcard-now-pill mono"><span className="bullet bullet-pulse" /> săptămâna curentă</span>}
        </div>
        <div className="wcard-meta">
          <div className="wcard-range">{wk.range}</div>
          <div className="wcard-phase mono" style={{ background: ph.color, color: wk.phase === 'race' ? '#fbfaf6' : '#0c1217' }}>{ph.label}</div>
        </div>
        <div className="wcard-totals">
          <div className="wcard-totals-num">
            <span className="wcard-checked">{formatKm(checkedKm)}</span>
            <span className="wcard-slash">/</span>
            <span className="wcard-planned">{formatKm(plannedKm)}</span>
          </div>
          <div className="mono wcard-totals-lab">km săpt.</div>
        </div>
      </div>

      <ul className="wcard-list">
        {wk.workouts.map((wo, j) => {
          const key = `${idx}-${j}`;
          const on = checkedSet.has(key);
          return (
            <li key={j} className={'wo' + (on ? ' wo-on' : '') + ' wo-' + wo.type}>
              <PillCheck checked={on} onClick={() => onToggle(key)} ariaLabel={wo.label}/>
              <span className="wo-type mono">{labelForType(wo.type)}</span>
              <span className="wo-label">{wo.label}</span>
              <span className="wo-km">{formatKm(wo.km)} km</span>
            </li>
          );
        })}
      </ul>

      {wk.note && <div className="wcard-note">{wk.note}</div>}
    </article>
  );
}

function labelForType(t) {
  return ({
    easy: 'easy',
    long: 'long run',
    tempo: 'tempo',
    intervale: 'intervale',
    recovery: 'recovery',
    race: 'race day',
  })[t] || t;
}

function PhasesLegend() {
  const items = Object.values(PHASES);
  return (
    <div className="legend mono">
      {items.map((p, i) => (
        <span key={i} className="legend-item">
          <span className="legend-sw" style={{ background: p.color, borderColor: p.dot }} />
          {p.label}
        </span>
      ))}
    </div>
  );
}

function Footer({ onReset }) {
  return (
    <footer className="foot">
      <div className="foot-quote">
        <div className="foot-quote-eyebrow mono"><span className="bullet" /> ținte realiste</div>
        <ul className="foot-targets">
          <li><span className="mono">iunie</span> să alergi constant fără pauze</li>
          <li><span className="mono">august</span> long run de 20+ km fără distrugere totală</li>
          <li><span className="mono">septembrie</span> încredere mentală</li>
          <li><span className="mono">octombrie</span> finish sănătos și controlat</li>
        </ul>
      </div>
      <div className="foot-right">
        <p className="foot-credo">
          Accentul acestui plan este pe <em>consistență</em>, progres lent și
          reducerea riscului de accidentare.
        </p>
        <button className="foot-reset mono" onClick={onReset}>↻ resetează progresul</button>
      </div>
    </footer>
  );
}

// ──────────────────────── app ────────────────────────────────

function App() {
  const [checked, setChecked] = useState(loadChecked);
  const now = useNow();

  useEffect(() => { saveChecked(checked); }, [checked]);

  const checkedSet = useMemo(() => new Set(Object.keys(checked).filter(k => checked[k])), [checked]);

  const totalChecked = useMemo(() => {
    let s = 0;
    WEEKS.forEach((wk, i) => wk.workouts.forEach((wo, j) => {
      if (checkedSet.has(`${i}-${j}`)) s += wo.km;
    }));
    return s;
  }, [checkedSet]);

  const checkedByWeek = useMemo(() => {
    return WEEKS.map((wk, i) => wk.workouts.reduce((s, wo, j) => s + (checkedSet.has(`${i}-${j}`) ? wo.km : 0), 0));
  }, [checkedSet]);

  const daysParts = useMemo(() => {
    const ms = RACE_DATE - now;
    const d = Math.max(0, Math.floor(ms / 86400000));
    const h = Math.max(0, Math.floor((ms % 86400000) / 3600000));
    const m = Math.max(0, Math.floor((ms % 3600000) / 60000));
    return { d, h, m };
  }, [now]);

  const weekIdxNow = currentWeekIndex(now);

  function onToggle(key) {
    setChecked(prev => ({ ...prev, [key]: !prev[key] }));
  }
  function onReset() {
    if (confirm('Sigur resetezi tot progresul?')) setChecked({});
  }

  return (
    <div className="shell">
      <TopBar />
      <Hero now={now} totalChecked={totalChecked} daysParts={daysParts} />
      <Quote />
      <ProfileChart checkedByWeek={checkedByWeek} weekIdxNow={weekIdxNow} />
      <PhasesLegend />

      <section className="weeks">
        <h2 className="section-title">Săptămânile <span className="section-sub mono">— bifează pe măsură ce le faci</span></h2>
        <div className="weeks-list">
          {WEEKS.map((wk, i) => (
            <WeekCard
              key={i}
              wk={wk}
              idx={i}
              checkedSet={checkedSet}
              onToggle={onToggle}
              isCurrent={i === weekIdxNow}
              isFuture={i > weekIdxNow}
              isPast={i < weekIdxNow}
            />
          ))}
        </div>
      </section>

      <Footer onReset={onReset} />
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
