/* Calendar views: Month, Week, Agenda */

function eventsByDay(events) {
  const map = {};
  events.forEach(e => { (map[e.key] = map[e.key] || []).push(e); });
  Object.values(map).forEach(list => list.sort((a, b) => (b.allDay - a.allDay) || (a.start - b.start)));
  return map;
}

/* ---------- MONTH ---------- */
function MonthView({ cursor, today, selected, events, groupColor, onNew, onOpen, onPeek }) {
  const y = cursor.getFullYear(), m = cursor.getMonth();
  const cells = buildMonthGrid(y, m);
  const map = eventsByDay(events);
  const MAX = 3;
  return React.createElement('div', { className: 'month view-anim', key: y + '-' + m },
    React.createElement('div', { className: 'month-dow' },
      WEEKDAYS.map((d, i) => React.createElement('span', { key: d, className: i >= 5 ? 'we' : '' }, d))),
    React.createElement('div', { className: 'month-grid' },
      cells.map((dt, i) => {
        const other = dt.getMonth() !== m;
        const isToday = isSameDay(dt, today);
        const we = (i % 7) >= 5;
        const list = map[dateKey(dt)] || [];
        const cls = ['day-cell'];
        if (other) cls.push('other');
        if (we && !other) cls.push('we');
        if (isToday) cls.push('today-cell');
        return React.createElement('div', {
          key: i, className: cls.join(' '),
          onClick: () => onNew(dt),
        },
          React.createElement('button', {
            className: 'add-here',
            onClick: (e) => { e.stopPropagation(); onNew(dt); },
          }, React.createElement(Icons.plus, { size: 12, sw: 2.5 })),
          React.createElement('div', { className: 'day-top' },
            React.createElement('span', { className: 'day-num' }, dt.getDate())),
          React.createElement('div', { className: 'day-events' },
            list.slice(0, MAX).map((e, idx) => {
              const c = groupColor(e.group);
              return React.createElement('div', {
                key: e.id, className: 'chip' + (e.allDay ? ' allday' : ''),
                style: { '--cc': c, animationDelay: (idx * 30) + 'ms' },
                onClick: (ev) => { ev.stopPropagation(); onOpen(e); },
              },
                e.allDay
                  ? React.createElement('span', { className: 'ctitle' }, e.title)
                  : [
                      React.createElement('span', { className: 'cdot', key: 'd' }),
                      React.createElement('span', { className: 'ctime', key: 't' }, fmtTime(e.start)),
                      React.createElement('span', { className: 'ctitle', key: 'n' }, e.title),
                    ]);
            }),
            list.length > MAX
              ? React.createElement('div', {
                  className: 'more-link',
                  onClick: (ev) => { ev.stopPropagation(); onPeek(dt, list); },
                }, '+' + (list.length - MAX) + ' more')
              : null));
      })));
}

/* ---------- AGENDA (default view — the hero) ---------- */
function nextUpcoming(events, now) {
  const nowKey = dateKey(now);
  const nowMins = now.getHours() * 60 + now.getMinutes();
  let best = null;
  events.forEach(e => {
    if (e.key < nowKey) return;
    if (e.key === nowKey && !e.allDay && e.end <= nowMins) return;
    const sortKey = e.key + '-' + (e.allDay ? '0000' : String(e.start).padStart(4, '0'));
    if (!best || sortKey < best.sortKey) best = { ...e, sortKey };
  });
  return best;
}

function untilLabel(e, now) {
  const [y, m, d] = e.key.split('-').map(Number);
  const evDay = new Date(y, m - 1, d);
  const dayDiff = Math.round((evDay - new Date(now.getFullYear(), now.getMonth(), now.getDate())) / 864e5);
  if (dayDiff === 0) {
    if (e.allDay) return 'Today · All day';
    const mins = e.start - (now.getHours() * 60 + now.getMinutes());
    if (mins <= 0) return 'Happening now';
    if (mins < 60) return 'Today · in ' + mins + ' min';
    return 'Today · in ' + Math.floor(mins / 60) + 'h' + (mins % 60 ? ' ' + (mins % 60) + 'm' : '');
  }
  if (dayDiff === 1) return 'Tomorrow' + (e.allDay ? ' · All day' : ' · ' + fmtTime(e.start));
  return 'In ' + dayDiff + ' days · ' + WEEKDAYS[mondayIndex(evDay)];
}

