// data.jsx — mockup data layer for 智慧樂齡復能評估系統
// Faithful to Project.md §7. 教具/六力 borrow real parameter vocabulary; no real hardware.

const SIX_ORDER = ['認知力', '反應力', '自主力', '體適能力', '情緒力', '社交力'];
const FUNCTIONAL = ['認知力', '反應力', '體適能力'];
const PSYCHOSOCIAL = ['自主力', '社交力', '情緒力'];

const POWER_META = {
  '認知力':  { kind: 'fn', theory: '雙重任務 · global cognition / working memory', signal: 'task accuracy 正確率' },
  '反應力':  { kind: 'fn', theory: '雙重任務 · executive function / attention', signal: 'response latency 反應潛時' },
  '體適能力': { kind: 'fn', theory: '雙重任務 · motor / gait stability', signal: 'movement regularity 動作規律性' },
  '自主力':  { kind: 'ps', theory: 'SDT · autonomy 自主', signal: '自選模式 / 主動發起' },
  '社交力':  { kind: 'ps', theory: 'SDT · relatedness 連結', signal: '團體參與 / 共同出席' },
  '情緒力':  { kind: 'ps', theory: 'SDT · competence 勝任（成就感）', signal: '成功率 / 持續參與' },
};

const TOOLS = [
  { id: 't1', name: '互動式認知遊戲機', type: '認知訓練', params: ['使用次數', '操作正確率', '反應潛時', '關卡完成率', '進步幅度'] },
  { id: 't2', name: '體感律動投影',   type: '肢體活動', params: ['使用次數', '單次時長', '動作完成率', '節奏準確度', '活躍度'] },
  { id: 't3', name: '語音回想訓練',   type: '記憶訓練', params: ['使用次數', '回答正確率', '詞彙召回數', '反應潛時'] },
  { id: 't4', name: '數位書法板',     type: '精細動作', params: ['使用次數', '單次時長', '筆畫完成率', '施力穩定度'] },
  { id: 't5', name: '觸控記憶配對',   type: '認知訓練', params: ['使用次數', '配對正確率', '完成時間', '連勝次數', '反應潛時'] },
];
const TOOL_NAMES = TOOLS.map((t) => t.name);

const CLASSES = [
  { id: 'c1', name: '認知活化 A 班', schedule: '週一、三、五 上午', size: 12, lead: '陳志明' },
  { id: 'c2', name: '律動健身班',    schedule: '每日上午',        size: 15, lead: '陳志明' },
  { id: 'c3', name: '懷舊回想班',    schedule: '週三 下午',       size: 8,  lead: '王美惠' },
  { id: 'c4', name: '失智友善班',    schedule: '週二、四 上午',   size: 6,  lead: '張伯宏' },
];

function sp(認知, 反應, 自主, 體適能, 情緒, 社交) {
  return { '認知力': 認知, '反應力': 反應, '自主力': 自主, '體適能力': 體適能, '情緒力': 情緒, '社交力': 社交 };
}

