// SOCIAL + FRESHNESS LAYER
// Tier 2: achievements, Sunday recap, family ticker
// Tier 3: workout of the day, monthly challenge

// ===== ACHIEVEMENTS ENGINE =====
const ACHIEVEMENTS = [
  // Foundation
  { id: "first_set",   tier: 1, icon: "▮",   name: "FIRST REP",       desc: "Log your first set" },
  { id: "first_pr",    tier: 1, icon: "🎯", name: "PR HUNTER",       desc: "Hit your first PR" },
  { id: "five_lifts",  tier: 1, icon: "✦",  name: "FIVE LIFTS",      desc: "Try 5 different exercises" },
  { id: "week_active", tier: 1, icon: "📅", name: "WEEK ACTIVE",     desc: "Train at least one set every day for 5 days" },

  // Streaks
  { id: "streak_3",    tier: 2, icon: "🔥", name: "WARMING UP",      desc: "3-day streak" },
  { id: "streak_7",    tier: 2, icon: "🔥", name: "WEEK WARRIOR",    desc: "7-day streak" },
  { id: "streak_14",   tier: 3, icon: "🔥", name: "FORTNIGHT",       desc: "14-day streak" },
  { id: "streak_30",   tier: 4, icon: "👹", name: "IRON MONK",       desc: "30-day streak" },

  // Volume milestones
  { id: "vol_1t",      tier: 1, icon: "💪", name: "FIRST TONNE",     desc: "1,000 kg total volume" },
  { id: "vol_10t",     tier: 2, icon: "💪", name: "TEN TONNES",      desc: "10,000 kg total volume" },
  { id: "vol_50t",     tier: 3, icon: "🦾", name: "ROAD WORK",       desc: "50,000 kg total volume" },
  { id: "vol_100t",    tier: 4, icon: "🏛", name: "CENTURY",         desc: "100,000 kg total volume" },

  // Lift milestones
  { id: "squat_bw",    tier: 2, icon: "🏋", name: "BODYWEIGHT SQUAT", desc: "Squat your bodyweight" },
  { id: "squat_2bw",   tier: 4, icon: "🏔", name: "DOUBLE BODYWEIGHT", desc: "Squat 2× bodyweight" },
  { id: "deadlift_2bw",tier: 4, icon: "⛓", name: "DEADLIFT BEAST",   desc: "Deadlift 2× bodyweight" },
  { id: "bench_bw",    tier: 3, icon: "📕", name: "BENCH BW",        desc: "Bench-press your bodyweight" },
  { id: "ohp_50",      tier: 3, icon: "☀",  name: "PRESS 0.5BW",     desc: "Overhead press 0.5× bodyweight" },
  { id: "pullup_first",tier: 1, icon: "▲",  name: "ZERO TO ONE",     desc: "First pull-up rep" },
  { id: "pullup_10",   tier: 3, icon: "🐒", name: "MONKEY BAR",      desc: "10 pull-ups in a single set" },

  // Family / social
  { id: "outvol_week", tier: 2, icon: "👑", name: "TOP DOG",         desc: "Highest weekly volume in the squad" },
  { id: "balanced_wk", tier: 2, icon: "⚖",  name: "BALANCED",        desc: "Train all 4 zones in a week" },
  { id: "cheer_given", tier: 1, icon: "🔥", name: "GOOD TEAMMATE",   desc: "Send your first cheer" },
];

const TIER_COLORS = {
  1: "#9D9D9D",   // bronze-ish neutral
  2: "#3AA8FF",   // blue
  3: "#D4FF3F",   // lime
  4: "#FFB800",   // gold
};