function AgendaView({ today, events, groupColor, groups, onOpen }) {
  const map = eventsByDay(events);
  const now = new Date();
  const next = nextUpcoming(events, now);
  const days = [];
  for (let i = 0; i < 42; i++) {
    const dt = addDays(today, i);
    const list = map[dateKey(dt)];
    if (list && list.length) days.push({ dt, list });
  }
  const groupName = (id) => (groups ? ((groups.find(g => g.id === id) || {}).name || id) : id);

  return React.createElement('div', { className: 'agenda view-anim' },
    React.createElement('div', { className: 'agenda-inner' },
      next
        ? React.createElement('div', { className: 'next-hero', style: { '--cc': groupColor(next.group) }, onClick: () => onOpen(next) },
            React.createElement('div', { className: 'next-hero-top' },
              React.createElement('span', { className: 'next-hero-label' }, 'Next up'),
              React.createElement('span', { className: 'next-hero-group' },
                React.createElement('span', { className: 'gdot' }), groupName(next.group))),
            React.createElement('div', { className: 'next-hero-title' }, next.title),
            React.createElement('div', { className: 'next-hero-meta' },
              React.createElement('span', { className: 'when' }, untilLabel(next, now)),
              next.allDay ? null : React.createElement('span', null, fmtTime(next.start) + ' – ' + fmtTime(next.end)),
              next.location ? React.createElement('span', { className: 'loc' }, React.createElement(Icons.pin, { size: 12 }), next.location) : null))
        : null,
      days.length === 0
        ? React.createElement('div', { className: 'agenda-empty' }, 'Nothing scheduled. Enjoy the quiet.')
        : days.map(({ dt, list }, di) => {
          const isToday = isSameDay(dt, today);
          return React.createElement('div', { className: 'agenda-day', key: di },
            React.createElement('div', { className: 'agenda-date' },
              React.createElement('div', { className: 'agenda-dow' + (isToday ? ' is-today' : '') }, isToday ? 'Today' : WEEKDAYS[mondayIndex(dt)]),
              React.createElement('div', { className: 'agenda-dnum' + (isToday ? ' is-today' : '') }, dt.getDate()),
              React.createElement('div', { className: 'agenda-mon' }, MONTHS[dt.getMonth()].slice(0, 3) + ' · ' + list.length + (list.length === 1 ? ' event' : ' events'))),
            React.createElement('div', { className: 'agenda-events' },
              list.map(e => {
                const c = groupColor(e.group);
                return React.createElement('div', {
                  key: e.id, className: 'agenda-card', style: { '--cc': c }, onClick: () => onOpen(e),
                },
                  React.createElement('span', { className: 'agenda-time' },
                    e.allDay ? 'All day' : fmtTime(e.start) + ' – ' + fmtTime(e.end)),
                  React.createElement('div', { style: { minWidth: 0 } },
                    React.createElement('div', { className: 'agenda-ev-title' }, e.title),
                    (e.location || e.notes)
                      ? React.createElement('div', { className: 'agenda-ev-meta' },
                          e.location ? React.createElement('span', { style: { display: 'inline-flex', alignItems: 'center', gap: 4, whiteSpace: 'nowrap' } }, React.createElement(Icons.pin, { size: 12 }), e.location) : null,
                          e.notes ? React.createElement('span', null, e.notes) : null)
                      : null));
              })));
        })));
}

