/* planner-data.jsx — data model, storage, helpers (ported & trimmed from original app.js) */

const STORAGE_KEY = "primary-planner-v1";

const DAY_NAMES = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
const DAY_SHORT = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
const DAY_COLOR_VARS = ["--c-mon", "--c-tue", "--c-wed", "--c-thu", "--c-fri", "--c-sat", "--c-sun"];

const PALETTE = ["#ff7aa9", "#ffc24c", "#5cd6b1", "#5ea7ff", "#b07cff", "#ff945c", "#c79fff", "#a7e34f"];

const BLOCK_TYPES = [
  { id: "math",      label: "Math",       icon: "math" },
  { id: "reading",   label: "Reading",    icon: "book" },
  { id: "writing",   label: "Writing",    icon: "pencil" },
  { id: "science",   label: "Science",    icon: "beaker" },
  { id: "art",       label: "Art",        icon: "palette" },
  { id: "music",     label: "Music",      icon: "music" },
  { id: "pe",        label: "PE",         icon: "ball" },
  { id: "circle",    label: "Circle",     icon: "heart" },
  { id: "recess",    label: "Recess",     icon: "sun" },
  { id: "assess",    label: "Assess",     icon: "check" },
  { id: "project",   label: "Project",    icon: "rocket" }
];

const DEFAULT_SETTINGS = { startHour: 8, endHour: 16, includeWeekend: false };

