// ─────────────────────────────────────────────────────────────────────────
//  ENGAGEMENT TRACKING — DATA MODEL
// ─────────────────────────────────────────────────────────────────────────
//  Every counselor interaction is captured as one immutable EVENT in an
//  append-only log (persisted to localStorage). The Impact & Engagement
//  reports are derived entirely from this log by rolling events up across
//  five dimensions: month · school year · semester · grade level · resource
//  type (and pillar).
//
//  EVENT SHAPE
//  {
//    id:          string,                 // unique
//    ts:          ISO datetime string,    // when it happened
//    counselorId: string,
//    type:        "watch" | "download" | "share" | "complete",
//    source:      "training" | "resource" | "roadmap",
//    refId:       string,                 // session / resource / task id
//    title:       string,                 // human label
//    pillar:      string,                 // recruiting | mental_health | academic | ncaa | financial_aid
//    grade:       "9"|"10"|"11"|"12"|null,// grade level, when the item is grade-specific
//    assetType:   "video"|"doc"|"sheet"|"pdf"|"docx"|"xlsx"|null,
//    minutes:     number,                 // watch events — minutes viewed
//    students:    number,                 // share events — # of student-athletes shared with
//    meta:        {}                      // optional extra
//  }
// ─────────────────────────────────────────────────────────────────────────

const EVENTS_KEY = "sasa_events_v1";
const COUNSELOR_ID = "rachel-kim";

function uid() {
  return "e_" + Math.random().toString(36).slice(2, 10) + Date.now().toString(36).slice(-4);
}

// ── Persistence ────────────────────────────────────────────────────────────
function readEvents() {
  try { return JSON.parse(localStorage.getItem(EVENTS_KEY) || "null"); }
  catch { return null; }
}
function writeEvents(list) {
  localStorage.setItem(EVENTS_KEY, JSON.stringify(list));
  window.dispatchEvent(new CustomEvent("sasa-events-change"));
}
function loadEvents() {
  let list = readEvents();
  if (!Array.isArray(list)) {            // first run → seed a realistic history
    list = buildSeed();
    localStorage.setItem(EVENTS_KEY, JSON.stringify(list));
  }
  return list;
}

// Append one event. Fills id / ts / counselorId when omitted.
function logEvent(partial) {
  const list = loadEvents();
  const evt = {
    id: uid(),
    ts: partial.ts || new Date().toISOString(),
    counselorId: partial.counselorId || COUNSELOR_ID,
    minutes: 0,
    students: 0,
    grade: null,
    assetType: null,
    meta: {},
    ...partial,
  };
  list.push(evt);
  writeEvents(list);
  return evt;
}

// Convenience wrappers (all funnel into logEvent)
const trackWatch    = (o) => logEvent({ type: "watch",    ...o });
const trackDownload = (o) => logEvent({ type: "download", ...o });
const trackShare    = (o) => logEvent({ type: "share",    ...o });
const trackComplete = (o) => logEvent({ type: "complete", ...o });