// featured students — hand-authored (陳秀英 matches reference exactly)
const FEATURED = [
  { id: 's1',  name: '陳秀英', classId: 'c1', joinMonths: 3, weekUses: 18, weekDays: 9, progress: 78, lastTool: '互動式認知遊戲機', lastDays: 1, status: '活躍',
    sp: sp([55,72],[50,68],[56,49],[48,63],[58,74],[64,58]) },
  { id: 's2',  name: '林文德', classId: 'c1', joinMonths: 5, weekUses: 22, weekDays: 11, progress: 86, lastTool: '觸控記憶配對', lastDays: 1, status: '活躍',
    sp: sp([62,78],[60,74],[58,66],[55,70],[60,77],[62,72]) },
  { id: 's3',  name: '周麗卿', classId: 'c1', joinMonths: 7, weekUses: 14, weekDays: 7, progress: 80, lastTool: '語音回想訓練', lastDays: 2, status: '活躍',
    sp: sp([70,66],[68,63],[66,70],[64,60],[72,68],[74,72]) },
  { id: 's4',  name: '許水木', classId: 'c1', joinMonths: 2, weekUses: 11, weekDays: 6, progress: 64, lastTool: '互動式認知遊戲機', lastDays: 2, status: '活躍',
    sp: sp([60,64],[58,62],[56,60],[54,58],[62,66],[64,68]) },
  { id: 's5',  name: '邱永發', classId: 'c1', joinMonths: 4, weekUses: 9,  weekDays: 5, progress: 58, lastTool: '數位書法板', lastDays: 3, status: '活躍',
    sp: sp([48,52],[46,50],[50,54],[47,51],[52,56],[54,58]) },
  { id: 's6',  name: '黃春美', classId: 'c2', joinMonths: 6, weekUses: 20, weekDays: 10, progress: 82, lastTool: '體感律動投影', lastDays: 1, status: '活躍',
    sp: sp([50,58],[48,55],[52,60],[60,72],[55,68],[58,66]) },
  { id: 's7',  name: '王國棟', classId: 'c2', joinMonths: 4, weekUses: 5,  weekDays: 2, progress: 41, lastTool: '體感律動投影', lastDays: 4, status: '需關注',
    sp: sp([45,42],[44,40],[50,46],[52,48],[48,45],[50,44]) },
  { id: 's8',  name: '吳建國', classId: 'c2', joinMonths: 8, weekUses: 24, weekDays: 12, progress: 88, lastTool: '體感律動投影', lastDays: 1, status: '活躍',
    sp: sp([66,72],[64,70],[62,68],[70,76],[68,74],[66,72]) },
  { id: 's9',  name: '鄭秀蓮', classId: 'c2', joinMonths: 9, weekUses: 21, weekDays: 11, progress: 90, lastTool: '互動式認知遊戲機', lastDays: 1, status: '活躍',
    sp: sp([68,74],[70,76],[66,72],[72,78],[70,76],[68,74]) },
  { id: 's10', name: '李秀美', classId: 'c3', joinMonths: 5, weekUses: 6,  weekDays: 3, progress: 49, lastTool: '語音回想訓練', lastDays: 6, status: '需關注',
    sp: sp([58,54],[55,52],[60,56],[54,50],[62,58],[64,60]) },
  { id: 's11', name: '蔡阿桃', classId: 'c3', joinMonths: 3, weekUses: 13, weekDays: 7, progress: 70, lastTool: '語音回想訓練', lastDays: 2, status: '活躍',
    sp: sp([52,60],[50,57],[55,62],[53,61],[58,65],[60,66]) },
  { id: 's12', name: '何美玲', classId: 'c3', joinMonths: 6, weekUses: 16, weekDays: 8, progress: 76, lastTool: '觸控記憶配對', lastDays: 1, status: '活躍',
    sp: sp([56,63],[54,61],[58,64],[55,62],[60,67],[62,68]) },
  { id: 's13', name: '張文雄', classId: 'c4', joinMonths: 4, weekUses: 4,  weekDays: 2, progress: 38, lastTool: '數位書法板', lastDays: 8, status: '需關注',
    sp: sp([40,38],[42,39],[45,43],[44,41],[46,44],[48,45]) },
  { id: 's14', name: '楊金水', classId: 'c4', joinMonths: 1, weekUses: 0,  weekDays: 0, progress: 12, lastTool: '—', lastDays: null, status: '未啟用',
    sp: sp([42,42],[40,40],[44,44],[43,43],[45,45],[46,46]) },
];

// deterministic generator to fill 康寧 roster to 41
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 clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));

const GEN_NAMES = [
  ['c1', '劉阿珠'], ['c1', '陳進財'], ['c1', '林罔市'], ['c1', '黃阿香'], ['c1', '張春嬌'], ['c1', '王添丁'], ['c1', '吳火旺'],
  ['c2', '鄭玉蘭'], ['c2', '謝金枝'], ['c2', '郭阿勉'], ['c2', '洪來福'], ['c2', '曾秋菊'], ['c2', '廖樹根'], ['c2', '賴阿英'], ['c2', '徐寶珠'], ['c2', '葉招弟'], ['c2', '蘇明德'], ['c2', '莊桂花'],
  ['c3', '呂萬發'], ['c3', '江阿足'], ['c3', '蕭銀花'], ['c3', '羅德旺'], ['c3', '高雪娥'],
  ['c4', '潘天賜'], ['c4', '簡阿鳳'], ['c4', '朱秋蘭'], ['c4', '周石頭'],
];

