/* ============================================================
   PROGRESS PORTFOLIO v2 — Profile / Character sheet
   ============================================================ */
function scoresAsOf(profile, date) {
  const P = window.PP;
  const out = {}; P.CAT_ORDER.forEach((c) => (out[c] = 0));
  P.profileContribs(profile).forEach((c) => {
    if (c.iso > date) return;
    const age = P.daysBetween(c.iso, date);
    if (age < 0) return;
    out[c.cat] += c.value * Math.pow(P.decayFactor(c.cat), age);
  });
  return out;
}
function powerAsOf(profile, date) {
  const P = window.PP; const s = scoresAsOf(profile, date);
  return P.CAT_ORDER.reduce((a, c) => a + P.catLevel(s[c]).level, 0);
}

function Character({ me, updateMe, state, today }) {
  const P = window.PP;
  const [editOpen, setEditOpen] = useState(false);
  const physRef = useRef(null);
  const scores = P.decayedScores(me, today);        // includes seed — drives level + bar
  const scoresPrev = P.decayedScores(me, P.addDays(today, -7));
  const rawScores = scoresAsOf(me, today);           // actual logged activity only — drives footer text
  const lvl = P.profileLevel(me);
  const pow = P.power(me, today);
  const strk = P.streak(me, today);
  const best = P.bestStreak(me);
  const workouts = P.countWorkouts(me);
  const money = P.moneyTotals(me, today);
  const rows = P.leaderboard(state, today);
  const myRank = rows.find((r) => r.isMe);
  const achv = P.evalAchievements(me, today);
  const achvCount = achv.filter((a) => a.got).length;

  // power over last 14 days
  const powSeries = []; for (let i = 13; i >= 0; i--) { const ds = P.decayedScores(me, P.addDays(today, -i)); powSeries.push(P.CAT_ORDER.reduce(function(a,c){ return a + P.catLevel(ds[c]).level; }, 0)); }
  const compBars = []; for (let i = 13; i >= 0; i--) { const iso = P.addDays(today, -i); const r = me.days[iso]; compBars.push({ label: P.WEEKDAY_NAMES[P.weekday(iso)][0], v: r ? Math.round(P.dayCompletion(r) * 100) : 0 }); }

  function uploadPhysique(files) {
    Array.from(files).forEach((file) => {
      const reader = new FileReader();
      reader.onload = (ev) => {
        const img = new Image();
        img.onload = () => {
          const max = 900; let { width, height } = img;
          if (width > max || height > max) { const s = max / Math.max(width, height); width *= s; height *= s; }
          const c = document.createElement("canvas"); c.width = width; c.height = height; c.getContext("2d").drawImage(img, 0, 0, width, height);
          updateMe((m) => m.physiquePhotos.push({ id: "phys" + Date.now() + Math.random().toString(36).slice(2, 5), data: c.toDataURL("image/jpeg", 0.82), caption: "", iso: today }));
        };
        img.src = ev.target.result;
      };
      reader.readAsDataURL(file);
    });
  }

  return (
    <div className="char">
      <Card glow className="char-hero">
        <div className="char-hero-grid">
          <div className="char-hero-left">
            <Avatar profile={me} size={88} />
            <Ring pct={lvl.pct} size={120} stroke={9}><div className="lvl-inner"><div className="lvl-lab">LEVEL</div><div className="lvl-num mono">{lvl.level}</div></div></Ring>
          </div>
          <div className="char-meta">
            <div className="char-name-row"><div className="char-name">{me.meta.name}</div><button className="mini-btn" onClick={() => setEditOpen(true)}>edit profile</button></div>
            <div className="char-bio">{me.meta.bio || "Set a bio in edit profile."}</div>
            <div className="char-vitals mono">
              {me.meta.height && <span>{me.meta.height}</span>}{me.meta.weight && <span>{me.meta.weight}</span>}{me.meta.age && <span>{me.meta.age} yrs</span>}
              <span className="dim">Day {Math.max(1, P.daysBetween(me.meta.createdISO, today) + 1)}</span>
            </div>
            <div className="char-xpbar"><Bar pct={lvl.pct} value={`${Math.round(lvl.into)} / ${Math.round(lvl.span)}`} label="TO NEXT LEVEL" mono height={11} /></div>
            <div className="char-quickstats">
              <Qs n={pow} l="power" hot />
              <Qs n={"#" + (myRank ? myRank.rank : "?")} l="rank" />
              <Qs n={strk} l="streak" hot={strk >= 3} />
              <Qs n={best} l="best" />
              <Qs n={workouts} l="workouts" />
              <Qs n={"$" + money.total.toLocaleString()} l="earned" />
              <Qs n={achvCount} l="achievements" />
            </div>
          </div>
        </div>
      </Card>

      <Card title="Attributes — current form (decays without input)">
        <div className="attrs">
          {P.CAT_ORDER.map((c) => {
            const cl = P.catLevel(scores[c]);
            const trend = scores[c] - scoresPrev[c];
            const dir = trend > scores[c] * 0.04 ? "up" : trend < -scores[c] * 0.04 ? "down" : "flat";
            return (
              <div className="attr" key={c} style={{ "--ah": `oklch(0.82 0.15 ${P.CATS[c].hue})` }}>
                <div className="attr-head">
                  <span className="attr-key">{c}</span>
                  <span className={"attr-trend " + dir}>{dir === "up" ? "▲" : dir === "down" ? "▼ fading" : "▬"}</span>
                  <span className="attr-lvl mono">Lv {cl.level}</span>
                </div>
                <div className="attr-name">{P.CATS[c].name}</div>
                <Bar pct={cl.pct} hue={P.CATS[c].hue} height={7} />
                <div className="attr-foot mono dim">{Math.round(rawScores[c]).toLocaleString()} {P.CATS[c].unit} · {P.CATS[c].blurb}</div>
              </div>
            );
          })}
        </div>
      </Card>

      <div className="char-charts">
        <Card title="Power — last 14 days"><Spark data={powSeries} h={90} fill /><div className="chart-cap mono dim">current power {pow}</div></Card>
        <Card title="Daily completion %"><BarChart data={compBars} h={110} /></Card>
      </div>

      <Card title="Physique" right={<button className="btn btn-sm" onClick={() => physRef.current.click()}>+ Add photo</button>}>
        <input ref={physRef} type="file" accept="image/*" multiple style={{ display: "none" }} onChange={(e) => uploadPhysique(e.target.files)} />
        {me.physiquePhotos && me.physiquePhotos.length > 0 ? (
          <div className="phys-grid">
            {me.physiquePhotos.slice().reverse().map((ph) => (
              <div className="phys-photo" key={ph.id}>
                <img src={ph.data} alt="" />
                <button className="photo-del" onClick={() => updateMe((m) => (m.physiquePhotos = m.physiquePhotos.filter((x) => x.id !== ph.id)))}>✕</button>
                <div className="photo-cap mono">{ph.iso ? P.MONTHS[P.parseISO(ph.iso).getMonth()].slice(0, 3) + " " + P.parseISO(ph.iso).getDate() : ""}{ph.caption ? " · " + ph.caption : ""}</div>
              </div>
            ))}
          </div>
        ) : <div className="dd-photo-drop" onClick={() => physRef.current.click()}>add physique progress photos</div>}
      </Card>

      <Card title={`Achievements · ${achvCount} / ${achv.length}`}>
        <div className="achv-groups">
          {P.ACH_GROUPS.map((g) => {
            const items = achv.filter((a) => a.group === g);
            if (!items.length) return null;
            const got = items.filter((a) => a.got).length;
            const next = items.find((a) => !a.got);
            return (
              <div className="achv-group" key={g}>
                <div className="achv-group-head">
                  <span className="achv-group-name">{items[0].icon} {g}</span>
                  <span className="mono dim">{got}/{items.length}</span>
                </div>
                <div className="achv-tiers">
                  {items.map((a) => (
                    <div className={"achv-tier" + (a.got ? " got" : "")} key={a.id} title={a.desc}>
                      <span className="achv-tier-name">{a.name}</span>
                      <span className="achv-tier-desc mono">{a.desc}</span>
                    </div>
                  ))}
                </div>
                {next && <div className="achv-next mono dim">next: {next.name} — {Math.round(next.value).toLocaleString()}/{next.threshold.toLocaleString()}</div>}
              </div>
            );
          })}
        </div>
      </Card>

      {editOpen && <EditProfileModal me={me} updateMe={updateMe} onClose={() => setEditOpen(false)} />}
    </div>
  );
}