/* ---------- WEEK ---------- */
function WeekView({ cursor, today, events, groupColor, onOpen, onNewAt }) {
  const weekStart = startOfWeek(cursor);
  const days = [];
  for (let i = 0; i < 7; i++) days.push(addDays(weekStart, i));
  const map = eventsByDay(events);
  const HOUR = 52;
  const hours = [];
  for (let h = 0; h < 24; h++) hours.push(h);
  const now = new Date();
  const nowTop = (now.getHours() * 60 + now.getMinutes()) / 60 * HOUR;
  const showNow = days.some(d => isSameDay(d, now));

  const scrollRef = React.useRef(null);
  React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = 7 * HOUR; }, []);

  // All-day events get their own band — without it, all-day items (and any
  // past all-day work) silently vanish from the week.
  const allDayHas = days.some(d => (map[dateKey(d)] || []).some(e => e.allDay));

  return React.createElement('div', { className: 'week view-anim' },
    React.createElement('div', { className: 'week-head' },
      React.createElement('div', { className: 'corner' }),
      days.map((d, i) =>
        React.createElement('div', { key: i, className: 'week-hcell' + (isSameDay(d, today) ? ' today-col' : '') },
          React.createElement('div', { className: 'wd' }, WEEKDAYS[i]),
          React.createElement('div', { className: 'wn' }, d.getDate())))),
    React.createElement('div', { className: 'week-allday' + (allDayHas ? ' has' : '') },
      React.createElement('div', { className: 'wad-label' }, 'all-day'),
      days.map((d, i) => {
        const adl = (map[dateKey(d)] || []).filter(e => e.allDay);
        return React.createElement('div', {
          key: i, className: 'wad-col' + (i >= 5 ? ' we' : '') + (isSameDay(d, today) ? ' today-col' : ''),
          onClick: () => onNewAt(d),
        },
          adl.map(e => React.createElement('div', {
            key: e.id, className: 'wad-chip', style: { '--cc': groupColor(e.group) },
            title: e.title, onClick: (ev) => { ev.stopPropagation(); onOpen(e); },
          }, e.title)));
      })),
    React.createElement('div', { className: 'week-scroll', ref: scrollRef },
      React.createElement('div', { className: 'week-grid' },
        React.createElement('div', { className: 'week-hours' },
          hours.map(h => React.createElement('div', { key: h, className: 'hour-row' },
            h > 0 ? React.createElement('span', { className: 'hour-label' }, fmtTime(h * 60)) : null))),
        days.map((d, di) => {
          const list = (map[dateKey(d)] || []).filter(e => !e.allDay);
          const we = di >= 5;
          return React.createElement('div', { key: di, className: 'week-col' + (we ? ' we' : ''), style: { position: 'relative' },
            onClick: (e) => {
              const rect = e.currentTarget.getBoundingClientRect();
              const mins = Math.max(0, Math.round(((e.clientY - rect.top) / HOUR) * 60 / 30) * 30);
              onNewAt(d, mins);
            } },
            hours.map(h => React.createElement('div', { key: h, className: 'hour-row' })),
            list.map(e => {
              const top = e.start / 60 * HOUR;
              const height = Math.max(22, (e.end - e.start) / 60 * HOUR - 2);
              const c = groupColor(e.group);
              return React.createElement('div', {
                key: e.id, className: 'week-ev', style: { top: top + 'px', height: height + 'px', '--cc': c },
                onClick: (ev) => { ev.stopPropagation(); onOpen(e); },
              },
                React.createElement('div', { className: 'we-time' }, fmtTime(e.start)),
                React.createElement('div', { className: 'we-title' }, e.title));
            }),
            showNow && isSameDay(d, now)
              ? React.createElement('div', { style: { position: 'absolute', left: 0, right: 0, top: nowTop + 'px', height: 2, background: 'var(--critical)', zIndex: 4 } },
                  React.createElement('span', { style: { position: 'absolute', left: -4, top: -3, width: 8, height: 8, borderRadius: '50%', background: 'var(--critical)' } }))
              : null);
        }))));
}

Object.assign(window, { MonthView, WeekView, AgendaView, eventsByDay });