function genStudent(i, classId, name) {
  const r = mulberry32(9001 + i * 137);
  const sr = r();
  const status = sr < 0.12 ? '未啟用' : sr < 0.30 ? '需關注' : '活躍';
  const base = 42 + Math.floor(r() * 26);
  const improve = status === '活躍' ? 3 + Math.floor(r() * 13) : status === '需關注' ? -7 + Math.floor(r() * 8) : 0;
  const mk = () => {
    const b = clamp(Math.round(base + (r() - 0.5) * 18), 22, 92);
    const rec = status === '未啟用' ? b : clamp(Math.round(b + improve + (r() - 0.5) * 6), 20, 95);
    return [b, rec];
  };
  const sp = { '認知力': mk(), '反應力': mk(), '自主力': mk(), '體適能力': mk(), '情緒力': mk(), '社交力': mk() };
  const weekUses = status === '活躍' ? 8 + Math.floor(r() * 16) : status === '需關注' ? 3 + Math.floor(r() * 5) : 0;
  const weekDays = status === '未啟用' ? 0 : clamp(Math.round(weekUses * (0.42 + r() * 0.2)), 1, 12);
  return {
    id: 'g' + i, name, classId, status,
    joinMonths: 1 + Math.floor(r() * 10),
    weekUses, weekDays,
    progress: status === '活躍' ? 55 + Math.floor(r() * 38) : status === '需關注' ? 35 + Math.floor(r() * 20) : 5 + Math.floor(r() * 14),
    lastTool: status === '未啟用' ? '—' : TOOL_NAMES[Math.floor(r() * TOOL_NAMES.length)],
    lastDays: status === '未啟用' ? null : status === '需關注' ? 4 + Math.floor(r() * 6) : 1 + Math.floor(r() * 2),
    sp,
  };
}
const GENERATED = GEN_NAMES.map(([cid, name], i) => genStudent(i, cid, name));
const STUDENTS = [...FEATURED, ...GENERATED];

const INSTITUTIONS = [
  { id: 'i1', name: '康寧日間照顧中心', type: '小規模日照', tier: 'Tier 1', tierNote: '示範', county: '屏東', members: 41, classes: 4, rate: 87, trend: 'up', live: true, lead: '林淑芬' },
  { id: 'i2', name: '仁愛日照（連鎖）', type: '連鎖型日照', tier: 'Tier 1', tierNote: '',   county: '桃園', members: 68, classes: 6, rate: 82, trend: 'up', live: false, lead: '黃文彬' },
  { id: 'i3', name: '慈恩失智照顧中心', type: '失智照顧中心', tier: 'Tier 1', tierNote: '', county: '台中', members: 30, classes: 3, rate: 74, trend: 'flat', live: false, lead: '吳玉珍' },
  { id: 'i4', name: '杏林醫事 C 級巷弄站', type: '醫事 C 據點', tier: 'Tier 2', tierNote: '', county: '高雄', members: 22, classes: 2, rate: 71, trend: 'flat', live: false, lead: '蔡宗翰' },
  { id: 'i5', name: '長青養護中心',   type: '轉型中養護', tier: 'Tier 3', tierNote: '需扶植', county: '屏東', members: 26, classes: 2, rate: 63, trend: 'down', live: false, lead: '李金龍' },
];

const VENDOR = {
  brand: '悅動智慧教具',
  activeInst: 12, devices: 86, totalUses: 4210, avgCompletion: 78,
  models: [
    { id: 't1', name: '互動式認知遊戲機', type: '認知訓練', uses: 1420, completion: 81, units: 24, trend: 'up',
      sample: [['操作正確率', '81%'], ['反應潛時', '1.8 秒'], ['關卡完成率', '76%'], ['進步幅度', '+12%']] },
    { id: 't2', name: '體感律動投影', type: '肢體活動', uses: 1180, completion: 76, units: 18, trend: 'up',
      sample: [['動作完成率', '79%'], ['節奏準確度', '73%'], ['單次時長', '14 分'], ['活躍度', '高']] },
    { id: 't3', name: '語音回想訓練', type: '記憶訓練', uses: 880, completion: 74, units: 16, trend: 'flat',
      sample: [['回答正確率', '74%'], ['詞彙召回數', '8.2'], ['反應潛時', '2.3 秒']] },
    { id: 't4', name: '數位書法板', type: '精細動作', uses: 460, completion: 70, units: 14, trend: 'flat',
      sample: [['筆畫完成率', '70%'], ['施力穩定度', '68%'], ['單次時長', '11 分']] },
    { id: 't5', name: '觸控記憶配對', type: '認知訓練', uses: 270, completion: 69, units: 14, trend: 'down',
      sample: [['配對正確率', '69%'], ['完成時間', '42 秒'], ['連勝次數', '3.1'], ['反應潛時', '2.1 秒']] },
  ],
  counties: [{ name: '屏東', n: 5 }, { name: '桃園', n: 3 }, { name: '台中', n: 2 }, { name: '高雄', n: 2 }],
  adopters: [
    { name: '康寧日間照顧中心', county: '屏東', devices: 18, uses: 642, completion: 82, trend: 'up', since: '2025.09' },
    { name: '仁愛日照（連鎖）', county: '桃園', devices: 22, uses: 588, completion: 79, trend: 'up', since: '2025.06' },
    { name: '慈恩失智照顧中心', county: '台中', devices: 14, uses: 410, completion: 71, trend: 'flat', since: '2025.11' },
    { name: '杏林醫事 C 級巷弄站', county: '高雄', devices: 8, uses: 196, completion: 68, trend: 'flat', since: '2026.01' },
    { name: '長青養護中心', county: '屏東', devices: 9, uses: 144, completion: 63, trend: 'down', since: '2026.02' },
  ],
};

