// data.jsx — deterministic mock roster, activities, live sessions & history.
// Seeded RNG so numbers are stable across reloads.

function mulberry32(a) {
  return function () {
    a |= 0; a = (a + 0x6D2B79F5) | 0;
    let t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}
const rng = mulberry32(73);
const ri = (lo, hi) => Math.floor(rng() * (hi - lo + 1)) + lo;
const pick = (arr) => arr[Math.floor(rng() * arr.length)];

// ---------- Activities (canonical set; Tweaks can hide some) ----------
const ALL_ACTIVITIES = [
  { id: 'immersion', name: 'Robotics Immersion Program', short: 'Immersion', code: 'RIP',   color: '#18A0F0', icon: 'graduation-cap' },
  { id: 'skills',    name: 'Skills Build',                short: 'Skills Build', code: 'SKB', color: '#3D4248', icon: 'wrench' },
  { id: 'frc',       name: 'FRC · 10002',                 short: 'FRC',        code: 'FRC',  color: '#0E73B0', icon: 'bot' },
  { id: 'ftc-blue',  name: 'FTC Blue · 14380',            short: 'FTC Blue',   code: '14380',color: '#18A0F0', icon: 'cpu' },
  { id: 'ftc-red',   name: 'FTC Red · 18228',             short: 'FTC Red',    code: '18228',color: '#E03B36', icon: 'cpu' },
  { id: 'ftc-green', name: 'FTC Green · 25614',           short: 'FTC Green',  code: '25614',color: '#2FAE4A', icon: 'cpu' },
  { id: 'mentoring', name: 'Mentoring',                   short: 'Mentoring',  code: 'MEN',  color: '#F2A41B', icon: 'users' },
];

// ---------- Roster source ----------
const NAMES = [
  'Maya Chen', 'Liam O\u2019Brien', 'Aarav Patel', 'Isla Nguyen', 'Noah Williams',
  'Priya Sharma', 'Ethan Kim', 'Zoe Taylor', 'Lucas Rossi', 'Amara Okafor',
  'Sophie Tran', 'Jack Murphy', 'Hana Suzuki', 'Mason Clarke', 'Ava Singh',
  'Oliver Brown', 'Mia Hoang', 'Caleb Jones', 'Layla Hassan', 'Ryan Walsh',
  'Chloe Martin', 'Daniel Lee', 'Grace Bennett', 'Finn Gallagher', 'Anika Reddy',
  'Hugo Schmidt', 'Ella Davies', 'Tom Fitzgerald', 'Sienna Park', 'Max Edwards',
  'Ruby Costa', 'Kai Anderson', 'Jade Wilson', 'Leo Romano', 'Nina Petrova', 'Sam Whitfield',
];
const SCHOOLS = ['Northgate SHS', 'Aspley SHS', 'Craigslea SHS', 'St Joseph\u2019s', 'Wavell SHS', 'Geebung SS', 'Mansfield SHS', 'Home-schooled'];
const AV_COLORS = ['#18A0F0', '#0E73B0', '#E03B36', '#2FAE4A', '#F2A41B', '#7A5AE0', '#3D4248', '#0E73B0', '#18A0F0', '#2FAE4A'];

function initials(name) {
  const p = name.replace(/[^\w\s'\u2019-]/g, '').split(/\s+/);
  return (p[0][0] + (p[1] ? p[1][0] : '')).toUpperCase();
}
function rfid() {
  const hex = '0123456789ABCDEF';
  let s = '';
  for (let i = 0; i < 6; i++) s += hex[ri(0, 15)];
  return 'BB-' + s;
}

// build-night dates: Tue / Thu / Sat across 10 past weeks (week 9 = current)
const WEEKS = 10;
const NOW = Date.now();
const DAY = 86400000;
// anchor "today" as a Saturday-ish current week
function weekDates(w) {
  // returns array of session day-offsets (days ago) for week index w (0 oldest .. 9 current)
  const weeksAgo = (WEEKS - 1) - w;
  const base = weeksAgo * 7;
  return [base + 5, base + 3, base + 0]; // Tue, Thu, Sat-ish spacing
}

function makeStudents() {
  return NAMES.map((name, i) => {
    // enrollment: everyone in 1-3 activities, weighted
    const pool = ['frc', 'frc', 'skills', 'skills', 'immersion', 'ftc-blue', 'ftc-red', 'ftc-green', 'mentoring'];
    const enrolled = [];
    const nEnroll = ri(1, 3);
    while (enrolled.length < nEnroll) {
      const a = pick(pool);
      if (!enrolled.includes(a)) enrolled.push(a);
    }
    const grade = ri(7, 12);
    const av = AV_COLORS[i % AV_COLORS.length];

    // generate sessions
    const sessions = [];
    const weeklyHours = new Array(WEEKS).fill(0);
    const byActivity = {};
    for (let w = 0; w < WEEKS; w++) {
      const days = weekDates(w);
      // attendance probability per build night
      for (const off of days) {
        if (rng() > 0.52) continue; // ~half the nights
        const act = pick(enrolled);
        const startHour = pick([15, 16, 16, 17]);
        const startMin = pick([0, 15, 30, 45]);
        const durMin = ri(75, 215);
        const start = NOW - off * DAY;
        const d = new Date(start);
        d.setHours(startHour, startMin, 0, 0);
        const inE = d.getTime();
        const outE = inE + durMin * 60000;
        const hrs = durMin / 60;
        weeklyHours[w] += hrs;
        byActivity[act] = (byActivity[act] || 0) + hrs;
        sessions.push({ inE, outE, activity: act, hrs });
      }
    }
    sessions.sort((a, b) => b.inE - a.inE);
    const seasonHours = sessions.reduce((s, x) => s + x.hrs, 0);
    const weekHours = weeklyHours[WEEKS - 1];

    return {
      id: 'S' + String(i + 1).padStart(3, '0'),
      name, initials: initials(name), av, grade,
      school: SCHOOLS[i % SCHOOLS.length],
      rfid: rfid(),
      pin: String(ri(1000, 9999)),
      enrolled,
      sessions, weeklyHours, byActivity,
      seasonHours, weekHours,
    };
  });
}

const STUDENTS = makeStudents();
const byId = {};
STUDENTS.forEach((s) => (byId[s.id] = s));

// ---------- Who's in the building right now ----------
// choose ~11 present students with ongoing sessions
const PRESENT_SEED = [];
const shuffled = [...STUDENTS].sort(() => rng() - 0.5);
for (let i = 0; i < 11; i++) {
  const s = shuffled[i];
  const act = pick(s.enrolled);
  const minsAgo = ri(12, 182);
  PRESENT_SEED.push({
    studentId: s.id,
    activity: act,
    inE: NOW - minsAgo * 60000,
    via: rng() > 0.18 ? 'tag' : 'manual',
  });
}
PRESENT_SEED.sort((a, b) => a.inE - b.inE);

// ---------- org-wide attendance: distinct attendees per week (last 8) ----------
function attendanceTrend() {
  const out = [];
  for (let w = WEEKS - 8; w < WEEKS; w++) {
    let count = 0;
    for (const s of STUDENTS) if (s.weeklyHours[w] > 0) count++;
    out.push(count);
  }
  // make current week reflect "present" people minimum
  return out;
}
const TREND = attendanceTrend();

// ---------- formatting helpers ----------
function fmtTime(e) {
  return new Date(e).toLocaleTimeString('en-AU', { hour: 'numeric', minute: '2-digit', hour12: true });
}
function fmtDayTime(e) {
  return new Date(e).toLocaleDateString('en-AU', { day: 'numeric', month: 'short' });
}
function fmtDur(ms) {
  const m = Math.max(0, Math.floor(ms / 60000));
  const h = Math.floor(m / 60);
  const mm = m % 60;
  return h > 0 ? `${h}h ${String(mm).padStart(2, '0')}m` : `${mm}m`;
}
function fmtHrs(h) {
  return (Math.round(h * 10) / 10).toFixed(1) + 'h';
}
const WEEK_LABELS = (() => {
  const out = [];
  for (let w = WEEKS - 8; w < WEEKS; w++) {
    const weeksAgo = (WEEKS - 1) - w;
    if (weeksAgo === 0) out.push('This wk');
    else out.push(`${weeksAgo}w`);
  }
  return out;
})();

Object.assign(window, {
  ALL_ACTIVITIES, STUDENTS, STUDENT_BY_ID: byId, PRESENT_SEED, TREND, WEEK_LABELS,
  fmtTime, fmtDayTime, fmtDur, fmtHrs,
});