// Compute earned achievements for an athlete
const computeAchievements = ({ athleteId, sets, athletes, cheers, today }) => {
  const me = athletes[athleteId];
  if (!me) return new Set();
  const mySets = sets.filter(s => s.athlete === athleteId);
  const myCheers = (cheers || []).filter(c => c.from === athleteId);

  // Compute aggregate stats
  const totalVol = mySets.reduce((t, s) => t + (s.weight || 0) * s.reps, 0);
  const uniqueExercises = new Set(mySets.map(s => s.exercise)).size;
  const prs = {};
  for (const s of mySets) {
    if (!s.weight) continue;
    if (!prs[s.exercise] || s.weight > prs[s.exercise]) prs[s.exercise] = s.weight;
  }
  const bw = me.bodyweight || 70;

  // Streak
  const dates = new Set(mySets.map(s => s.date));
  let streak = 0; let cursor = new Date(today);
  while (true) {
    const ds = cursor.toISOString().slice(0, 10);
    if (dates.has(ds)) { streak++; cursor.setDate(cursor.getDate() - 1); if (streak > 365) break; }
    else if (streak === 0 && ds === today) { cursor.setDate(cursor.getDate() - 1); }
    else break;
  }

  // Past-week activity for "week_active" / "balanced_wk"
  const cutoff7 = new Date(today); cutoff7.setDate(cutoff7.getDate() - 6);
  const weekSets = mySets.filter(s => s.date >= cutoff7.toISOString().slice(0, 10));
  const weekDates = new Set(weekSets.map(s => s.date));

  // Zones hit this week (push/pull/legs/core)
  const zonesHit = new Set();
  const exercises = window.FITNESS_DATA.exercises;
  for (const s of weekSets) {
    const ex = exercises.find(e => e.id === s.exercise);
    if (!ex) continue;
    (ex.primary || []).forEach(m => {
      const z = window.coach && window.coach.zoneMap ? window.coach.zoneMap(m) : ZONE_FALLBACK[m];
      if (z) zonesHit.add(z);
    });
  }

  // Weekly volume — compare to other active athletes
  const cutoffStr7 = cutoff7.toISOString().slice(0, 10);
  const weeklyVolByAthlete = {};
  for (const s of sets) {
    if (s.date < cutoffStr7) continue;
    weeklyVolByAthlete[s.athlete] = (weeklyVolByAthlete[s.athlete] || 0) + (s.weight || athletes[s.athlete]?.bodyweight || 70) * s.reps;
  }
  const ranked = Object.entries(weeklyVolByAthlete).sort((a, b) => b[1] - a[1]);
  const isTopDog = ranked.length > 1 && ranked[0][0] === athleteId && ranked[0][1] > 0;

  const earned = new Set();
  const has = (id) => earned.add(id);

  if (mySets.length > 0) has("first_set");
  if (mySets.some(s => s.isPR)) has("first_pr");
  if (uniqueExercises >= 5) has("five_lifts");
  if (weekDates.size >= 5) has("week_active");

  if (streak >= 3)  has("streak_3");
  if (streak >= 7)  has("streak_7");
  if (streak >= 14) has("streak_14");
  if (streak >= 30) has("streak_30");

  if (totalVol >= 1000)   has("vol_1t");
  if (totalVol >= 10000)  has("vol_10t");
  if (totalVol >= 50000)  has("vol_50t");
  if (totalVol >= 100000) has("vol_100t");

  if ((prs.bb_squat    || 0) >= bw)         has("squat_bw");
  if ((prs.bb_squat    || 0) >= bw * 2)     has("squat_2bw");
  if ((prs.bb_deadlift || 0) >= bw * 2)     has("deadlift_2bw");
  if ((prs.bb_bench    || 0) >= bw)         has("bench_bw");
  if ((prs.bb_ohp      || 0) >= bw * 0.5)   has("ohp_50");

  if (mySets.some(s => s.exercise === "pu_pullup" && s.reps >= 1))  has("pullup_first");
  if (mySets.some(s => s.exercise === "pu_pullup" && s.reps >= 10)) has("pullup_10");

  if (isTopDog) has("outvol_week");
  if (zonesHit.size >= 4) has("balanced_wk");
  if (myCheers.length > 0) has("cheer_given");

  return earned;
};

