/* Vault Calendar — main app shell, state, topbar. Wired to Supabase
   (event_groups / calendar_events). No seed data. */
const { useState, useEffect, useMemo, useCallback, useRef } = React;

const VIEWS = [
  { id: 'agenda', label: 'Agenda', icon: 'list' },
  { id: 'week', label: 'Week', icon: 'columns' },
  { id: 'month', label: 'Month', icon: 'grid' },
];

function Topbar(props) {
  const { view, setView, title, sub, onPrev, onNext, onToday, onNew, search, setSearch, tabs, utils } = props;
  const showNav = view !== 'agenda';
  return React.createElement('header', { className: 'cal-topbar' },
    React.createElement('div', { className: 'cal-brand', style: tabs ? { minWidth: 'auto' } : null },
      React.createElement('span', { className: 'mark' }, React.createElement(Icons.shield, { size: 17 })),
      tabs ? null : React.createElement('span', { className: 'wordmark' }, 'VAULT')),
    tabs || null,
    React.createElement('div', { className: 'cal-nav' },
      showNav ? React.createElement('button', { className: 'icon-btn', onClick: onPrev }, React.createElement(Icons.chevL)) : null,
      React.createElement('div', { className: 'cal-nav-title' }, title,
        sub ? React.createElement('span', { className: 'yr' }, sub) : null),
      showNav ? React.createElement('button', { className: 'icon-btn', onClick: onNext }, React.createElement(Icons.chevR)) : null),
    React.createElement('button', { className: 'today-btn', onClick: onToday }, 'Today'),
    React.createElement('div', { className: 'cal-spacer' }),
    React.createElement('div', { className: 'search-wrap' },
      React.createElement(Icons.search, { size: 15 }),
      React.createElement('input', {
        className: 'search-input', placeholder: 'Search events',
        value: search, onChange: (e) => setSearch(e.target.value),
      })),
    React.createElement('div', { className: 'seg' },
      VIEWS.map(v => React.createElement('button', {
        key: v.id, className: view === v.id ? 'on' : '', onClick: () => setView(v.id),
      }, React.createElement(Icons[v.icon], { size: 14 }), React.createElement('span', { className: 'seg-label' }, v.label)))),
    React.createElement('button', { className: 'btn-primary', onClick: () => onNew(null) },
      React.createElement(Icons.plus, { size: 15, sw: 2.5 }), React.createElement('span', { className: 'np-label' }, 'New event')),
    utils || null);
}

