/* eslint-disable no-undef */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* =========================================================
   STORAGE
   ========================================================= */
const LS_FRIENDS = "porco.friends.v1";
const LS_LOGS    = "porco.logs.v1";

const DEFAULT_FRIENDS = [
  { id: "f_you",  name: "You",   color: "#FCD86A" },
  { id: "f_pal1", name: "Pal",   color: "#EE6388" },
  { id: "f_pal2", name: "Bestie", color: "#7EE0C5" },
];

const loadJSON = (k, fb) => {
  try { const v = JSON.parse(localStorage.getItem(k)); return v == null ? fb : v; } catch { return fb; }
};
const saveJSON = (k, v) => { try { localStorage.setItem(k, JSON.stringify(v)); } catch {} };

/* =========================================================
   DATE HELPERS — pick the active week from today.
   The system date is set to 2026-05-15 for this build but the
   logic works for any date.
   ========================================================= */
function findCurrentWeekIdx(weeks, today = new Date()) {
  // First, any week where start ≤ today ≤ end
  for (let i = 0; i < weeks.length; i++) {
    const s = new Date(weeks[i].start + "T00:00:00");
    const e = new Date(weeks[i].end + "T23:59:59");
    if (today >= s && today <= e) return i;
  }
  // Else: next upcoming week
  for (let i = 0; i < weeks.length; i++) {
    if (today < new Date(weeks[i].start + "T00:00:00")) return i;
  }
  // Else: most recent past
  return weeks.length - 1;
}

/* =========================================================
   APP
   ========================================================= */