// Local fallback zone map (in case coach.jsx hasn't loaded the helper yet)
const ZONE_FALLBACK = {
  chest: "PUSH", front_delt: "PUSH", side_delt: "PUSH", triceps: "PUSH",
  upper_back: "PULL", lats: "PULL", rear_delt: "PULL", traps: "PULL", biceps: "PULL", forearms: "PULL",
  quads: "LEGS", glutes: "LEGS", hamstrings: "LEGS", calves: "LEGS", adductors: "LEGS",
  abs: "CORE", obliques: "CORE", lower_back: "CORE",
};

// ===== ACHIEVEMENTS RAIL UI =====
const AchievementsRail = ({ athleteId, sets, athletes, cheers, today, accent }) => {
  const earned = React.useMemo(
    () => computeAchievements({ athleteId, sets, athletes, cheers, today }),
    [athleteId, sets, athletes, cheers, today]
  );
  const total = ACHIEVEMENTS.length;
  const earnedCount = earned.size;

  const sorted = [
    ...ACHIEVEMENTS.filter(a => earned.has(a.id)).sort((a, b) => b.tier - a.tier),
    ...ACHIEVEMENTS.filter(a => !earned.has(a.id)).sort((a, b) => a.tier - b.tier),
  ];

  return (
    <div className="ach-section" style={{ "--c": accent }}>
      <div className="ach-head">
        <div>
          <div className="ach-head-l">▮ ACHIEVEMENTS</div>
          <div className="ach-head-sub">{earnedCount} / {total} unlocked · {Math.round(earnedCount/total*100)}%</div>
        </div>
        <div className="ach-progress">
          <div className="ach-progress-bar" style={{ width: `${(earnedCount/total)*100}%`, background: accent }} />
        </div>
      </div>
      <div className="ach-grid">
        {sorted.map(a => {
          const got = earned.has(a.id);
          return (
            <div key={a.id}
              className={`ach ${got ? "ach--earned" : "ach--locked"}`}
              style={{ "--tier": TIER_COLORS[a.tier] }}
              title={`${a.name} — ${a.desc}`}>
              <div className="ach-icon">{got ? a.icon : "🔒"}</div>
              <div className="ach-name">{a.name}</div>
              <div className="ach-desc">{a.desc}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ===== FAMILY TICKER =====
const FamilyTicker = ({ sets, athletes, today, whoami }) => {
  // Find the most recent set logged by another athlete (within last 8 hours)
  const recent = React.useMemo(() => {
    const NOW = Date.now();
    const cutoff = NOW - 8 * 3600 * 1000;
    const others = sets.filter(s => s.athlete !== whoami && s.athlete);
    let best = null;
    for (const s of others) {
      const ts = Date.parse(`${s.date}T${s.time || "00:00"}:00`);
      if (isNaN(ts) || ts < cutoff || ts > NOW) continue;
      if (!best || ts > best.ts) best = { ...s, ts };
    }
    return best;
  }, [sets, whoami]);

  if (!recent) return null;
  const them = athletes[recent.athlete];
  const ex = window.FITNESS_DATA.exercises.find(e => e.id === recent.exercise);
  if (!them || !ex) return null;
  const minsAgo = Math.round((Date.now() - recent.ts) / 60000);
  const ago = minsAgo < 1 ? "JUST NOW"
    : minsAgo < 60 ? `${minsAgo} MIN AGO`
    : `${Math.round(minsAgo/60)}H AGO`;

  const isTime = window.exerciseIsTime ? window.exerciseIsTime(ex) : false;
  const detail = isTime
    ? `${recent.weight ? `${recent.weight}kg + ` : ""}${recent.reps}s hold`
    : (recent.weight ? `${recent.weight}kg × ${recent.reps} reps` : `BW × ${recent.reps} reps`);

  return (
    <div className="ft-ticker" style={{ "--c": them.color }}>
      <div className="ft-ticker-pulse" />
      <div className="ft-ticker-tag" style={{ background: them.color }}>{them.short}</div>
      <div className="ft-ticker-msg">
        <span className="ft-ticker-action">JUST LOGGED</span>
        <span className="ft-ticker-detail">{ex.name} — {detail}{recent.isPR ? " · ★ PR" : ""}</span>
      </div>
      <div className="ft-ticker-time">{ago}</div>
    </div>
  );
};

// ===== SUNDAY RECAP =====
const SundayRecap = ({ sets, athletes, today, whoami, onClose }) => {
  // Compute previous week's stats per athlete
  const cutoffEnd = new Date(today);
  const cutoffStart = new Date(today);
  cutoffStart.setDate(cutoffStart.getDate() - 7);
  const startStr = cutoffStart.toISOString().slice(0, 10);

  const active = Object.values(athletes).filter(a => !a.placeholder);
  const stats = active.map(a => {
    const aSets = sets.filter(s => s.athlete === a.id && s.date >= startStr);
    const vol = aSets.reduce((t, s) => t + (s.weight || a.bodyweight || 70) * s.reps, 0);
    const days = new Set(aSets.map(s => s.date)).size;
    const prs = aSets.filter(s => s.isPR).length;
    return { ...a, vol, days, prs, sets: aSets.length };
  }).sort((a, b) => b.vol - a.vol);

  const winner = stats[0];
  const me = stats.find(s => s.id === whoami) || stats[0];
  const myRank = stats.findIndex(s => s.id === whoami) + 1;

  // Persist dismiss so it doesn't pop again the same Sunday
  const dismiss = () => {
    try { localStorage.setItem(`recap-dismissed-${today}`, "1"); } catch {}
    onClose();
  };

  return ReactDOM.createPortal(
    <div className="sr-modal" onClick={dismiss}>
      <div className="sr-card" onClick={e => e.stopPropagation()} style={{ "--c": me.color }}>
        <div className="sr-header">
          <div className="sr-tag">★ SUNDAY RECAP</div>
          <div className="sr-title">WEEK OF {cutoffStart.toLocaleDateString("en-US", { month: "short", day: "numeric" }).toUpperCase()}</div>
          <button className="sr-close" onClick={dismiss}>×</button>
        </div>

        {/* Winner */}
        {winner.vol > 0 && (
          <div className="sr-winner" style={{ "--wc": winner.color }}>
            <div className="sr-winner-crown">👑</div>
            <div>
              <div className="sr-winner-tag">TOP LIFTER</div>
              <div className="sr-winner-name">{winner.name.toUpperCase()}</div>
              <div className="sr-winner-vol" style={{ color: winner.color }}>{(winner.vol/1000).toFixed(1)}T volume</div>
            </div>
          </div>
        )}

        {/* Comparison bars */}
        <div className="sr-bars">
          <div className="sr-bars-head">VOLUME LADDER</div>
          {stats.map((s, i) => (
            <div key={s.id} className="sr-row">
              <div className="sr-row-rank">#{i + 1}</div>
              <div className="sr-row-name" style={{ color: s.color }}>{s.short}</div>
              <div className="sr-row-bar">
                <div className="sr-row-fill" style={{
                  width: `${stats[0].vol > 0 ? Math.max(2, (s.vol / stats[0].vol) * 100) : 0}%`,
                  background: s.color
                }} />
              </div>
              <div className="sr-row-v">{(s.vol/1000).toFixed(1)}T</div>
            </div>
          ))}
        </div>

        {/* Personal stats */}
        <div className="sr-personal">
          <div className="sr-personal-head">YOUR WEEK · {me.short}</div>
          <div className="sr-personal-grid">
            <div className="sr-stat">
              <div className="sr-stat-v" style={{ color: me.color }}>#{myRank}</div>
              <div className="sr-stat-l">RANK</div>
            </div>
            <div className="sr-stat">
              <div className="sr-stat-v">{me.days}</div>
              <div className="sr-stat-l">DAYS TRAINED</div>
            </div>
            <div className="sr-stat">
              <div className="sr-stat-v">{me.sets}</div>
              <div className="sr-stat-l">SETS LOGGED</div>
            </div>
            <div className="sr-stat">
              <div className="sr-stat-v" style={{ color: me.color }}>{me.prs}</div>
              <div className="sr-stat-l">PRs</div>
            </div>
          </div>
        </div>

        {/* Next-week target */}
        <div className="sr-target">
          <div className="sr-target-tag">NEXT WEEK · TARGET</div>
          <div className="sr-target-text">
            {me.vol > 0
              ? <>Beat <strong>{(me.vol/1000).toFixed(1)}T</strong>. Add <strong>10%</strong> = aim for <strong style={{ color: me.color }}>{(me.vol*1.1/1000).toFixed(1)}T</strong>.</>
              : <>Log your first set this week to start the chase.</>
            }
          </div>
        </div>

        <button className="sr-dismiss" style={{ background: me.color }} onClick={dismiss}>
          ▸ LET'S GO
        </button>
      </div>
    </div>,
    document.body
  );
};

// ===== WORKOUT OF THE DAY =====
// Coach-suggested 4-lift session based on imbalance + recovery
const generateWorkoutOfDay = ({ sets, whoami, athletes, today, exercises }) => {
  const me = athletes[whoami];
  if (!me || me.placeholder) return null;

  const C = window.coach;
  const zones = C ? C.computeZoneVolume(sets, whoami, 7, today, exercises, me.bodyweight)
                  : { PUSH: 0, PULL: 0, LEGS: 0, CORE: 0 };

  // Sort zones by volume ascending — pick the 2 lightest as priorities
  const zoneList = Object.entries(zones).sort((a, b) => a[1] - b[1]);
  const priority = zoneList.slice(0, 2).map(z => z[0]);
  const cover = ["PUSH", "PULL", "LEGS"]; // ensure these get one each if possible

  // Selection: 1 from each priority + 1 from each remaining (up to 4)
  const exFor = (zone, exclude) => {
    return exercises.find(ex => {
      if (exclude.has(ex.id)) return false;
      const exZ = new Set();
      (ex.primary || []).forEach(m => { const z = ZONE_FALLBACK[m]; if (z) exZ.add(z); });
      return exZ.has(zone);
    });
  };

  const picked = [];
  const used = new Set();
  // First pass: prioritise weak zones
  for (const z of priority) {
    const ex = exFor(z, used);
    if (ex) { picked.push({ ex, zone: z, reason: "weak this week" }); used.add(ex.id); }
  }
  // Second pass: ensure push/pull/legs coverage
  for (const z of cover) {
    if (picked.length >= 4) break;
    if (picked.some(p => p.zone === z)) continue;
    const ex = exFor(z, used);
    if (ex) { picked.push({ ex, zone: z, reason: "balance" }); used.add(ex.id); }
  }
  // Third pass: any 4th compound
  if (picked.length < 4) {
    const ex = exFor("PULL", used) || exFor("LEGS", used) || exFor("PUSH", used);
    if (ex) {
      const z = (ex.primary || []).map(m => ZONE_FALLBACK[m]).find(Boolean);
      picked.push({ ex, zone: z, reason: "fill" });
    }
  }

  return picked.slice(0, 4);
};

const WorkoutOfDayCard = ({ sets, whoami, athletes, today, exercises, onStart, accent }) => {
  const session = React.useMemo(
    () => generateWorkoutOfDay({ sets, whoami, athletes, today, exercises }),
    [sets, whoami, athletes, today, exercises]
  );
  if (!session || session.length === 0) return null;

  // Compute prescribed weight: PR + 0/2.5kg or starting weight
  const prsByEx = {};
  for (const s of sets.filter(s => s.athlete === whoami && s.weight > 0)) {
    if (!prsByEx[s.exercise] || s.weight > prsByEx[s.exercise]) prsByEx[s.exercise] = s.weight;
  }
  const prescribe = (ex) => {
    const isBW = ex.equip === "bw" || ex.equip === "pullup";
    if (isBW) return null;
    return prsByEx[ex.id] || 20;
  };

  return (
    <div className="wod-card" style={{ "--c": accent }}>
      <div className="wod-head">
        <div>
          <div className="wod-tag">★ WORKOUT OF THE DAY</div>
          <div className="wod-title">SUGGESTED · 4 LIFTS · {session.map(s => s.zone).join(" · ")}</div>
        </div>
        <button className="wod-start" style={{ background: accent }}
          onClick={() => onStart(session[0].ex, prescribe(session[0].ex), 5)}>
          ▸ START
        </button>
      </div>
      <div className="wod-grid">
        {session.map((s, i) => {
          const w = prescribe(s.ex);
          return (
            <button key={s.ex.id} className="wod-lift"
              onClick={() => onStart(s.ex, w, 5)}>
              <div className="wod-lift-num">{String(i + 1).padStart(2, "0")}</div>
              <div className="wod-lift-info">
                <div className="wod-lift-name">{s.ex.name}</div>
                <div className="wod-lift-meta">
                  <span className="wod-lift-zone" style={{ background: ZONE_COLORS_LOCAL[s.zone] }}>{s.zone}</span>
                  <span className="wod-lift-prescribe">{w !== null ? `${w}kg × 5` : "BW × 5"}</span>
                  <span className="wod-lift-reason">· {s.reason}</span>
                </div>
              </div>
              <div className="wod-lift-go">▸</div>
            </button>
          );
        })}
      </div>
    </div>
  );
};

const ZONE_COLORS_LOCAL = window.ZONE_COLORS;

// ===== MONTHLY CHALLENGE =====
const MonthlyChallenge = ({ sets, athletes, today }) => {
  const t = new Date(today);
  const monthStart = new Date(t.getFullYear(), t.getMonth(), 1).toISOString().slice(0, 10);
  const monthName = t.toLocaleDateString("en-US", { month: "long" }).toUpperCase();
  const daysInMonth = new Date(t.getFullYear(), t.getMonth() + 1, 0).getDate();
  const dayOfMonth = t.getDate();
  const pctOfMonth = dayOfMonth / daysInMonth;

  const active = Object.values(athletes).filter(a => !a.placeholder);
  const monthlyVolByAth = {};
  let totalVol = 0;
  for (const s of sets) {
    if (s.date < monthStart) continue;
    const w = s.weight || athletes[s.athlete]?.bodyweight || 70;
    monthlyVolByAth[s.athlete] = (monthlyVolByAth[s.athlete] || 0) + w * s.reps;
    totalVol += w * s.reps;
  }

  const goal = (window.FITNESS_DATA.groupChallenge?.goal || 10000) * 4; // 4× weekly = monthly
  const pct = Math.min(100, (totalVol / goal) * 100);
  const onPace = totalVol >= goal * pctOfMonth;

  return (
    <div className={`mc-banner ${onPace ? "mc-banner--ok" : "mc-banner--behind"}`}>
      <div className="mc-l">
        <div className="mc-tag">★ {monthName} SQUAD CHALLENGE</div>
        <div className="mc-meta">{(totalVol/1000).toFixed(1)}T of {(goal/1000).toFixed(0)}T · {onPace ? "ON PACE" : `${Math.round((1-pctOfMonth)*100)}% remaining time`}</div>
      </div>
      <div className="mc-bar">
        <div className="mc-bar-fill" style={{ width: `${pct}%` }} />
        <div className="mc-bar-pace" style={{ left: `${pctOfMonth*100}%` }} title={`Today: day ${dayOfMonth} / ${daysInMonth}`}/>
      </div>
      <div className="mc-r">
        <div className="mc-pct">{Math.round(pct)}%</div>
        <div className="mc-day">DAY {dayOfMonth}/{daysInMonth}</div>
      </div>
    </div>
  );
};

// Expose to global so tracker.jsx can use them
window.social = {
  AchievementsRail,
  FamilyTicker,
  SundayRecap,
  WorkoutOfDayCard,
  MonthlyChallenge,
  ACHIEVEMENTS,
  computeAchievements,
};
