/* Onboarding flow: unified, sport-agnostic team selector. Walks the user
 * through every sport in window.SPORTS — favorite, then optional rivals —
 * fetching each sport's team data on demand as the user reaches it (see
 * window.W2R4_loadSportData in src/data.js). Lives at "/" (src/app.jsx's
 * HomeRoute), never nested under a sport-specific path. */

const { useState, useEffect, useCallback } = React;

// Lazily fetches a sport's team data the first time it's requested this
// onboarding session and caches {status, data} per sport id.
function useSportDataCache() {
  const [cache, setCache] = useState({});
  const request = useCallback((sportId) => {
    setCache((prev) => {
      if (prev[sportId] && prev[sportId].status !== "error") return prev;
      return { ...prev, [sportId]: { status: "loading", data: null } };
    });
    window.W2R4_loadSportData(sportId).then((data) => {
      setCache((prev) => ({ ...prev, [sportId]: { status: "ready", data } }));
    }).catch((err) => {
      setCache((prev) => ({ ...prev, [sportId]: { status: "error", data: null, error: err } }));
    });
  }, []);
  return [cache, request];
}

function TeamSlot({ label, team, kind = "favorite" }) {
  if (!team) {
    return (
      <div className="onb-slot onb-slot-empty">
        <span>{label}</span>
      </div>);

  }
  return (
    <div className={"onb-slot filled " + kind} style={{ background: team.color }} title={`${label}: ${team.title}`}>
      {team.abbr}
      <span className="onb-slot-badge">{kind === "favorite" ? "★" : "✕"}</span>
    </div>);

}

