// Data layer — categories + habits are static config; events come from the store.
// On first load, EVENTS is empty (per requirement). The store persists to
// localStorage and exposes a swappable adapter for future cloud sync.

const CATEGORIES = {
  work:     { label: "Work",     hue: 240, dot: "oklch(0.62 0.14 240)", soft: "oklch(0.94 0.04 240)", ink: "oklch(0.32 0.10 240)" },
  personal: { label: "Personal", hue: 290, dot: "oklch(0.62 0.14 290)", soft: "oklch(0.94 0.04 290)", ink: "oklch(0.32 0.10 290)" },
  health:   { label: "Health",   hue: 145, dot: "oklch(0.62 0.14 145)", soft: "oklch(0.94 0.04 145)", ink: "oklch(0.32 0.10 145)" },
  travel:   { label: "Travel",   hue: 35,  dot: "oklch(0.62 0.14 35)",  soft: "oklch(0.94 0.04 35)",  ink: "oklch(0.32 0.10 35)" },
  family:   { label: "Family",   hue: 350, dot: "oklch(0.62 0.14 350)", soft: "oklch(0.94 0.04 350)", ink: "oklch(0.32 0.10 350)" },
  admin:    { label: "Admin",    hue: 80,  dot: "oklch(0.55 0.06 80)",  soft: "oklch(0.94 0.02 80)",  ink: "oklch(0.32 0.04 80)" },
  social:   { label: "Social",   hue: 320, dot: "oklch(0.62 0.14 320)", soft: "oklch(0.94 0.04 320)", ink: "oklch(0.32 0.10 320)" },
  leave:    { label: "Leave",    hue: 60,  dot: "oklch(0.72 0.13 60)",  soft: "oklch(0.93 0.06 60)",  ink: "oklch(0.40 0.10 60)" },
  holiday:  { label: "Holiday",  hue: 0,   dot: "oklch(0.55 0.02 0)",   soft: "oklch(0.92 0.005 0)",  ink: "oklch(0.32 0.005 0)" },
};

const HABITS = [
  { id: "h1", label: "Movement", emoji: "●", color: "oklch(0.62 0.14 145)" },
  { id: "h2", label: "Read 20m", emoji: "■", color: "oklch(0.62 0.14 240)" },
];

// ─── Habits store: localStorage-backed, shape { [habitId]: { [dateKey]: true } } ───
const HABITS_KEY = "personal-calendar:habits:v1";
let habitsCache = null;
const habitsListeners = new Set();

function loadHabits() {
  if (habitsCache) return habitsCache;
  try { habitsCache = JSON.parse(localStorage.getItem(HABITS_KEY)) || {}; }
  catch { habitsCache = {}; }
  return habitsCache;
}
function saveHabits() {
  try { localStorage.setItem(HABITS_KEY, JSON.stringify(habitsCache)); } catch {}
  habitsListeners.forEach(fn => fn());
}
function habitDone(id, dateKey) {
  const all = loadHabits();
  return !!(all[id] && all[id][dateKey]);
}
function habitToggle(id, dateKey) {
  const all = loadHabits();
  if (!all[id]) all[id] = {};
  if (all[id][dateKey]) delete all[id][dateKey];
  else all[id][dateKey] = true;
  if (Object.keys(all[id]).length === 0) delete all[id];
  saveHabits();
}
window.useHabits = function useHabits() {
  const [, force] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => {
    const fn = () => force();
    habitsListeners.add(fn);
    return () => habitsListeners.delete(fn);
  }, []);
  return { done: habitDone, toggle: habitToggle };
};

// Create the events store. Adapter is the cloud one when served over https
// (production at calendar.nettleton.family), falling back to localStorage for
// the offline / file:// build.
const eventStore = window.CalendarStore.createStore({
  adapter: window.cloudAdapter || window.CalendarStore.localAdapter,
});

// Expose a CALENDAR_DATA shim where EVENTS is always the current store snapshot,
// expanded to include recurring instances within ±2 years of today.
function getExpandedEvents() {
  const today = new Date();
  const fromKey = `${today.getFullYear() - 2}-01-01`;
  const toKey = `${today.getFullYear() + 2}-12-31`;
  // Drop legacy/broken records (older builds stored events without a `date` field).
  const clean = eventStore.getEvents().filter(e => e && typeof e.date === "string" && /^\d{4}-\d{2}-\d{2}$/.test(e.date));
  return window.CalendarStore.expandRecurrence(clean, fromKey, toKey);
}

window.CALENDAR_DATA = {
  CATEGORIES,
  HABITS,
  habitDone,
  habitToggle,
  get EVENTS() { return getExpandedEvents(); },
};

// React hook — components subscribe to re-render when events change.
window.useCalendarEvents = function useCalendarEvents() {
  const [, force] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => eventStore.subscribe(() => force()), []);
  return {
    events: getExpandedEvents(),
    raw: eventStore.getEvents(),
    add: (e) => eventStore.addEvent(e),
    update: (id, patch) => {
      // Strip recurrence-instance suffix if present
      const realId = id.includes("__") ? id.split("__")[0] : id;
      eventStore.updateEvent(realId, patch);
    },
    remove: (id) => {
      const realId = id.includes("__") ? id.split("__")[0] : id;
      eventStore.deleteEvent(realId);
    },
  };
};

window.eventStore = eventStore;

// In cloud mode, replace the local mirror with the authoritative cloud state
// once it's available. Components subscribed to the store will re-render.
if (window.cloudAdapter && window.cloudAdapter.refresh) {
  window.cloudAdapter.refresh()
    .then(events => eventStore.replaceAll(events))
    .catch(e => console.warn("Cloud sync skipped:", e.message));
}