function Qs({ n, l, hot }) { return <div className={"qs" + (hot ? " qs-hot" : "")}><div className="qs-n mono">{n}</div><div className="qs-l">{l}</div></div>; }

function EditProfileModal({ me, updateMe, onClose }) {
  const [m, setM] = useState({ ...me.meta });
  const avRef = useRef(null);
  function uploadAvatar(file) {
    const reader = new FileReader();
    reader.onload = (ev) => {
      const img = new Image();
      img.onload = () => {
        const s = 200; const c = document.createElement("canvas"); c.width = s; c.height = s;
        const ctx = c.getContext("2d"); const min = Math.min(img.width, img.height);
        ctx.drawImage(img, (img.width - min) / 2, (img.height - min) / 2, min, min, 0, 0, s, s);
        setM((mm) => ({ ...mm, avatar: c.toDataURL("image/jpeg", 0.85) }));
      };
      img.src = ev.target.result;
    };
    reader.readAsDataURL(file);
  }
  return (
    <Modal open onClose={onClose} title="Edit profile"
      footer={<button className="btn btn-accent" onClick={() => { updateMe((x) => (x.meta = { ...x.meta, ...m })); onClose(); }}>Save</button>}>
      <div className="stack">
        <div className="row-inline" style={{ alignItems: "center", gap: 14 }}>
          <Avatar profile={{ meta: m }} size={64} />
          <button className="btn btn-sm" onClick={() => avRef.current.click()}>Upload photo</button>
          <input ref={avRef} type="file" accept="image/*" style={{ display: "none" }} onChange={(e) => e.target.files[0] && uploadAvatar(e.target.files[0])} />
        </div>
        <Field label="Name"><input className="inp" value={m.name} onChange={(e) => setM({ ...m, name: e.target.value })} /></Field>
        <div className="row2">
          <Field label="Height"><input className="inp" value={m.height} placeholder={"6'1\""} onChange={(e) => setM({ ...m, height: e.target.value })} /></Field>
          <Field label="Weight"><input className="inp" value={m.weight} placeholder="182 lb" onChange={(e) => setM({ ...m, weight: e.target.value })} /></Field>
        </div>
        <Field label="Age"><input className="inp" type="number" value={m.age} onChange={(e) => setM({ ...m, age: e.target.value })} /></Field>
        <Field label="Bio"><textarea className="ta" rows={2} value={m.bio} placeholder="Your one-liner…" onChange={(e) => setM({ ...m, bio: e.target.value })} /></Field>
      </div>
    </Modal>
  );
}

Object.assign(window, { Character, EditProfileModal, scoresAsOf, powerAsOf });