function clamp(v, lo, hi) { return Math.max(lo, Math.min(hi, v)); }
function snapMin(v) { return clamp(Math.round(Number(v) / 15) * 15, 0, 1440); }
function makeId() { return "b-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 7); }

function startOfWeek(date) {
  const d = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  const day = (d.getDay() + 6) % 7;
  d.setDate(d.getDate() - day);
  return d;
}
function addDays(d, n) { const x = new Date(d); x.setDate(x.getDate() + n); return x; }
function toISODate(d) {
  return d.getFullYear() + "-" + String(d.getMonth() + 1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
}
function parseISODate(s) { const p = String(s).split("-").map(Number); return new Date(p[0], p[1]-1, p[2]); }
function fmtDate(d, opt) { return new Intl.DateTimeFormat(undefined, opt).format(d); }
function fmtHour(h) { const s = h >= 12 ? "PM":"AM"; const n = h % 12 || 12; return n + " " + s; }
function fmtTime(m) {
  const h = Math.floor(m/60), mn = m%60, s = h>=12?"PM":"AM", n = h%12||12;
  return n + ":" + String(mn).padStart(2,"0") + " " + s;
}
function minsToInput(m){ return String(Math.floor(m/60)).padStart(2,"0")+":"+String(m%60).padStart(2,"0"); }
function inputToMins(v){ const p = String(v||"08:00").split(":").map(Number); return clamp((p[0]||0)*60+(p[1]||0), 0, 1440); }
function fmtDur(m){ const h=Math.floor(m/60), r=m%60; if(!h)return r+"m"; return r? h+"h "+r+"m" : h+"h"; }

function normalizeBlock(b) {
  if (!b) return null;
  const start = clamp(Number(b.start)||540, 0, 1430);
  const end = clamp(Number(b.end)||start+60, start+15, 1440);
  const typeId = BLOCK_TYPES.find(t => t.id === b.typeId) ? b.typeId : "math";
  return {
    id: b.id || makeId(),
    dayIndex: clamp(Number(b.dayIndex)||0, 0, 6),
    start: snapMin(start),
    end: snapMin(end),
    title: String(b.title || "Untitled"),
    group: String(b.group || ""),
    typeId,
    color: PALETTE.includes(b.color) ? b.color : PALETTE[0],
    objective: String(b.objective || ""),
    activities: Array.isArray(b.activities) ? b.activities.map(a => ({
      name: String(a.name||"Activity").slice(0,60),
      minutes: clamp(Number(a.minutes)||10, 1, 240),
      detail: String(a.detail||""),
      done: Boolean(a.done)
    })) : [],
    materials: String(b.materials || ""),
    notes: String(b.notes || ""),
    stickers: Array.isArray(b.stickers) ? b.stickers.slice(0,8) : []
  };
}

function sampleBlocks() {
  return [
    { dayIndex: 0, start: 8*60+30, end: 9*60+15, title: "Morning Circle", typeId: "circle", color: "#ffc24c",
      objective: "Greet, share weekend, set Monday goals.",
      activities: [
        { name: "Hello song", minutes: 5, detail: "Wave hello to each table." },
        { name: "Share time", minutes: 20, detail: "Two students share weekend news." },
        { name: "Goal map", minutes: 15, detail: "Pick a 'try this week' card." }
      ],
      materials: "Goal cards, smile chart",
      stickers: ["star","heart"] },
    { dayIndex: 0, start: 9*60+30, end: 10*60+30, title: "Reading Workshop", typeId: "reading", color: "#5cd6b1",
      objective: "Find clues about how a character feels.",
      activities: [
        { name: "Hook", minutes: 10, detail: "Picture-book read aloud." },
        { name: "Independent read", minutes: 30, detail: "Sticky note feelings." },
        { name: "Share", minutes: 10, detail: "Partner trade." }
      ],
      materials: "Anchor book, sticky notes",
      stickers: ["rainbow"] },
    { dayIndex: 1, start: 9*60, end: 10*60, title: "Math Stations", typeId: "math", color: "#5ea7ff",
      objective: "Use number lines to add within 20.",
      activities: [
        { name: "Launch", minutes: 8, detail: "Notice & wonder image." },
        { name: "Rotations", minutes: 40, detail: "Three stations: build, sort, challenge." },
        { name: "Debrief", minutes: 10, detail: "Which strategy felt fast?" }
      ],
      materials: "Number line mats, counters",
      stickers: ["sparkle","star"] },
    { dayIndex: 2, start: 10*60+15, end: 11*60+15, title: "Science Lab", typeId: "science", color: "#ff7aa9",
      objective: "Test which materials sink or float.",
      activities: [
        { name: "Predict", minutes: 8, detail: "Vote sink/float for 6 items." },
        { name: "Test", minutes: 35, detail: "Pairs test and record." },
        { name: "Pattern talk", minutes: 12, detail: "What did floaters share?" }
      ],
      materials: "Tub of water, test items, paper",
      stickers: ["rainbow","sparkle"] },
    { dayIndex: 2, start: 13*60, end: 13*60+45, title: "Art: Self-portraits", typeId: "art", color: "#b07cff",
      objective: "Mix skin-tone colors and add a 'me' detail.",
      activities: [
        { name: "Demo", minutes: 8, detail: "Mix two tones on palette." },
        { name: "Paint", minutes: 30, detail: "Studio time with music." },
        { name: "Gallery walk", minutes: 7, detail: "Two compliments each." }
      ],
      materials: "Tempera, mirrors, brushes",
      stickers: ["heart"] },
    { dayIndex: 3, start: 11*60, end: 11*60+30, title: "Music Together", typeId: "music", color: "#ff945c",
      objective: "Keep a steady beat and add a new verse.",
      activities: [
        { name: "Warm up", minutes: 6, detail: "Clap & echo." },
        { name: "Make a verse", minutes: 18, detail: "Small groups write." },
        { name: "Perform", minutes: 6, detail: "Each group shares." }
      ],
      materials: "Shakers, sticks",
      stickers: ["sparkle"] },
    { dayIndex: 4, start: 9*60+15, end: 10*60, title: "Writing Time", typeId: "writing", color: "#ffc24c",
      objective: "Add one feeling word and one sound word.",
      activities: [
        { name: "Mini lesson", minutes: 10, detail: "Show before/after sentence." },
        { name: "Quiet write", minutes: 25, detail: "Confer with 4 students." },
        { name: "Author share", minutes: 10, detail: "Two volunteers." }
      ],
      materials: "Writer's notebooks",
      stickers: ["star","heart"] },
    { dayIndex: 4, start: 13*60+30, end: 14*60+15, title: "PE: Tag Games", typeId: "pe", color: "#a7e34f",
      objective: "Move safely, find space, change direction.",
      activities: [
        { name: "Stretch", minutes: 5, detail: "Animal stretches." },
        { name: "Freeze tag", minutes: 25, detail: "Rotate taggers." },
        { name: "Cool down", minutes: 10, detail: "Breath walk." }
      ],
      materials: "Cones, pinnies",
      stickers: ["rainbow"] }
  ].map(b => normalizeBlock({ id: makeId(), ...b }));
}

function loadState() {
  try {
    const saved = JSON.parse(localStorage.getItem(STORAGE_KEY));
    if (saved && saved.weeks && saved.currentWeekStart) return normalizeState(saved);
  } catch (e) {}
  const ws = toISODate(startOfWeek(new Date()));
  return normalizeState({
    currentWeekStart: ws,
    weeks: { [ws]: { settings: { ...DEFAULT_SETTINGS }, blocks: sampleBlocks() } }
  });
}

function normalizeState(s) {
  const out = { currentWeekStart: s.currentWeekStart || toISODate(startOfWeek(new Date())), weeks: s.weeks || {} };
  Object.keys(out.weeks).forEach(k => {
    const w = out.weeks[k] || {};
    w.settings = { ...DEFAULT_SETTINGS, ...(w.settings||{}) };
    w.settings.startHour = clamp(Number(w.settings.startHour)||DEFAULT_SETTINGS.startHour, 5, 21);
    w.settings.endHour   = clamp(Number(w.settings.endHour)||DEFAULT_SETTINGS.endHour, w.settings.startHour+1, 22);
    w.settings.includeWeekend = Boolean(w.settings.includeWeekend);
    w.blocks = Array.isArray(w.blocks) ? w.blocks.map(normalizeBlock).filter(Boolean) : [];
    out.weeks[k] = w;
  });
  if (!out.weeks[out.currentWeekStart]) {
    out.weeks[out.currentWeekStart] = { settings: { ...DEFAULT_SETTINGS }, blocks: [] };
  }
  return out;
}

function saveState(state) { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); } catch(e){} }