const TOOL_HEAT = [
  { id: 't1', name: '互動式認知遊戲機', uses: 104 },
  { id: 't2', name: '體感律動投影',   uses: 82 },
  { id: 't3', name: '語音回想訓練',   uses: 61 },
  { id: 't4', name: '數位書法板',     uses: 42 },
  { id: 't5', name: '觸控記憶配對',   uses: 23 },
];

// 康寧 教具裝置 (機構端 教具頁)
const DEVICES = [
  { toolId: 't1', units: 6, online: 6, weekUses: 104, trend: 'up',   classes: ['認知活化 A 班', '失智友善班'], sample: [['操作正確率', '81%'], ['反應潛時', '1.8 秒'], ['關卡完成率', '76%'], ['進步幅度', '+12%']] },
  { toolId: 't2', units: 4, online: 4, weekUses: 82,  trend: 'up',   classes: ['律動健身班'], sample: [['動作完成率', '79%'], ['節奏準確度', '73%'], ['單次時長', '14 分'], ['活躍度', '高']] },
  { toolId: 't3', units: 5, online: 4, weekUses: 61,  trend: 'flat', classes: ['懷舊回想班', '認知活化 A 班'], sample: [['回答正確率', '74%'], ['詞彙召回數', '8.2'], ['反應潛時', '2.3 秒']] },
  { toolId: 't4', units: 3, online: 3, weekUses: 42,  trend: 'flat', classes: ['認知活化 A 班'], sample: [['筆畫完成率', '70%'], ['施力穩定度', '68%'], ['單次時長', '11 分']] },
  { toolId: 't5', units: 4, online: 3, weekUses: 23,  trend: 'down', classes: ['律動健身班', '懷舊回想班'], sample: [['配對正確率', '69%'], ['完成時間', '42 秒'], ['連勝次數', '3.1'], ['反應潛時', '2.1 秒']] },
];

// 帳號與權限 (三層 A/B/C，Project.md §4)
const ACCOUNTS = [
  { name: '姚絜歆', role: 'A', roleLabel: '平台方', org: '樂動有感', scope: '全平台 · 所有機構與數據', last: '今日 09:12', status: '啟用' },
  { name: '李孟翰', role: 'A', roleLabel: '平台方', org: '樂動有感', scope: '全平台 · 系統與數據', last: '今日 08:40', status: '啟用' },
  { name: '林淑芬', role: 'B', roleLabel: '機構管理者', org: '康寧日間照顧中心', scope: '康寧 · 全機構資料、評鑑匯出', last: '1 小時前', status: '啟用' },
  { name: '陳志明', role: 'C', roleLabel: '服務員', org: '康寧日間照顧中心', scope: '認知活化 A 班 · 律動健身班', last: '今日 10:25', status: '啟用' },
  { name: '王美惠', role: 'C', roleLabel: '服務員', org: '康寧日間照顧中心', scope: '懷舊回想班', last: '昨日 16:50', status: '啟用' },
  { name: '張伯宏', role: 'C', roleLabel: '服務員', org: '康寧日間照顧中心', scope: '失智友善班', last: '2 天前', status: '啟用' },
  { name: '黃文彬', role: 'B', roleLabel: '機構管理者', org: '仁愛日照（連鎖）', scope: '仁愛 · 全機構資料', last: '今日 09:55', status: '啟用' },
  { name: '吳玉珍', role: 'B', roleLabel: '機構管理者', org: '慈恩失智照顧中心', scope: '慈恩 · 全機構資料', last: '3 天前', status: '待啟用' },
];

// 報表存檔 (報表中心)
const REPORTS = [
  { title: '康寧 · 機構成效報告', period: '2026 Q1', juri: '屏東縣衛生局', date: '2026.03.31', by: '林淑芬', scope: '機構' },
  { title: '陳秀英 · 前後測成效報告', period: '2026.02–04', juri: '屏東縣衛生局', date: '2026.04.15', by: '陳志明', scope: '學員' },
  { title: '律動健身班 · 季度參與報告', period: '2026 Q1', juri: '屏東縣衛生局', date: '2026.03.30', by: '陳志明', scope: '班別' },
  { title: '康寧 · 評鑑佐證彙整', period: '2025 下半', juri: '屏東縣衛生局', date: '2026.02.28', by: '林淑芬', scope: '機構' },
  { title: '吳建國 · 前後測成效報告', period: '2025.10–2026.01', juri: '屏東縣衛生局', date: '2026.01.20', by: '陳志明', scope: '學員' },
];