function App() {
  const weeks = window.WEEKS;
  const [friends, setFriends] = useState(() => loadJSON(LS_FRIENDS, DEFAULT_FRIENDS));
  const [logs, setLogs] = useState(() => loadJSON(LS_LOGS, {}));
  const [activeTab, setActiveTab] = useState("now"); // "now" | "season"
  const [manageOpen, setManageOpen] = useState(false);
  const [editing, setEditing] = useState(null); // { weekId, friendId }
  const [sort, setSort] = useState("chrono"); // "chrono" | "rated" | "visited"

  useEffect(() => saveJSON(LS_FRIENDS, friends), [friends]);
  useEffect(() => saveJSON(LS_LOGS, logs), [logs]);

  const currentIdx = useMemo(() => findCurrentWeekIdx(weeks), [weeks]);
  const currentWeek = weeks[currentIdx];
  const todayISO = useMemo(() => new Date().toISOString().slice(0, 10), []);

  // ---- mutate helpers ----
  const updateEntry = useCallback((weekId, friendId, patch) => {
    setLogs(prev => {
      const next = { ...prev };
      next[weekId] = { ...(next[weekId] || {}) };
      next[weekId][friendId] = { ...(next[weekId][friendId] || {}), ...patch, ts: Date.now() };
      return next;
    });
  }, []);

  const deleteEntry = useCallback((weekId, friendId) => {
    setLogs(prev => {
      const next = { ...prev };
      if (!next[weekId]) return prev;
      const { [friendId]: _, ...rest } = next[weekId];
      if (Object.keys(rest).length === 0) {
        delete next[weekId];
      } else {
        next[weekId] = rest;
      }
      return next;
    });
  }, []);

  const onPickFriend = (weekId, friendId) => {
    setEditing(prev =>
      prev && prev.weekId === weekId && prev.friendId === friendId
        ? null
        : { weekId, friendId }
    );
  };

  // ---- tweaks ----
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "theme": "indigo",
    "density": "comfy",
    "drips": "on",
    "sort": "chrono"
  }/*EDITMODE-END*/;
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  useEffect(() => {
    document.body.dataset.theme = t.theme;
    document.body.dataset.density = t.density;
    document.body.dataset.drips = t.drips;
  }, [t.theme, t.density, t.drips]);

  // Sort weeks for the season list
  const sortedWeeks = useMemo(() => {
    const arr = [...weeks];
    if (t.sort === "rated") {
      const score = (w) => {
        const wl = logs[w.id];
        if (!wl) return -1;
        const ratings = Object.values(wl).map(e => e.stars || 0).filter(s => s > 0);
        if (!ratings.length) return -1;
        return ratings.reduce((a,b) => a + b, 0) / ratings.length;
      };
      arr.sort((a, b) => score(b) - score(a));
    } else if (t.sort === "visited") {
      const has = (w) => logs[w.id] && Object.values(logs[w.id]).some(e => e.stars || e.flavors?.length || e.comment);
      arr.sort((a, b) => Number(has(b)) - Number(has(a)));
    } else {
      // chrono
    }
    return arr;
  }, [weeks, logs, t.sort]);

  return (
    <>
      <div className="poster-border" aria-hidden="true" />
      <svg width="0" height="0" style={{ position: "absolute" }} aria-hidden="true">
        <defs>
          <filter id="wobble">
            <feTurbulence baseFrequency="0.015" numOctaves="2" seed="3"/>
            <feDisplacementMap in="SourceGraphic" scale="3"/>
          </filter>
        </defs>
      </svg>

      <div className="app">
        <Header />
        <Tabs active={activeTab} onChange={setActiveTab} />

        {activeTab === "now" && (
          <NowView
            week={currentWeek}
            friends={friends}
            weekLogs={logs[currentWeek.id]}
            editing={editing}
            onPickFriend={(fid) => onPickFriend(currentWeek.id, fid)}
            onChange={(fid, patch) => updateEntry(currentWeek.id, fid, patch)}
            onDelete={(fid) => { deleteEntry(currentWeek.id, fid); setEditing(null); }}
            onCloseEntry={() => setEditing(null)}
            onManageFriends={() => setManageOpen(true)}
            currentIdx={currentIdx}
            totalWeeks={weeks.length}
          />
        )}

        {activeTab === "season" && (
          <SeasonView
            weeks={sortedWeeks}
            currentWeekId={currentWeek.id}
            todayISO={todayISO}
            friends={friends}
            logs={logs}
            editing={editing}
            onPickFriend={onPickFriend}
            onChange={updateEntry}
            onDelete={(wid, fid) => { deleteEntry(wid, fid); setEditing(null); }}
            onCloseEntry={() => setEditing(null)}
            onManageFriends={() => setManageOpen(true)}
            sortLabel={t.sort}
          />
        )}

        <Legend />
      </div>

      {manageOpen && (
        <ManageFriendsModal
          friends={friends}
          onClose={() => setManageOpen(false)}
          onSave={setFriends}
        />
      )}

      <TweaksPanel title="Tweaks">
        <TweakSection label="Look">
          <TweakRadio label="Theme" value={t.theme} onChange={(v) => setTweak("theme", v)} options={[
            { value: "indigo", label: "Indigo" },
            { value: "midnight", label: "Midnight" },
            { value: "cherry", label: "Cherry" },
            { value: "pistachio", label: "Pistachio" },
          ]} />
          <TweakRadio label="Density" value={t.density} onChange={(v) => setTweak("density", v)} options={[
            { value: "comfy", label: "Comfy" },
            { value: "compact", label: "Compact" },
          ]} />
          <TweakRadio label="Drips" value={t.drips} onChange={(v) => setTweak("drips", v)} options={[
            { value: "off", label: "Off" },
            { value: "on", label: "Subtle" },
            { value: "heavy", label: "Heavy" },
          ]} />
        </TweakSection>
        <TweakSection label="Season list">
          <TweakSelect label="Sort by" value={t.sort} onChange={(v) => setTweak("sort", v)} options={[
            { value: "chrono", label: "Chronological" },
            { value: "rated", label: "Highest rated" },
            { value: "visited", label: "Visited first" },
          ]} />
        </TweakSection>
        <TweakSection label="Danger">
          <TweakButton label="Reset all logs" onClick={() => { if (confirm("Clear all logs?")) { setLogs({}); } }} />
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

/* =========================================================
   Header lockup
   ========================================================= */
function Header() {
  return (
    <header className="hero-head">
      <div className="title-lockup">
        <Drip className="left" />
        <h1 className="title-main">Soft Serve</h1>
        <div className="title-sub">TRACKER · ’26</div>
        <div className="title-dots"><i/><i/><i/><i/><i/><i/></div>
        <Drip className="right" />
      </div>
    </header>
  );
}

/* =========================================================
   Tabs
   ========================================================= */
function Tabs({ active, onChange }) {
  return (
    <div className="tab-row">
      <button className={active === "now" ? "active" : ""} onClick={() => onChange("now")}>This week</button>
      <button className={active === "season" ? "active" : ""} onClick={() => onChange("season")}>Full season</button>
    </div>
  );
}

/* =========================================================
   NOW VIEW
   ========================================================= */
function NowView({ week, friends, weekLogs, editing, onPickFriend, onChange, onDelete, onCloseEntry, onManageFriends, currentIdx, totalWeeks }) {
  const activeFriend = editing && friends.find(f => f.id === editing.friendId);
  return (
    <section>
      <div className="now-card">
        <p className="now-week-range">{week.range}</p>
        <p className="now-week-meta">Week {currentIdx + 1} of {totalWeeks}</p>

        {week.flavors.map(f => (
          <div key={f.name} className="flavor">
            <div className="flavor-head">
              <span className="flavor-name">{f.name}</span>
              <Badges gf={f.gf} v={f.v} />
            </div>
          </div>
        ))}

        <div className="topping-row">
          <span className="label">+ topping</span>
          <span className="name">{week.topping.name}</span>
          <Badges gf={week.topping.gf} v={week.topping.v} />
        </div>

        <FriendStrip
          friends={friends}
          weekLogs={weekLogs}
          activeFriendId={editing?.friendId}
          onPickFriend={onPickFriend}
          onManageFriends={onManageFriends}
        />

        {editing && activeFriend && (
          <EntryCard
            week={week}
            friend={activeFriend}
            entry={weekLogs?.[activeFriend.id] || {}}
            onChange={(patch) => onChange(activeFriend.id, patch)}
            onDelete={() => onDelete(activeFriend.id)}
            onClose={onCloseEntry}
          />
        )}
      </div>

      <div className="section-label">Notes &amp; ratings</div>
      <NotesPreview weekLogs={weekLogs} friends={friends} />
    </section>
  );
}

function NotesPreview({ weekLogs, friends }) {
  const entries = Object.entries(weekLogs || {}).filter(([_, e]) => e && (e.stars || e.comment || e.flavors?.length));
  if (!entries.length) {
    return <p className="empty-friends">No one's logged this week yet — tap a friend chip above to start.</p>;
  }
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10, marginBottom: 16 }}>
      {entries.map(([fid, e]) => {
        const f = friends.find(x => x.id === fid);
        if (!f) return null;
        return (
          <div key={fid} style={{
            display: "flex", gap: 10, padding: "10px 12px",
            background: "rgba(255,255,255,0.04)",
            border: "1.5px solid var(--line)",
            borderRadius: 14,
          }}>
            <Avatar friend={f} size={32} />
            <div style={{ flex: 1 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <span style={{ fontFamily: "var(--f-hand)", fontSize: 19, color: "var(--cream)" }}>{f.name}</span>
                {e.stars > 0 && <MiniStars value={e.stars} />}
              </div>
              {e.flavors?.length > 0 && (
                <div style={{ fontFamily: "var(--f-body)", fontSize: 12, color: "var(--cream)", opacity: 0.65, letterSpacing: 0.4, marginTop: 2 }}>
                  Got: {e.flavors.join(" + ")}
                  {e.topping && " + topping"}
                  {e.sprinkles && " + sprinkles"}
                </div>
              )}
              {e.comment && (
                <p style={{ margin: "6px 0 0", fontFamily: "var(--f-hand)", fontSize: 17, color: "var(--white-soft)", lineHeight: 1.3 }}>
                  “{e.comment}”
                </p>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

/* =========================================================
   SEASON VIEW
   ========================================================= */
function SeasonView({ weeks, currentWeekId, todayISO, friends, logs, editing, onPickFriend, onChange, onDelete, onCloseEntry, onManageFriends, sortLabel }) {
  return (
    <section>
      <div className="section-label">2026 season</div>
      <div className="season-list">
        {weeks.map(w => {
          const isCurrent = w.id === currentWeekId;
          const isPast = w.end < todayISO && !isCurrent;
          const isEditingHere = editing?.weekId === w.id;
          return (
            <React.Fragment key={w.id}>
              <WeekRow
                week={w}
                isCurrent={isCurrent}
                isPast={isPast}
                friends={friends}
                weekLogs={logs[w.id]}
                onTap={() => onPickFriend(w.id, editing?.weekId === w.id && editing?.friendId ? editing.friendId : friends[0].id)}
              />
              {isEditingHere && (
                <div style={{ marginTop: 6, marginBottom: 14 }}>
                  <FriendStrip
                    friends={friends}
                    weekLogs={logs[w.id]}
                    activeFriendId={editing.friendId}
                    onPickFriend={(fid) => onPickFriend(w.id, fid)}
                    onManageFriends={onManageFriends}
                  />
                  {editing.friendId && (() => {
                    const f = friends.find(x => x.id === editing.friendId);
                    if (!f) return null;
                    return (
                      <EntryCard
                        week={w}
                        friend={f}
                        entry={logs[w.id]?.[f.id] || {}}
                        onChange={(patch) => onChange(w.id, f.id, patch)}
                        onDelete={() => onDelete(w.id, f.id)}
                        onClose={onCloseEntry}
                      />
                    );
                  })()}
                </div>
              )}
            </React.Fragment>
          );
        })}
      </div>
    </section>
  );
}

/* =========================================================
   Legend (matches poster footer)
   ========================================================= */
function Legend() {
  return (
    <div className="legend">
      <div className="sprinkle-line">🌈 RAINBOW SPRINKLES ALWAYS AVAILABLE 🌈</div>
      <div className="key">
        <b className="gf">GF</b> Gluten-Free &nbsp;·&nbsp; <b className="vg">VG</b> Vegan
      </div>
    </div>
  );
}

/* =========================================================
   Patch: useTweaks doesn't return setTweak inline on object —
   provide a small wrapper so we can call t.setTweak() above.
   ========================================================= */
// useTweaks is already a hook from tweaks-panel.jsx; just make sure we use it.
// (no-op — useTweaks already returns the tweaks object with `setTweak` attached if the starter exposes it.)

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