function App({ tabs, utils } = {}) {
  const DB = window.VaultDB;
  const today = useMemo(() => new Date(), []);
  const [view, setView] = useState('agenda');
  const [cursor, setCursor] = useState(() => new Date(today.getFullYear(), today.getMonth(), 1));
  const [selected, setSelected] = useState(today);
  const [search, setSearch] = useState('');

  const [groups, setGroups] = useState([]);      // [{id,name,color}]
  const [events, setEvents] = useState([]);      // UI-shape events
  const [ready, setReady] = useState(null);      // null=loading, false=needs migration, true=ok
  const [active, setActive] = useState({});      // group filter (id -> bool)
  const [modal, setModal] = useState(null);
  const paletteIdx = useRef(0);

  const evFromRow = (r) => ({ id: r.id, title: r.title, group: r.group_id, key: r.day, start: r.start_min || 0, end: r.end_min || 0, allDay: !!r.all_day, location: r.location || '', notes: r.notes || '' });

  // Load groups + events (and seed default groups for a fresh vault)
  useEffect(() => {
    let alive = true;
    (async () => {
      await DB.init();
      if (!DB.calendar.ready()) { if (alive) setReady(false); return; }
      try {
        let gs = await DB.calendar.listGroups();
        if (gs.length === 0) {
          for (const g of DEFAULT_GROUPS) { try { await DB.calendar.createGroup(g.name, g.color); } catch (e) {} }
          gs = await DB.calendar.listGroups();
        }
        const es = await DB.calendar.listEvents();
        if (!alive) return;
        setGroups(gs);
        const a = {}; gs.forEach(g => a[g.id] = true); setActive(a);
        setEvents(es.map(evFromRow));
        paletteIdx.current = gs.length % GROUP_PALETTE.length;
        setReady(true);
      } catch (e) { if (alive) setReady(false); }
    })();
    const unsub = DB.subscribe((table) => {
      if (table === 'events') DB.calendar.listEvents().then(es => setEvents(es.map(evFromRow))).catch(() => {});
      if (table === 'groups') DB.calendar.listGroups().then(gs => { setGroups(gs); setActive(prev => { const a = { ...prev }; gs.forEach(g => { if (!(g.id in a)) a[g.id] = true; }); return a; }); }).catch(() => {});
    });
    return () => { alive = false; unsub(); };
  }, []);

  const groupColor = useCallback((id) => (groups.find(g => g.id === id) || {}).color || 'var(--text-muted)', [groups]);

  const visible = useMemo(() => {
    const q = search.trim().toLowerCase();
    return events.filter(e => active[e.group] !== false &&
      (!q || e.title.toLowerCase().includes(q) || (e.location || '').toLowerCase().includes(q)));
  }, [events, active, search]);

  const counts = useMemo(() => {
    const c = {}; events.forEach(e => { c[e.group] = (c[e.group] || 0) + 1; }); return c;
  }, [events]);

  const shift = (dir) => setCursor(c => view === 'week' ? addDays(c, dir * 7) : addMonths(c, dir));
  const changeView = (v) => {
    setView(v);
    if (v === 'week') setCursor(selected || today);
    else if (v === 'month') { const a = selected || today; setCursor(new Date(a.getFullYear(), a.getMonth(), 1)); }
  };
  const goToday = () => { setCursor(view === 'week' ? today : new Date(today.getFullYear(), today.getMonth(), 1)); setSelected(today); };

  const openNew = (date, mins) => {
    const dt = date || selected || today;
    setModal({ type: 'event', draft: {
      title: '', group: (groups[0] || {}).id, key: dateKey(dt),
      start: mins != null ? mins : 9 * 60, end: mins != null ? mins + 60 : 10 * 60,
      allDay: mins == null, location: '', notes: '',
    } });
  };
  const openEvent = (e) => setModal({ type: 'event', draft: { ...e } });

  const toRow = (d) => ({ title: d.title, group_id: d.group, day: d.key, start_min: d.start, end_min: d.end, all_day: d.allDay, location: d.location, notes: d.notes });

  const saveEvent = async (d) => {
    setModal(null);
    try {
      if (d.id) { await DB.calendar.updateEvent(d.id, toRow(d)); setEvents(prev => prev.map(e => e.id === d.id ? d : e)); }
      else { const row = await DB.calendar.createEvent(toRow(d)); setEvents(prev => [...prev, evFromRow(row)]); }
    } catch (e) {}
  };
  const deleteEvent = async (id) => {
    setModal(null);
    setEvents(prev => prev.filter(e => e.id !== id));
    try { await DB.calendar.removeEvent(id); } catch (e) {}
  };

  const addGroup = async () => {
    const name = prompt('New group name'); if (!name || !name.trim()) return;
    const color = GROUP_PALETTE[paletteIdx.current % GROUP_PALETTE.length];
    paletteIdx.current += 1;
    try { const g = await DB.calendar.createGroup(name.trim(), color); setGroups(prev => [...prev, g]); setActive(a => ({ ...a, [g.id]: true })); } catch (e) {}
  };
  const toggleGroup = (id) => setActive(a => ({ ...a, [id]: a[id] === false }));
  const renameGroup = async (id) => {
    const g = groups.find(x => x.id === id); if (!g) return;
    const nx = prompt('Rename group', g.name);
    if (!nx || !nx.trim() || nx.trim() === g.name) return;
    const nm = nx.trim();
    setGroups(prev => prev.map(x => x.id === id ? { ...x, name: nm } : x));
    try { await DB.calendar.renameGroup(id, nm); } catch (e) {}
  };
  const deleteGroup = async (id) => {
    const g = groups.find(x => x.id === id); if (!g) return;
    if (!confirm('Delete group "' + g.name + '"? Its events become ungrouped.')) return;
    setGroups(prev => prev.filter(x => x.id !== id));
    setActive(a => { const n = { ...a }; delete n[id]; return n; });
    setEvents(prev => prev.map(e => e.group === id ? { ...e, group: null } : e));
    try { await DB.calendar.removeGroup(id); } catch (e) {}
  };

  // Topbar title
  let title = '', sub = '';
  if (view === 'week') {
    const ws = startOfWeek(cursor), we = addDays(ws, 6);
    if (ws.getMonth() === we.getMonth()) { title = MONTHS[ws.getMonth()].slice(0, 3) + ' ' + ws.getDate() + ' – ' + we.getDate(); sub = '' + ws.getFullYear(); }
    else { title = MONTHS[ws.getMonth()].slice(0, 3) + ' ' + ws.getDate() + ' – ' + MONTHS[we.getMonth()].slice(0, 3) + ' ' + we.getDate(); sub = '' + we.getFullYear(); }
  } else if (view === 'agenda') { title = 'Upcoming'; }
  else { title = MONTHS[cursor.getMonth()]; sub = '' + cursor.getFullYear(); }

  const topbar = React.createElement(Topbar, {
    view, setView: changeView, title, sub,
    onPrev: () => shift(-1), onNext: () => shift(1), onToday: goToday,
    onNew: openNew, search, setSearch, tabs, utils,
  });

  if (ready === false) {
    return React.createElement('div', { className: 'cal-root' }, topbar,
      React.createElement('div', { className: 'empty-pane' },
        React.createElement(Icons.calendar, { size: 40, sw: 1.5 }),
        React.createElement('div', { className: 'et' }, 'Calendar needs a one-time setup'),
        React.createElement('div', { className: 'es', style: { maxWidth: 420 } }, 'Run CALENDAR_MIGRATION.sql in the Supabase SQL editor to create the event tables, then reload.')));
  }
  if (ready === null) {
    return React.createElement('div', { className: 'cal-root' }, topbar,
      React.createElement('div', { className: 'empty-pane' }, React.createElement('div', { className: 'es' }, 'Loading…')));
  }

  return React.createElement('div', { className: 'cal-root' },
    topbar,
    React.createElement('div', { className: 'cal-body' },
      React.createElement(Sidebar, {
        cursor, selected, today, events: visible, groups, active, counts,
        onToggle: toggleGroup, onAddGroup: addGroup, onRenameGroup: renameGroup, onDeleteGroup: deleteGroup,
        onPick: (dt) => { setSelected(dt); setCursor(view === 'week' ? dt : new Date(dt.getFullYear(), dt.getMonth(), 1)); },
        onShift: shift,
      }),
      React.createElement('main', { className: 'cal-main' },
        view === 'month' && React.createElement(MonthView, {
          cursor, today, selected, events: visible, groupColor,
          onNew: openNew, onOpen: openEvent,
          onPeek: (date, list) => setModal({ type: 'peek', date, list }),
        }),
        view === 'week' && React.createElement(WeekView, {
          cursor, today, events: visible, groupColor, onOpen: openEvent, onNewAt: (d, mins) => openNew(d, mins),
        }),
        view === 'agenda' && React.createElement(AgendaView, {
          today, events: visible, groupColor, groups, onOpen: openEvent,
        }))),
    modal && modal.type === 'event' && React.createElement(EventModal, {
      draft: modal.draft, groups, onClose: () => setModal(null), onSave: saveEvent, onDelete: deleteEvent,
      onDuplicate: (d) => { const c = { ...d }; delete c.id; saveEvent(c); },
    }),
    modal && modal.type === 'peek' && React.createElement(DayPeek, {
      date: modal.date, list: modal.list, groupColor,
      onClose: () => setModal(null), onOpen: (e) => openEvent(e), onNew: (d) => openNew(d),
    }));
}

window.App = App;