function planCompletion(b) {
  const checks = [
    Boolean(b.objective && b.objective.trim()),
    b.activities && b.activities.some(a => a.detail && a.detail.trim()),
    Boolean(b.materials && b.materials.trim()),
    Boolean(b.notes && b.notes.trim())
  ];
  return Math.round(checks.filter(Boolean).length / checks.length * 100);
}

function computeLayouts(blocks) {
  const layouts = {};
  for (let day = 0; day < 7; day++) {
    const sorted = blocks.filter(b => b.dayIndex === day).slice()
      .sort((a,b) => a.start - b.start || a.end - b.end);
    let group = [], groupEnd = -1;
    function assign(g) {
      const ends = [];
      g.forEach(b => {
        let col = ends.findIndex(e => e <= b.start);
        if (col === -1) { col = ends.length; ends.push(b.end); } else { ends[col] = b.end; }
        layouts[b.id] = { col, cols: 1 };
      });
      const cols = Math.max(ends.length, 1);
      g.forEach(b => { layouts[b.id].cols = cols; });
    }
    sorted.forEach(b => {
      if (group.length && b.start >= groupEnd) { assign(group); group = []; groupEnd = -1; }
      group.push(b); groupEnd = Math.max(groupEnd, b.end);
    });
    if (group.length) assign(group);
  }
  return layouts;
}

Object.assign(window, {
  PLANNER_DATA: {
    DAY_NAMES, DAY_SHORT, DAY_COLOR_VARS, PALETTE, BLOCK_TYPES, DEFAULT_SETTINGS,
    clamp, snapMin, makeId,
    startOfWeek, addDays, toISODate, parseISODate, fmtDate, fmtHour, fmtTime,
    minsToInput, inputToMins, fmtDur,
    normalizeBlock, normalizeState, sampleBlocks,
    loadState, saveState, planCompletion, computeLayouts
  }
});
