// ---------- Store: data, auth, date helpers (globals) ----------

const STORE_KEY = 'mycal.v1';
const AUTH_KEY = 'mycal.auth.v1';
const PREF_KEY = 'mycal.pref.v1';

window.COLORS = [
  { id: 'red',    hex: '#ef4444', label: '레드'   },
  { id: 'orange', hex: '#f97316', label: '오렌지' },
  { id: 'amber',  hex: '#eab308', label: '앰버'   },
  { id: 'green',  hex: '#22c55e', label: '그린'   },
  { id: 'cyan',   hex: '#06b6d4', label: '시안'   },
  { id: 'blue',   hex: '#3b82f6', label: '블루'   },
  { id: 'violet', hex: '#8b5cf6', label: '바이올렛' },
  { id: 'pink',   hex: '#ec4899', label: '핑크'   },
];
window.COLOR_BY_ID = Object.fromEntries(COLORS.map(c => [c.id, c]));

window.TABS = [
  { id: 'todo',  label: 'TODO',  korTitle: '할 일', accent: '#2563eb' },
  { id: 'memo',  label: '메모',  korTitle: '메모',   accent: '#d97706' },
  { id: 'day',   label: '일',    korTitle: '일기',   accent: '#7c3aed' },
  { id: 'learn', label: '배움',  korTitle: '배움',   accent: '#059669' },
];
window.TAB_BY_ID = Object.fromEntries(TABS.map(t => [t.id, t]));

window.STATUSES = [
  { id: 'planned',     label: '예정',   dot: '#a3a3a3' },
  { id: 'in-progress', label: '진행중', dot: '#3b82f6' },
  { id: 'done',        label: '완료',   dot: '#22c55e' },
];

window.REPEATS = [
  { id: 'none',    label: '반복 없음' },
  { id: 'daily',   label: '매일'      },
  { id: 'weekly',  label: '매주'      },
  { id: 'monthly', label: '매월'      },
];

window.uid = () => Math.random().toString(36).slice(2, 8) + Date.now().toString(36).slice(-4);

window.sha256 = async (text) => {
  const buf = new TextEncoder().encode(text);
  const hash = await crypto.subtle.digest('SHA-256', buf);
  return [...new Uint8Array(hash)].map(b => b.toString(16).padStart(2, '0')).join('');
};

// ---------- persistence ----------
window.loadData = () => {
  try {
    const raw = localStorage.getItem(STORE_KEY);
    if (!raw) return { items: [] };
    const d = JSON.parse(raw);
    if (!d.items) d.items = [];
    return d;
  } catch { return { items: [] }; }
};
window.saveData = (data) => localStorage.setItem(STORE_KEY, JSON.stringify(data));

window.loadAuth = () => {
  try { const r = localStorage.getItem(AUTH_KEY); return r ? JSON.parse(r) : null; }
  catch { return null; }
};
window.saveAuth = (a) => localStorage.setItem(AUTH_KEY, JSON.stringify(a));
window.clearAuth = () => localStorage.removeItem(AUTH_KEY);

window.loadPref = () => {
  try { const r = localStorage.getItem(PREF_KEY); return r ? JSON.parse(r) : {}; }
  catch { return {}; }
};
window.savePref = (p) => localStorage.setItem(PREF_KEY, JSON.stringify(p));

// ---------- date helpers (Monday start) ----------
const pad = (n) => String(n).padStart(2, '0');
window.D = {
  pad,
  toISO: (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`,
  parse: (iso) => {
    if (!iso) return null;
    const [y, m, dd] = iso.split('-').map(Number);
    return new Date(y, m - 1, dd);
  },
  sameDay: (a, b) =>
    a.getFullYear() === b.getFullYear() &&
    a.getMonth() === b.getMonth() &&
    a.getDate() === b.getDate(),
  addDays: (d, n) => { const x = new Date(d); x.setDate(x.getDate() + n); return x; },
  startOfMonth: (d) => new Date(d.getFullYear(), d.getMonth(), 1),
  endOfMonth: (d) => new Date(d.getFullYear(), d.getMonth() + 1, 0),
  // Monday=0 ... Sunday=6
  weekdayMon: (d) => (d.getDay() + 6) % 7,
  startOfMonthGrid(d) {
    const first = this.startOfMonth(d);
    return this.addDays(first, -this.weekdayMon(first));
  },
  monthGrid(d) {
    // 6 weeks × 7 days
    const start = this.startOfMonthGrid(d);
    return Array.from({ length: 42 }, (_, i) => this.addDays(start, i));
  },
  fmtKor: (d) => `${d.getFullYear()}년 ${d.getMonth() + 1}월 ${d.getDate()}일`,
  fmtMonthHeader: (d) => `${d.getFullYear()}. ${pad(d.getMonth() + 1)}`,
  fmtTime: (iso) => {
    if (!iso) return '';
    const t = iso.slice(11, 16);
    return t || '';
  },
  todayISO: () => {
    const d = new Date();
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
  },
  // for todo: get spanned days as ISO strings
  spanDays(startISO, endISO) {
    if (!startISO) return [];
    const s = this.parse(startISO.slice(0, 10));
    const e = endISO ? this.parse(endISO.slice(0, 10)) : s;
    if (!s || !e || e < s) return [this.toISO(s)];
    const days = [];
    for (let cur = s; cur <= e; cur = this.addDays(cur, 1)) days.push(this.toISO(cur));
    return days;
  },
};

// ---------- Item helpers ----------
window.itemDateISO = (it) => {
  // Returns primary date for sorting/listing
  if (it.tab === 'todo') return (it.startISO || it.dateISO || '').slice(0, 10);
  return (it.dateISO || it.startISO || '').slice(0, 10);
};

window.itemMatchesFilters = (it, f) => {
  if (f.colors && f.colors.size > 0 && !f.colors.has(it.color)) return false;
  if (it.tab === 'todo') {
    if (f.important && !it.important) return false;
    if (f.urgent && !it.urgent) return false;
    if (f.status && f.status !== 'all' && it.status !== f.status) return false;
  }
  if (f.tags && f.tags.size > 0) {
    const tags = it.tags || [];
    let ok = false;
    for (const t of f.tags) if (tags.includes(t)) { ok = true; break; }
    if (!ok) return false;
  }
  if (f.q) {
    const q = f.q.toLowerCase();
    const hay = [it.title, it.memo, it.location, (it.tags || []).join(' ')].filter(Boolean).join(' ').toLowerCase();
    if (!hay.includes(q)) return false;
  }
  return true;
};

// ---------- JSON export / import ----------
window.exportJSON = () => {
  const data = loadData();
  const payload = {
    app: 'Dada Calendar',
    version: 1,
    exportedAt: new Date().toISOString(),
    items: data.items || [],
  };
  const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `mycalendar-backup-${D.todayISO()}.json`;
  document.body.appendChild(a);
  a.click();
  a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
};

window.importJSONText = (text, { mode = 'merge' } = {}) => {
  const obj = JSON.parse(text);
  if (!obj || !Array.isArray(obj.items)) throw new Error('잘못된 백업 파일 형식이에요.');
  const cur = loadData();
  let next;
  if (mode === 'replace') next = { items: obj.items };
  else {
    const seen = new Set(cur.items.map(i => i.id));
    const merged = [...cur.items];
    for (const it of obj.items) if (!seen.has(it.id)) merged.push(it);
    next = { items: merged };
  }
  saveData(next);
  return next;
};
