/* ============================================================
   PROGRESS PORTFOLIO — Goals (fully custom, no category/level effect)
   Block types: streak (build/quit), number log, habit counter, photo log
   ============================================================ */
function goalStreak(goal, today) {
  const P = window.PP;
  // consecutive successful days ending today (or yesterday if today unlogged)
  let cur = today, count = 0;
  if (goal.entries[today] == null) cur = P.addDays(today, -1);
  while (true) {
    const v = goal.entries[cur];
    const ok = goal.polarity === "quit" ? v === 1 : v === 1; // 1 = success/clean
    if (v != null && ok) { count++; cur = P.addDays(cur, -1); } else break;
  }
  return count;
}
function goalBest(goal) {
  const isos = Object.keys(goal.entries).sort();
  let best = 0, run = 0, prev = null;
  isos.forEach((iso) => { if (goal.entries[iso] === 1) { run = prev && window.PP.daysBetween(prev, iso) === 1 ? run + 1 : 1; best = Math.max(best, run); prev = iso; } else { run = 0; prev = iso; } });
  return best;
}

function Goals({ me, updateMe, today }) {
  const P = window.PP;
  const [adding, setAdding] = useState(false);
  const goals = me.goals || [];
  function mutate(fn) { updateMe((m) => { m.goals = m.goals || []; fn(m.goals, m); }); }

  return (
    <div className="goals">
      <div className="ql-head">
        <div>
          <div className="ql-date">Goals</div>
          <div className="ql-quote">Your own trackers — quitting something, a weight target, a habit, daily photos. These don't touch your stats or level.</div>
        </div>
        <button className="btn btn-accent" onClick={() => setAdding(true)}>+ New goal</button>
      </div>

      {goals.length === 0 && <Empty>No goals yet. Add one — quit a habit, hit a weight, build a streak, log daily photos.</Empty>}

      <div className="goal-grid">
        {goals.map((g, gi) => <GoalCard key={g.id} goal={g} today={today}
          onLog={(iso, val) => mutate((gs) => { gs[gi].entries[iso] = val; })}
          onAddPhoto={(ph) => mutate((gs) => { gs[gi].photos = gs[gi].photos || []; gs[gi].photos.push(ph); })}
          onDelPhoto={(id) => mutate((gs) => { gs[gi].photos = (gs[gi].photos || []).filter((p) => p.id !== id); })}
          onDelete={() => { if (confirm("Delete this goal?")) mutate((gs) => gs.splice(gi, 1)); }} />)}
      </div>

      {adding && <NewGoalModal today={today} onClose={() => setAdding(false)} onCreate={(g) => { mutate((gs) => gs.push(g)); setAdding(false); }} />}
    </div>
  );
}