// ── Date / period helpers ────────────────────────────────────────────────
// Semester boundary: Jan–Jun = spring, Jul–Dec = fall.
function semesterOf(ts) { return new Date(ts).getMonth() >= 6 ? "fall" : "spring"; }
function schoolYearStart(ts) {
  const d = new Date(ts);
  return d.getMonth() >= 6 ? d.getFullYear() : d.getFullYear() - 1;
}
function schoolYearOf(ts) {
  const s = schoolYearStart(ts);
  return `${s}\u2013${String((s + 1) % 100).padStart(2, "0")}`;
}
function monthKey(ts) {
  const d = new Date(ts);
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`;
}
function monthLabel(ts) {
  return new Date(ts).toLocaleDateString("en-US", { month: "short", year: "numeric" });
}

// Group video / documents / spreadsheets for the "by resource type" rollup.
const TYPE_GROUP = {
  video: "Video", doc: "Document", pdf: "Document", docx: "Document",
  sheet: "Spreadsheet", xlsx: "Spreadsheet", "video_doc": "Video",
};
function typeGroup(assetType) { return TYPE_GROUP[assetType] || "Other"; }

const GRADE_LABEL_T = { "9": "9th grade", "10": "10th grade", "11": "11th grade", "12": "12th grade" };

// ── Aggregation ────────────────────────────────────────────────────────────
function summarize(list) {
  const s = { minutes: 0, downloads: 0, shares: 0, completes: 0, watches: 0, students: 0, interactions: list.length };
  for (const e of list) {
    if (e.type === "watch")    { s.minutes += e.minutes || 0; s.watches++; }
    else if (e.type === "download") s.downloads++;
    else if (e.type === "share")    { s.shares++; s.students += e.students || 0; }
    else if (e.type === "complete") s.completes++;
  }
  return s;
}

// Generic grouping → [{ key, label, ...summary }] sorted by `sort`.
function groupSummary(list, keyFn, labelFn, sort = "key") {
  const buckets = {};
  for (const e of list) {
    const k = keyFn(e);
    if (k == null || k === "") continue;
    (buckets[k] = buckets[k] || []).push(e);
  }
  let rows = Object.entries(buckets).map(([key, evs]) => ({
    key, label: labelFn ? labelFn(key, evs) : key, ...summarize(evs),
  }));
  if (sort === "key") rows.sort((a, b) => (a.key < b.key ? -1 : 1));
  else rows.sort((a, b) => b[sort] - a[sort]);
  return rows;
}

const byMonth    = (l) => groupSummary(l, e => monthKey(e.ts), (k, evs) => monthLabel(evs[0].ts), "key");
const bySemester = (l) => groupSummary(l, e => `${schoolYearStart(e.ts)}-${semesterOf(e.ts)}`,
                          (k, evs) => `${semesterOf(evs[0].ts) === "fall" ? "Fall" : "Spring"} ${schoolYearOf(evs[0].ts)}`, "key");
const bySchoolYear = (l) => groupSummary(l, e => schoolYearOf(e.ts), k => `School year ${k}`, "key");
const byGrade    = (l) => groupSummary(l, e => e.grade, k => GRADE_LABEL_T[k] || k, "key");
const byPillar   = (l) => groupSummary(l, e => e.pillar, k => (window.DATA.TAGS[k]?.label || k), "interactions");
const byType     = (l) => groupSummary(l, e => (e.assetType ? typeGroup(e.assetType) : null), k => k, "interactions");

// Filter by a time range relative to the latest recorded activity ("anchor").
function anchorTs(list) {
  return list.reduce((m, e) => (e.ts > m ? e.ts : m), "1970-01-01");
}
function inRange(e, range, anchor) {
  if (range === "all") return true;
  const a = new Date(anchor), d = new Date(e.ts);
  if (range === "month")    return d.getFullYear() === a.getFullYear() && d.getMonth() === a.getMonth();
  if (range === "semester") return semesterOf(e.ts) === semesterOf(anchor) && schoolYearStart(e.ts) === schoolYearStart(anchor);
  if (range === "year")     return schoolYearOf(e.ts) === schoolYearOf(anchor);
  return true;
}
function filterRange(list, range) {
  const anchor = anchorTs(list);
  return list.filter(e => inRange(e, range, anchor));
}

// ── React hook ───────────────────────────────────────────────────────────
function useEvents() {
  const [events, setEvents] = useState(loadEvents);
  useEffect(() => {
    const h = () => setEvents(loadEvents());
    window.addEventListener("sasa-events-change", h);
    window.addEventListener("storage", h);
    return () => {
      window.removeEventListener("sasa-events-change", h);
      window.removeEventListener("storage", h);
    };
  }, []);
  return events;
}

// ── Seed: a realistic 2025–26 school-year history ──────────────────────────
// Dated per roadmap month so the month / semester / grade rollups all populate.
const SEED_MONTH_DATE = {
  August: "2025-08-20", September: "2025-09-18", October: "2025-10-15",
  November: "2025-11-12", December: "2025-12-10", January: "2026-01-14",
  February: "2026-02-11", March: "2026-03-11", April: "2026-04-08",
  May: "2026-05-13", June: "2026-06-10",
};

function buildSeed() {
  const D = window.DATA || {};
  const ev = [];
  const at = (date, h = 15, m = 0) => `${date}T${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:00`;

  // 1) Training watch + completion events (real sessions)
  (D.TRAINING_SESSIONS || []).forEach((s, i) => {
    const mins = Math.round((s.watchedSeconds || 0) / 60);
    if (mins > 0) ev.push({ id: uid(), ts: at(s.date, 15, 5), counselorId: COUNSELOR_ID, type: "watch", source: "training", refId: s.id, title: s.title, pillar: s.category, grade: null, assetType: "video", minutes: mins, students: 0, meta: {} });
    if (s.completed) ev.push({ id: uid(), ts: at(s.date, 15, 55), counselorId: COUNSELOR_ID, type: "complete", source: "training", refId: s.id, title: s.title, pillar: s.category, grade: null, assetType: "video", minutes: 0, students: 0, meta: {} });
  });

  // 2) Re-watch / catch-up sessions spread across the year (adds depth to the log)
  const REWATCH = [
    ["2025-10-03", "ts-jan-26", 22], ["2025-11-19", "ts-dec-25", 30], ["2025-12-05", "ts-jan-26", 41],
    ["2026-01-12", "ts-nov-25", 29], ["2026-01-27", "ts-feb-26", 25], ["2026-02-14", "ts-mar-26", 28],
    ["2026-02-28", "ts-dec-25", 35], ["2026-03-22", "ts-apr-26", 26], ["2026-03-30", "ts-jan-26", 30],
    ["2026-04-03", "ts-mar-26", 33], ["2026-04-10", "ts-feb-26", 20], ["2026-04-15", "ts-apr-26", 41],
    ["2026-04-18", "ts-dec-25", 22], ["2026-04-19", "ts-apr-26", 24],
  ];
  const sById = Object.fromEntries((D.TRAINING_SESSIONS || []).map(s => [s.id, s]));
  REWATCH.forEach(([date, id, mins], i) => {
    const s = sById[id]; if (!s) return;
    ev.push({ id: uid(), ts: at(date, 9 + (i % 8)), counselorId: COUNSELOR_ID, type: "watch", source: "training", refId: id, title: s.title, pillar: s.category, grade: null, assetType: "video", minutes: mins, students: 0, meta: {} });
  });

  // 3) Resource-hub downloads (real resources, dated by last update)
  (D.RESOURCES || []).forEach((r, i) => {
    ev.push({ id: uid(), ts: at(r.updated, 10 + (i % 9)), counselorId: COUNSELOR_ID, type: "download", source: "resource", refId: r.id, title: r.title, pillar: r.category, grade: null, assetType: (r.type || "pdf").toLowerCase(), minutes: 0, students: 0, meta: {} });
  });

  // 4) Roadmap completions → share events with student-athlete counts (carry grade)
  const roadmap = window.ROADMAP_DATA || [];
  const SHARE_PLAN = [
    ["aug-1", 6], ["aug-2", 8], ["sep-2", 5], ["sep-4", 9], ["oct-1", 7],
    ["nov-2", 4], ["nov-3", 6], ["jan-2", 5], ["feb-1", 8], ["mar-1", 6], ["apr-1", 7],
  ];
  const taskIndex = {};
  roadmap.forEach(m => m.tasks.forEach(t => { taskIndex[t.id] = { ...t, month: m.label }; }));
  const rtypeAsset = { doc: "doc", video: "video", video_doc: "video", video_doc_sheet: "video", spreadsheet: "sheet" };
  SHARE_PLAN.forEach(([tid, students], i) => {
    const t = taskIndex[tid]; if (!t) return;
    const date = SEED_MONTH_DATE[t.month] || "2026-03-01";
    ev.push({ id: uid(), ts: at(date, 11 + (i % 6), 30), counselorId: COUNSELOR_ID, type: "share", source: "roadmap", refId: tid, title: t.title, pillar: t.pillar, grade: t.grade, assetType: rtypeAsset[t.rtype] || "doc", minutes: 0, students, meta: {} });
    ev.push({ id: uid(), ts: at(date, 11 + (i % 6), 35), counselorId: COUNSELOR_ID, type: "complete", source: "roadmap", refId: tid, title: t.title, pillar: t.pillar, grade: t.grade, assetType: rtypeAsset[t.rtype] || "doc", minutes: 0, students: 0, meta: {} });
  });

  // 5) A few roadmap resource downloads (carry grade → feeds the grade rollup)
  const RM_DL = ["aug-1", "aug-3", "oct-2", "nov-1", "feb-1", "mar-1"];
  RM_DL.forEach((tid, i) => {
    const t = taskIndex[tid]; if (!t) return;
    const date = SEED_MONTH_DATE[t.month] || "2026-02-01";
    ev.push({ id: uid(), ts: at(date, 13, 10 + i), counselorId: COUNSELOR_ID, type: "download", source: "roadmap", refId: tid, title: t.title, pillar: t.pillar, grade: t.grade, assetType: rtypeAsset[t.rtype] || "doc", minutes: 0, students: 0, meta: {} });
  });

  ev.sort((a, b) => (a.ts < b.ts ? -1 : 1));
  return ev;
}

// ── Streak: consecutive active days ────────────────────────────────────────
//  Tracked separately from the engagement log so it never pollutes the Impact
//  rollups. Each calendar day the counselor opens the portal is recorded once;
//  the streak is the run of consecutive days ending today (with a one-day grace
//  so it still shows before you've done anything on the current day).
const DAYS_KEY = "sasa_active_days_v1";

function dayStr(d) {
  const x = new Date(d);
  return `${x.getFullYear()}-${String(x.getMonth() + 1).padStart(2, "0")}-${String(x.getDate()).padStart(2, "0")}`;
}
function loadActiveDays() {
  try {
    const a = JSON.parse(localStorage.getItem(DAYS_KEY));
    if (Array.isArray(a)) return a;
  } catch { /* fall through */ }
  // First run → seed a 14-day consecutive run ending today so the streak is
  // meaningful immediately; subsequent visits extend or break it for real.
  const today = new Date();
  const seed = [];
  for (let i = 13; i >= 0; i--) {
    const d = new Date(today);
    d.setDate(today.getDate() - i);
    seed.push(dayStr(d));
  }
  localStorage.setItem(DAYS_KEY, JSON.stringify(seed));
  return seed;
}
// Record that the counselor is active today (idempotent per calendar day).
function recordVisit() {
  const days = loadActiveDays();
  const t = dayStr(new Date());
  if (!days.includes(t)) {
    days.push(t);
    days.sort();
    localStorage.setItem(DAYS_KEY, JSON.stringify(days));
    window.dispatchEvent(new CustomEvent("sasa-days-change"));
  }
  return days;
}
// Count consecutive days ending today (or yesterday, if today isn't logged yet).
function computeStreak(days) {
  const set = new Set(days || loadActiveDays());
  const cur = new Date();
  if (!set.has(dayStr(cur))) cur.setDate(cur.getDate() - 1); // grace day
  let streak = 0;
  while (set.has(dayStr(cur))) {
    streak++;
    cur.setDate(cur.getDate() - 1);
  }
  return streak;
}
// Which of the trailing `n` days were active — for rendering the bar row.
function trailingDays(n = 14, days) {
  const set = new Set(days || loadActiveDays());
  const today = new Date();
  const out = [];
  for (let i = n - 1; i >= 0; i--) {
    const d = new Date(today);
    d.setDate(today.getDate() - i);
    out.push({ day: dayStr(d), active: set.has(dayStr(d)) });
  }
  return out;
}
// Hook: records today's visit on mount, re-renders on any change.
function useStreak() {
  const [state, setState] = useState(() => ({ streak: computeStreak(), days: loadActiveDays() }));
  useEffect(() => {
    recordVisit();
    const h = () => { const days = loadActiveDays(); setState({ streak: computeStreak(days), days }); };
    h();
    window.addEventListener("sasa-days-change", h);
    window.addEventListener("storage", h);
    return () => {
      window.removeEventListener("sasa-days-change", h);
      window.removeEventListener("storage", h);
    };
  }, []);
  return { streak: state.streak, trailing: trailingDays(14, state.days) };
}

// ── Exports ────────────────────────────────────────────────────────────────
Object.assign(window, {
  loadEvents, logEvent, trackWatch, trackDownload, trackShare, trackComplete,
  useEvents,
  useStreak, recordVisit, computeStreak, loadActiveDays,
  ENGAGEMENT: {
    summarize, groupSummary, filterRange, anchorTs,
    byMonth, bySemester, bySchoolYear, byGrade, byPillar, byType,
    semesterOf, schoolYearOf, monthKey, monthLabel, typeGroup, GRADE_LABEL: GRADE_LABEL_T,
  },
});
