// Tempo — Month-calendar bottom sheet.
//
// Tapping any day in the home week strip opens this. Renders a 6×7 month
// grid with completion state pulled from `tempo.dayRecords`, prev/next
// month navigation, and a "Today" jump-back when off the current month.
// Read-only: tapping a date is a no-op (no drill-in on v1).
//
// Cell state is derived from window.TempoMinify.dayRecord(dateStr) and
// updates live via the `tempo-day-changed` event the data layer dispatches.
//
// Visual vocabulary borrows from tempo-week-progress.jsx (DayDot):
//   done            → filled accent, accentInk number
//   today, undone   → ring + halo, ink number
//   started, undone → ring (no halo)
//   target, past    → faint outlined ring (theme.line)
//   future / non-target idle → dim number
//   spillover (adjacent month) → very dim number, no chrome
//   minified day    → small orange dot in the cell corner

const { useState: useStateCAL, useEffect: useEffectCAL, useMemo: useMemoCAL } = React;

// Mon-first day-of-week index. JS getDay is Sun=0..Sat=6.
function _monIdx(date) { return (date.getDay() + 6) % 7; }

const _WEEKDAY_LABELS = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];

// Spillover text colors — direct rgba so we can tune translucency
// independently of theme.subtle (which is a fill, not a text color).
function _spilloverColor(dark) {
  return dark ? 'rgba(239,231,214,0.18)' : 'rgba(21,32,26,0.22)';
}