function GoalCard({ goal, today, onLog, onAddPhoto, onDelPhoto, onDelete }) {
  const P = window.PP;
  const fileRef = useRef(null);
  const hue = goal.hue != null ? goal.hue : 162;
  const accent = `oklch(0.82 0.15 ${hue})`;
  const last30 = []; for (let i = 29; i >= 0; i--) last30.push(P.addDays(today, -i));

  function handlePhoto(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); onAddPhoto({ id: "gp" + Date.now() + Math.random().toString(36).slice(2, 5), data: c.toDataURL("image/jpeg", 0.82), iso: today }); }; img.src = ev.target.result; };
      reader.readAsDataURL(file);
    });
  }

  const head = (
    <div className="goal-card-head">
      <div className="goal-card-title" style={{ "--gc": accent }}>{goal.name}</div>
      <button className="mini-btn" onClick={onDelete}>✕</button>
    </div>
  );

  if (goal.type === "streak") {
    const cur = goalStreak(goal, today), best = goalBest(goal);
    const todayVal = goal.entries[today];
    const totalSlips = Object.values(goal.entries).filter((v) => v === 0).length;
    return (
      <div className="goal-card" style={{ "--gc": accent }}>
        {head}
        <div className="goal-streak-big">
          <div className="gs-num mono" style={{ color: accent }}>{cur}</div>
          <div className="gs-lab">day{cur === 1 ? "" : "s"} {goal.polarity === "quit" ? "clean" : "streak"}</div>
        </div>
        <div className="chain">
          {last30.map((iso) => { const v = goal.entries[iso]; return <span key={iso} className={"chain-dot " + (v === 1 ? "ok" : v === 0 ? "miss" : "none")} title={P.prettyDate(iso)} />; })}
        </div>
        <div className="goal-card-stats mono"><span>best {best}</span><span>{goal.polarity === "quit" ? "slips" : "misses"} {totalSlips}</span></div>
        <div className="goal-log-row">
          <button className={"btn btn-sm" + (todayVal === 1 ? " btn-done" : " btn-accent")} onClick={() => onLog(today, 1)}>{goal.polarity === "quit" ? "Stayed clean" : "Did it"} today</button>
          <button className={"btn btn-sm" + (todayVal === 0 ? " btn-danger" : "")} onClick={() => onLog(today, 0)}>{goal.polarity === "quit" ? "Slipped" : "Missed"}</button>
        </div>
      </div>
    );
  }

  if (goal.type === "number") {
    const isos = Object.keys(goal.entries).sort();
    const series = isos.map((i) => goal.entries[i]);
    const latest = series.length ? series[series.length - 1] : null;
    const first = series.length ? series[0] : null;
    const delta = latest != null && first != null ? latest - first : 0;
    const [val, setVal] = useState(latest != null ? latest : "");
    let targetPct = null;
    if (goal.target != null && first != null && latest != null && goal.target !== first) targetPct = Math.max(0, Math.min(1, (first - latest) / (first - goal.target)));
    return (
      <div className="goal-card" style={{ "--gc": accent }}>
        {head}
        <div className="goal-number-row">
          <div><div className="gn-num mono" style={{ color: accent }}>{latest != null ? latest : "—"}<span className="gn-unit">{goal.unit}</span></div>{goal.target != null && <div className="gn-target mono dim">target {goal.target} {goal.unit}</div>}</div>
          {delta !== 0 && <div className={"gn-delta mono " + (delta < 0 ? "down" : "up")}>{delta > 0 ? "+" : ""}{delta.toFixed(1)}</div>}
        </div>
        <Spark data={series.length > 1 ? series : [0, 0]} h={64} hue={hue} fill />
        {targetPct != null && <Bar pct={targetPct} hue={hue} height={6} value={Math.round(targetPct * 100) + "%"} label="to target" mono />}
        <div className="goal-log-row">
          <input className="inp" type="number" step="0.1" value={val} placeholder={goal.unit} onChange={(e) => setVal(e.target.value)} />
          <button className="btn btn-sm btn-accent" onClick={() => { if (val !== "") onLog(today, Number(val)); }}>Log today</button>
        </div>
      </div>
    );
  }

  if (goal.type === "counter") {
    const wk = P.weekStart(today);
    let weekTotal = 0; Object.keys(goal.entries).forEach((iso) => { if (iso >= wk && iso <= today) weekTotal += goal.entries[iso] || 0; });
    const todayCount = goal.entries[today] || 0;
    return (
      <div className="goal-card" style={{ "--gc": accent }}>
        {head}
        <div className="goal-counter">
          <button className="ctr-btn" onClick={() => onLog(today, Math.max(0, todayCount - 1))}>−</button>
          <div className="ctr-val mono" style={{ color: accent }}>{todayCount}</div>
          <button className="ctr-btn" onClick={() => onLog(today, todayCount + 1)}>+</button>
        </div>
        <div className="goal-card-stats mono"><span>today</span></div>
        {goal.target ? <Bar pct={Math.min(1, weekTotal / goal.target)} hue={hue} height={7} label={`this week ${weekTotal} / ${goal.target}`} value={Math.round(Math.min(1, weekTotal / goal.target) * 100) + "%"} mono /> : <div className="goal-card-stats mono"><span>this week {weekTotal}</span></div>}
      </div>
    );
  }

  // photo
  const photos = (goal.photos || []).slice().reverse();
  const loggedToday = (goal.photos || []).some((p) => p.iso === today);
  return (
    <div className="goal-card" style={{ "--gc": accent }}>
      {head}
      <input ref={fileRef} type="file" accept="image/*" style={{ display: "none" }} onChange={(e) => handlePhoto(e.target.files)} />
      <div className="goal-card-stats mono"><span>{(goal.photos || []).length} photos</span>{loggedToday && <span style={{ color: accent }}>✓ today</span>}</div>
      {photos.length ? <div className="goal-photos">{photos.slice(0, 8).map((ph) => <div className="goal-photo" key={ph.id}><img src={ph.data} alt="" /><button className="photo-del" onClick={() => onDelPhoto(ph.id)}>✕</button><div className="photo-cap mono">{P.MONTHS[P.parseISO(ph.iso).getMonth()].slice(0, 3)} {P.parseISO(ph.iso).getDate()}</div></div>)}</div> : <div className="dd-photo-drop" onClick={() => fileRef.current.click()}>add your first photo</div>}
      <div className="goal-log-row"><button className="btn btn-sm btn-accent" onClick={() => fileRef.current.click()}>+ Add today's photo</button></div>
    </div>
  );
}