function Onboarding({ initialBySport, startSport, onFinish }) {
  const order = window.SPORTS.map((s) => s.id);
  const startIdx = Math.max(0, order.indexOf(startSport));

  const [picks, setPicks] = useState(() => ({ ...(initialBySport || {}) }));
  const [sportIndex, setSportIndex] = useState(startIdx);
  const [phase, setPhase] = useState("favorite"); // 'favorite' | 'rivals' | 'done'
  const [fav, setFav] = useState(() => initialBySport?.[order[startIdx]]?.favTeam || null);
  const [dislikes, setDislikes] = useState(() => new Set(initialBySport?.[order[startIdx]]?.dislikes || []));
  const [cache, requestSportData] = useSportDataCache();

  const currentId = order[sportIndex];
  const sport = window.SPORTS[sportIndex];
  const sportData = cache[currentId];
  const ready = sportData?.status === "ready";

  useEffect(() => {
    if (!cache[currentId]) requestSportData(currentId);
  }, [currentId]);

  // Re-sync the local editing buffer whenever the current sport changes
  // (covers both forward advance and a logo-click jump).
  useEffect(() => {
    setFav(picks[currentId]?.favTeam || null);
    setDislikes(new Set(picks[currentId]?.dislikes || []));
  }, [currentId]);

  useEffect(() => {
    window.scrollTo({ top: 0, behavior: "auto" });
    document.documentElement.scrollTop = 0;
    document.body.scrollTop = 0;
    const shell = document.querySelector(".onb-shell");
    if (shell) shell.scrollTop = 0;
  }, [currentId, phase]);

  const toggleDislike = (abbr) => {
    setDislikes((prev) => {
      const next = new Set(prev);
      if (next.has(abbr)) next.delete(abbr);else next.add(abbr);
      return next;
    });
  };

  // teamFor() lets the header badges render for a sport whose data hasn't
  // been fetched this session (e.g. re-opening onboarding on Football while
  // Baseball was decided last visit) — falls back to the static, fetch-free
  // color table instead of blocking on a fetch just to paint a circle.
  const teamFor = (sportId, abbr) => {
    if (!abbr) return null;
    const cachedTeam = cache[sportId]?.data?.TEAMS?.[abbr];
    if (cachedTeam) {
      return { abbr, color: cachedTeam.color, title: `${cachedTeam.city} ${cachedTeam.name}`.trim() || abbr };
    }
    const bundle = window.W2R4_getLeague ? window.W2R4_getLeague(sportId) : null;
    return { abbr, color: bundle?.TEAM_COLOR_FALLBACK?.[abbr] || "#999999", title: abbr };
  };

  // Always walks to the next sport in cyclic order, even if it was already
  // decided in an earlier session — re-editing one sport shouldn't silently
  // skip the rest. Once the walk laps back to where it started, every sport
  // has been visited this pass; stop and let the user pick where to land
  // instead of guessing for them.
  const advance = (updatedPicks) => {
    const nextIdx = (sportIndex + 1) % order.length;
    if (nextIdx === startIdx) {
      const finalPicks = { ...updatedPicks };
      for (const id of order) if (!(id in finalPicks)) finalPicks[id] = { favTeam: null, dislikes: [] };
      setPicks(finalPicks);
      setPhase("done");
      return;
    }
    setSportIndex(nextIdx);
    setPhase("favorite");
  };

  const handleSkip = () => {
    if (phase === "favorite") {
      // Skipping the favorite step skips the sport entirely — rivals can't
      // be picked without a favorite.
      const updated = { ...picks, [currentId]: { favTeam: null, dislikes: [] } };
      setPicks(updated);
      advance(updated);
    } else {
      // Skipping rivals keeps the already-chosen favorite, discards toggles.
      const updated = { ...picks, [currentId]: { favTeam: fav, dislikes: [] } };
      setPicks(updated);
      advance(updated);
    }
  };

  const handleNext = () => {
    if (phase === "favorite") {
      setPhase("rivals");
      return;
    }
    const updated = { ...picks, [currentId]: { favTeam: fav, dislikes: Array.from(dislikes) } };
    setPicks(updated);
    advance(updated);
  };

  const jumpToSport = (targetId) => {
    const targetIdx = order.indexOf(targetId);
    if (targetIdx === sportIndex) { setPhase("favorite"); return; }
    const lo = Math.min(sportIndex, targetIdx);
    const hi = Math.max(sportIndex, targetIdx);
    setPicks((prev) => {
      const next = { ...prev };
      for (let i = lo + 1; i < hi; i++) {
        const id = order[i];
        if (!(id in next)) next[id] = { favTeam: null, dislikes: [] };
      }
      return next;
    });
    setSportIndex(targetIdx);
    setPhase("favorite");
  };

  // Primary button label: what the *next* step is, e.g. "Football Rivals",
  // "Baseball Favorites", or "Continue" once every sport has been visited.
  let nextLabel;
  if (phase === "favorite") {
    nextLabel = `${sport.name} Rivals`;
  } else {
    const nextIdx = (sportIndex + 1) % order.length;
    nextLabel = nextIdx === startIdx ? "Continue" : `${window.SPORTS[nextIdx].name} Favorites`;
  }

  const isFav = phase === "favorite";
  const TEAMS = sportData?.data?.TEAMS;
  const sortedDivisions = ready ?
  sportData.data.LEAGUE.conferences.flatMap(
    (c) => sportData.data.LEAGUE.divisionOrder.map((d) => `${c} ${d}`)) :
  [];

  const handleTileClick = (abbr) => {
    if (isFav) {
      setFav(abbr);
    } else {
      if (!fav) return;
      const favDivision = TEAMS[fav]?.div;
      const favConference = TEAMS[fav]?.conf;
      const inSameDiv = TEAMS[abbr]?.div === favDivision && TEAMS[abbr]?.conf === favConference;
      if (abbr === fav || inSameDiv) return; // cannot dislike own team or division
      toggleDislike(abbr);
    }
  };

  return (
    <div className="onb-shell">
      <div className="onb-inner">
        <div className="onb-header">
          <div className="onb-wordmark">
            Who2Root4<sup className="w2r4-tm">TM</sup>
          </div>
          <div className="onb-sport-rows">
            {window.SPORTS.map((s, i) => {
              const isCurrent = i === sportIndex;
              const pick = isCurrent ? { favTeam: fav, dislikes: Array.from(dislikes) } : picks[s.id];
              return (
                <div key={s.id} className={"onb-sport-row" + (isCurrent ? " active" : "")}>
                  <button
                    type="button"
                    className="onb-sport-logo"
                    onClick={() => jumpToSport(s.id)}
                    title={s.name}
                    aria-current={isCurrent}>

                    <s.Icon size={22} />
                  </button>
                  <div className="onb-slots">
                    <TeamSlot label="Favorite" kind="favorite" team={teamFor(s.id, pick?.favTeam)} />
                    {pick?.favTeam &&
                    (pick.dislikes && pick.dislikes.length ?
                    pick.dislikes.map((abbr) =>
                    <TeamSlot key={abbr} label="Rival" kind="rival" team={teamFor(s.id, abbr)} />) :

                    <TeamSlot label="Rivals" team={null} />)
                    }
                  </div>
                </div>);

            })}
          </div>
        </div>

        {phase === "done" ?
        <div className="onb-done">
            <h1 className="onb-title">Select your sport</h1>
            <p className="onb-sub">Your picks are saved — jump into whichever league you want to see first.</p>
            <div className="onb-sport-pick-row">
              {window.SPORTS.map((s) => (
                <button key={s.id} type="button" className="onb-sport-pick" onClick={() => onFinish(picks, s.id)}>
                  <s.Icon size={36} />
                  <span>{s.name}</span>
                </button>
              ))}
            </div>
          </div> :

        !ready ?
        <div className="onb-loading">
            <div className="w2r4-boot-bar"><span /></div>
            <p>
              {sportData?.status === "error" ?
              <>Couldn't load {sport.name} teams. <button className="link-btn" onClick={() => requestSportData(currentId)}>Retry</button></> :

              `Loading ${sport.name} teams…`}
            </p>
          </div> :

        <>
            <h1 className="onb-title">
              {isFav ? `Who's your ${sport.name} team?` : `Choose your ${sport.name} rivals`}
            </h1>
            <p className="onb-sub">
              {isFav ?
            "We'll use this to figure out which other games actually matter to you each week." :
            "Optional. Choose teams you like to see lose. You can change this anytime."}
            </p>

            <div className="onb-actions onb-actions-top">
              <span className="helper">
                {isFav ?
              fav ? `${TEAMS[fav].city} ${TEAMS[fav].name}` : "" :
              `${dislikes.size} team${dislikes.size === 1 ? "" : "s"} you like to root against`}
              </span>
              <div style={{ display: "flex", gap: 8 }}>
                {!isFav &&
              <button className="btn ghost" onClick={() => setPhase("favorite")}>Back</button>
              }
                <button className="btn ghost" onClick={handleSkip}>Skip</button>
                <button className="btn primary" onClick={handleNext} disabled={isFav && !fav}>
                  {nextLabel}
                  <span style={{ fontSize: 11, opacity: 0.9 }}>→</span>
                </button>
              </div>
            </div>

            {sortedDivisions.map((div, divIdx) => {
            const [conf, divName] = div.split(" ");
            const rawAbbrs = sportData.data.TEAMS_BY_DIVISION[`${conf} ${divName}`] || [];
            const abbrs = rawAbbrs.slice().sort((a, b) => {
              const ta = TEAMS[a],tb = TEAMS[b];
              const aP = ta.record[0] / Math.max(1, ta.record[0] + ta.record[1]);
              const bP = tb.record[0] / Math.max(1, tb.record[0] + tb.record[1]);
              return bP - aP || tb.record[0] - ta.record[0];
            });
            const favDiv = fav ? TEAMS[fav]?.div : null;
            const favConf = fav ? TEAMS[fav]?.conf : null;
            return (
              <div className="div-section" key={div}>
                  <h4>{conf} {divName}</h4>
                  {/* Columns follow the division size so every team sits on one row —
                  4 across for the NFL, 5 for MLB. */}
                  <div className="team-grid" style={{ gridTemplateColumns: `repeat(${abbrs.length}, minmax(0, 1fr))` }}>
                    {abbrs.map((abbr, i) => {
                    const t = TEAMS[abbr];
                    const selected = isFav ? fav === abbr : dislikes.has(abbr);
                    const isOwn = !isFav && abbr === fav;
                    const isDivTeam = !isFav && !isOwn && t.div === favDiv && t.conf === favConf;
                    const isGrayedOut = isOwn || isDivTeam;
                    const tileStyle = { "--enter-delay": `${divIdx * 60 + i * 25}ms` };
                    return (
                      <button
                        key={abbr}
                        className={"team-tile" + (selected ? isFav ? " selected" : " disliked" : "")}
                        onClick={() => handleTileClick(abbr)}
                        disabled={isGrayedOut}
                        style={tileStyle}>

                          <div className="swatch" style={{ background: t.color }}></div>
                          <div className="meta">
                            <div className="name">{t.name}</div>
                            <div className="abbr">{t.abbr}<span className="record">{t.record[0]}-{t.record[1]}</span></div>
                          </div>
                          {selected &&
                        <div className="check" style={!isFav ? { background: "var(--warn)" } : null}>
                              {isFav ? "✓" : "✕"}
                            </div>
                        }
                        </button>);

                  })}
                  </div>
                </div>);

          })}
          </>
        }
      </div>
    </div>);

}

window.Onboarding = Onboarding;