function CalendarSheet({ theme, targetDays = [], initialDate, onClose }) {
  const M = window.TempoMinify;
  const Icon = window.TempoIcon;

  // Anchor: the month being viewed. Initialized from the tapped date so
  // tapping a Monday opens on that week's month, not always today's.
  const [viewMonth, setViewMonth] = useStateCAL(() => {
    const seed = (() => {
      if (!initialDate) return new Date();
      const [Y, Mo, D] = initialDate.split('-').map(n => parseInt(n, 10));
      return new Date(Y, Mo - 1, D);
    })();
    return new Date(seed.getFullYear(), seed.getMonth(), 1);
  });

  // Live re-render when any day record changes (workout completed elsewhere,
  // minify level toggled). Cheap: forces dayRecord re-reads on visible cells.
  const [, force] = useStateCAL(0);
  useEffectCAL(() => {
    const onChange = () => force(n => n + 1);
    window.addEventListener('tempo-day-changed', onChange);
    window.addEventListener('tempo-week-changed', onChange);
    return () => {
      window.removeEventListener('tempo-day-changed', onChange);
      window.removeEventListener('tempo-week-changed', onChange);
    };
  }, []);

  const today = useMemoCAL(() => {
    const d = new Date(); d.setHours(0, 0, 0, 0); return d;
  }, []);
  const todayStr = M.todayKey(today);

  // 6×7 grid: first cell = the Monday of the week containing the 1st of the
  // viewed month. Always renders 42 cells so the sheet's height is stable
  // across months (some months span 5 weeks, some 6).
  const cells = useMemoCAL(() => {
    const firstOfMonth = new Date(viewMonth.getFullYear(), viewMonth.getMonth(), 1);
    const lead = _monIdx(firstOfMonth);
    const start = new Date(firstOfMonth);
    start.setDate(1 - lead);
    const out = [];
    for (let i = 0; i < 42; i++) {
      const d = new Date(start);
      d.setDate(start.getDate() + i);
      out.push(d);
    }
    return out;
  }, [viewMonth.getTime()]);

  const monthName = viewMonth.toLocaleDateString(undefined, { month: 'long', year: 'numeric' });
  const isCurrentMonthView =
    viewMonth.getFullYear() === today.getFullYear() &&
    viewMonth.getMonth() === today.getMonth();

  const goPrev = () => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() - 1, 1));
  const goNext = () => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 1));
  const goToday = () => setViewMonth(new Date(today.getFullYear(), today.getMonth(), 1));

  // Monthly summary: workouts completed + how many of those landed on a
  // target day. Pure derivation; cheap to compute once per render.
  const summary = useMemoCAL(() => {
    let workouts = 0;
    let targetHit = 0;
    let targetTotal = 0;
    const Y = viewMonth.getFullYear();
    const Mo = viewMonth.getMonth();
    const daysInMonth = new Date(Y, Mo + 1, 0).getDate();
    for (let day = 1; day <= daysInMonth; day++) {
      const d = new Date(Y, Mo, day);
      const isTarget = !!targetDays[_monIdx(d)];
      if (isTarget) targetTotal++;
      const rec = M.peekDayRecord(M.todayKey(d));
      if (rec?.workoutCompleted) {
        workouts++;
        if (isTarget) targetHit++;
      }
    }
    return { workouts, targetHit, targetTotal };
  }, [viewMonth.getTime(), targetDays.join(','), force]);

  const chevronBtn = {
    background: 'transparent', border: 'none', cursor: 'pointer',
    color: theme.ink2, padding: 8,
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    borderRadius: 10,
  };

  return (
    <>
      {/* Backdrop */}
      <div onClick={onClose} style={{
        position: 'absolute', inset: 0,
        background: 'rgba(0,0,0,0.4)', zIndex: 50,
      }}/>
      {/* Sheet */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0,
        background: theme.bg, borderRadius: '20px 20px 0 0',
        padding: '8px 20px var(--tempo-bottom-cta)',
        zIndex: 51,
        maxHeight: '92%',
        display: 'flex', flexDirection: 'column',
        boxShadow: '0 -8px 32px rgba(0,0,0,0.3)',
        animation: 'tempoSlide 240ms ease-out',
        fontFamily: theme.ui,
      }}>
        {/* Grabber */}
        <div style={{
          width: 36, height: 4, borderRadius: 2,
          background: theme.line, margin: '8px auto 12px',
        }}/>

        {/* Month header */}
        <div style={{
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          marginBottom: 14,
        }}>
          <button onClick={goPrev} aria-label="Previous month" style={chevronBtn}>
            <Icon name="chevron-left" size={22} strokeWidth={2}/>
          </button>
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2 }}>
            <div style={{
              fontFamily: theme.timerFont, fontSize: 22, color: theme.ink,
              letterSpacing: '-0.01em', lineHeight: 1.1,
            }}>{monthName}</div>
            {!isCurrentMonthView && (
              <button onClick={goToday} style={{
                background: 'transparent', border: 'none', cursor: 'pointer',
                color: theme.ink2, fontSize: 11, padding: '2px 0 0',
                fontFamily: theme.ui, letterSpacing: '0.16em', textTransform: 'uppercase',
                fontWeight: 600,
              }}>Today</button>
            )}
          </div>
          <button onClick={goNext} aria-label="Next month" style={chevronBtn}>
            <Icon name="chevron-right" size={22} strokeWidth={2}/>
          </button>
        </div>

        {/* Weekday header */}
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4,
          marginBottom: 6, padding: '0 2px',
        }}>
          {_WEEKDAY_LABELS.map((d, i) => (
            <div key={i} style={{
              textAlign: 'center', fontSize: 10, fontWeight: 600,
              letterSpacing: '0.16em', textTransform: 'uppercase',
              color: theme.ink2,
            }}>{d}</div>
          ))}
        </div>

        {/* Day grid */}
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4,
          padding: '0 2px',
        }}>
          {cells.map((date, i) => {
            const inMonth = date.getMonth() === viewMonth.getMonth() && date.getFullYear() === viewMonth.getFullYear();
            const dateStr = M.todayKey(date);
            const isToday = dateStr === todayStr;
            const isFuture = date.getTime() > today.getTime();
            const isTarget = !!targetDays[_monIdx(date)];
            // Skip lookup for spillover cells — they're decorative. Use the
            // non-mutating peek so we don't write empty records for every
            // visible date on every render.
            const rec = inMonth ? M.peekDayRecord(dateStr) : null;
            const done = !!rec?.workoutCompleted;
            const started = !!rec?.workoutStarted && !done;
            const minified = done && (rec?.minifyLevel || 0) > 0;

            // Layered styling — start with defaults, then override per state.
            let bg = 'transparent';
            let border = '1px solid transparent';
            let textColor = theme.ink2;
            let fontWeight = 400;
            let halo = 'none';

            if (!inMonth) {
              textColor = _spilloverColor(theme.dark);
            } else if (done) {
              bg = theme.accent;
              textColor = theme.accentInk;
              fontWeight = 600;
              if (isToday) halo = `0 0 0 3px ${theme.accent}26`;
            } else if (started) {
              border = `1.5px solid ${theme.accent}`;
              textColor = theme.ink;
            } else if (isToday) {
              border = `1.5px solid ${theme.accent}`;
              textColor = theme.ink;
              fontWeight = 600;
              halo = `0 0 0 3px ${theme.accent}26`;
            } else if (isFuture) {
              textColor = theme.ink2;
            } else if (isTarget) {
              border = `1px solid ${theme.line}`;
              textColor = theme.ink2;
            } else {
              textColor = theme.ink2;
            }

            return (
              <div key={i} style={{
                aspectRatio: '1 / 1',
                position: 'relative',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontSize: 13, color: textColor, fontWeight,
                background: bg,
                border,
                borderRadius: '50%',
                fontVariantNumeric: 'tabular-nums',
                boxShadow: halo,
              }}>
                {date.getDate()}
                {minified && (
                  <div style={{
                    position: 'absolute', bottom: 1, right: 1,
                    width: 6, height: 6, borderRadius: 3,
                    background: '#ff5e3a',
                    boxShadow: `0 0 0 1.5px ${theme.bg}`,
                  }}/>
                )}
              </div>
            );
          })}
        </div>

        {/* Monthly summary */}
        <div style={{
          marginTop: 18, padding: '10px 4px 2px',
          textAlign: 'center', fontSize: 12, color: theme.ink2,
          letterSpacing: '0.02em', lineHeight: 1.5,
        }}>
          <span style={{ color: theme.ink, fontWeight: 600 }}>{summary.workouts}</span>
          {' '}workout{summary.workouts === 1 ? '' : 's'}
          {summary.targetTotal > 0 && (
            <>
              {' · '}
              <span style={{ color: theme.ink, fontWeight: 600 }}>{summary.targetHit}</span>
              {`/${summary.targetTotal} target days`}
            </>
          )}
        </div>
      </div>
    </>
  );
}

window.CalendarSheet = CalendarSheet;