// ---- helpers ----
const round1 = (x) => Math.round(x * 10) / 10;
function baselineAvg(s) { return SIX_ORDER.reduce((a, k) => a + s.sp[k][0], 0) / 6; }
function recentAvg(s)   { return SIX_ORDER.reduce((a, k) => a + s.sp[k][1], 0) / 6; }
function deltaAvg(s)    { return recentAvg(s) - baselineAvg(s); }

const ASSESSED = STUDENTS.filter((s) => s.status !== '未啟用');
const INST_MEAN = round1(ASSESSED.reduce((a, s) => a + recentAvg(s), 0) / ASSESSED.length);
const WATCH = STUDENTS.filter((s) => s.status === '需關注');

function studentsByClass(cid) { return STUDENTS.filter((s) => s.classId === cid); }
function classById(cid) { return CLASSES.find((c) => c.id === cid); }
function studentById(sid) { return STUDENTS.find((s) => s.id === sid); }
function toolById(tid) { return TOOLS.find((t) => t.id === tid); }

function quadrantOf(s) {
  const above = recentAvg(s) >= INST_MEAN;
  const up = deltaAvg(s) >= 0;
  if (above && up) return 'maintain';
  if (above && !up) return 'acute';
  if (!above && up) return 'follow';
  return 'risk';
}
const QUADRANT_META = {
  maintain: { label: '維持', note: '可作示範案例' },
  acute:    { label: '留意', note: '查是否有急性事件' },
  follow:   { label: '持續追蹤', note: '介入有效，仍需支持' },
  risk:     { label: '建議關注', note: '建議安排臨床轉介評估' },
};

// per-student derived detail (deterministic)
function seedOf(id) { let h = 0; for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) | 0; return Math.abs(h); }
function studentAttendance(s) {
  const r = mulberry32(seedOf(s.id) + 7);
  const ratio = s.status === '活躍' ? 0.85 : s.status === '需關注' ? 0.42 : 0.0;
  return Array.from({ length: 8 }, (_, i) => (i >= 8 - 1 && s.status !== '未啟用' ? true : r() < ratio));
}
function studentToolLog(s) {
  if (s.status === '未啟用') return [];
  const r = mulberry32(seedOf(s.id) + 13);
  const n = s.status === '活躍' ? 4 : 2;
  const pick = [...TOOLS].sort(() => r() - 0.5).slice(0, n);
  return pick.map((t) => ({
    name: t.name,
    uses: 1 + Math.floor(r() * (s.status === '活躍' ? 9 : 4)),
    metric: t.params[1],
    value: (60 + Math.floor(r() * 35)) + (t.params[1].includes('時間') || t.params[1].includes('潛時') ? '' : '%'),
  }));
}
const NOTE_BANK = {
  '活躍': ['本週主動選了體感律動，完成後笑得很開心。', '配對遊戲連續答對，成就感明顯，鼓勵她帶動鄰座。', '出席穩定，認知遊戲關卡持續推進。'],
  '需關注': ['這兩週出席變少，已電話關心，家屬說最近天氣影響外出。', '情緒較低落，安排了懷舊活動陪伴，再觀察一週。', '反應潛時略增，下次調整任務難度。'],
  '未啟用': ['剛加入，正在熟悉環境，尚未開始使用教具。'],
};
function studentNotes(s) {
  const r = mulberry32(seedOf(s.id) + 23);
  const bank = NOTE_BANK[s.status];
  const dates = ['2026.05.28', '2026.05.21', '2026.05.14'];
  const n = s.status === '未啟用' ? 1 : 2;
  return Array.from({ length: n }, (_, i) => ({ date: dates[i], by: classById(s.classId).lead, text: bank[Math.floor(r() * bank.length)] }));
}

Object.assign(window, {
  SIX_ORDER, FUNCTIONAL, PSYCHOSOCIAL, POWER_META, TOOLS, TOOL_NAMES, CLASSES, STUDENTS, FEATURED,
  INSTITUTIONS, VENDOR, TOOL_HEAT, DEVICES, ACCOUNTS, REPORTS, INST_MEAN, ASSESSED, WATCH,
  baselineAvg, recentAvg, deltaAvg, round1,
  studentsByClass, classById, studentById, toolById, quadrantOf, QUADRANT_META,
  studentAttendance, studentToolLog, studentNotes,
});