function NewGoalModal({ today, onClose, onCreate }) {
  const P = window.PP;
  const [type, setType] = useState("streak");
  const [name, setName] = useState("");
  const [polarity, setPolarity] = useState("quit");
  const [unit, setUnit] = useState("lb");
  const [target, setTarget] = useState("");
  const [hue, setHue] = useState(162);
  const HUES = [162, 200, 75, 295, 25, 330];
  return (
    <Modal open onClose={onClose} title="New goal"
      footer={<button className="btn btn-accent" disabled={!name.trim()} onClick={() => {
        const g = { id: "g" + Date.now(), type, name: name.trim(), hue, entries: {}, photos: [], created: today };
        if (type === "streak") g.polarity = polarity;
        if (type === "number") { g.unit = unit; if (target !== "") g.target = Number(target); }
        if (type === "counter") { g.unit = "x"; if (target !== "") g.target = Number(target); }
        onCreate(g);
      }}>Create goal</button>}>
      <div className="stack">
        <Field label="What kind of goal?">
          <div className="goaltype-grid">
            {[{ v: "streak", t: "Streak / Quit", d: "Don't break the chain" }, { v: "number", t: "Number log", d: "Weight, measurements…" }, { v: "counter", t: "Habit counter", d: "Count per day/week" }, { v: "photo", t: "Photo log", d: "Daily progress pics" }].map((o) => (
              <button key={o.v} className={"goaltype" + (type === o.v ? " on" : "")} onClick={() => setType(o.v)}><span className="gt-t">{o.t}</span><span className="gt-d">{o.d}</span></button>
            ))}
          </div>
        </Field>
        <Field label="Name"><input className="inp" autoFocus value={name} placeholder={type === "streak" ? "e.g. No vaping" : type === "number" ? "e.g. Bodyweight" : type === "counter" ? "e.g. Cold showers" : "e.g. Physique"} onChange={(e) => setName(e.target.value)} /></Field>
        {type === "streak" && <Field label="Type"><Seg options={[{ value: "quit", label: "Quit (stay clean)" }, { value: "build", label: "Build (do daily)" }]} value={polarity} onChange={setPolarity} /></Field>}
        {type === "number" && <div className="row2"><Field label="Unit"><input className="inp" value={unit} onChange={(e) => setUnit(e.target.value)} /></Field><Field label="Target (optional)"><input className="inp" type="number" value={target} onChange={(e) => setTarget(e.target.value)} /></Field></div>}
        {type === "counter" && <Field label="Weekly goal (optional)"><input className="inp" type="number" value={target} onChange={(e) => setTarget(e.target.value)} /></Field>}
        <Field label="Color"><div className="hue-row">{HUES.map((h) => <button key={h} className={"hue-dot" + (hue === h ? " on" : "")} style={{ background: `oklch(0.82 0.15 ${h})` }} onClick={() => setHue(h)} />)}</div></Field>
      </div>
    </Modal>
  );
}

Object.assign(window, { Goals, goalStreak, goalBest });
