// Kalender screen — week grid with overlap density

function ScreenKalender({ wide, activeGroupId, onChangeGroup, onOpenSession }) {
  const t = window.t;
  const [view, setView] = React.useState('week');
  const [weekOffset, setWeekOffset] = React.useState(0);

  return (
    <div style={{ padding: wide ? 0 : '16px 0 100px' }}>
      <div style={{ padding: wide ? '0 0 16px' : '0 16px 14px' }}>
        <div style={{
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          marginBottom: 4,
        }}>
          <div>
            <div style={{
              fontFamily: 'Space Grotesk, system-ui', fontSize: 13, fontWeight: 500,
              color: 'var(--muted)', letterSpacing: 0.5, textTransform: 'uppercase',
            }}>
              {t('kw')} {window.weekKW(weekOffset)} · {t('crew_kalender')}
            </div>
            <h1 style={{
              fontFamily: 'Space Grotesk, system-ui', fontSize: 30, fontWeight: 700,
              color: 'var(--text)', letterSpacing: -0.8, margin: '2px 0 0',
            }}>{weekOffset === 0 ? t('diese_woche') : weekOffset === 1 ? t('naechste_woche') : `${t('kw')} ${window.weekKW(weekOffset)}`}</h1>
          </div>
          <div style={{ display: 'flex', gap: 6 }}>
            <RoundIconBtn onClick={() => setWeekOffset(o => Math.max(0, o - 1))} disabled={weekOffset === 0}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M15 6l-6 6 6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </RoundIconBtn>
            <RoundIconBtn onClick={() => setWeekOffset(o => o + 1)}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M9 6l6 6-6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>
            </RoundIconBtn>
          </div>
        </div>

        {!wide && (
          <div style={{ marginTop: 12 }}>
            <window.GroupFilter active={activeGroupId} onChange={onChangeGroup} />
          </div>
        )}

        <div style={{ display: 'flex', gap: 6, marginTop: wide ? 14 : 0 }}>
          <Chip color="mint" active={view === 'week'} onClick={() => setView('week')}>{t('woche')}</Chip>
          <Chip color="violet" active={view === 'heatmap'} onClick={() => setView('heatmap')}>{t('heatmap')}</Chip>
        </div>
      </div>

      {view === 'week' ? (
        <WeekGrid wide={wide} onOpenSession={onOpenSession} weekOffset={weekOffset} activeGroupId={activeGroupId} />
      ) : (
        <Heatmap wide={wide} onOpenSession={onOpenSession} activeGroupId={activeGroupId} />
      )}
    </div>
  );
}

function RoundIconBtn({ children, onClick, disabled }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      appearance: 'none', cursor: disabled ? 'default' : 'pointer',
      width: 34, height: 34, borderRadius: 999,
      background: 'var(--surface)', border: '1px solid var(--border)',
      color: disabled ? 'var(--muted)' : 'var(--text)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      opacity: disabled ? 0.4 : 1,
    }}>{children}</button>
  );
}

function WeekGrid({ wide, onOpenSession, weekOffset, activeGroupId }) {
  const HOURS_START = 14;
  const HOURS_END = 27;
  const days = window.dayLabelsShort();
  // On desktop, taller rows so the calendar fills the available height instead
  // of occupying only a small part of the screen.
  const HOUR_H = wide ? 46 : 28;
  const filterGroupId = activeGroupId === 'all' ? null : activeGroupId;

  const blocksByDay = React.useMemo(() => {
    const result = {};
    const weekDates = window.weekDatesFor(weekOffset);
    for (let dow = 0; dow < 7; dow++) {
      const dateKey = window.freeDateKey(weekDates[dow]);
      const blocks = [];
      let cur = null;
      let curSet = '';
      for (let h = HOURS_START; h <= HOURS_END; h++) {
        const free = window.whoIsFree(dow, h, filterGroupId, dateKey);
        const key = free.slice().sort().join(',');
        if (free.length >= 2 && key === curSet) {
          cur.to = h + 1;
        } else {
          if (cur && cur.friends.length >= 2) blocks.push(cur);
          if (free.length >= 2) {
            cur = { dow, from: h, to: h + 1, friends: free };
            curSet = key;
          } else {
            cur = null; curSet = '';
          }
        }
      }
      if (cur && cur.friends.length >= 2) blocks.push(cur);
      result[dow] = blocks;
    }
    return result;
  }, [filterGroupId, weekOffset]);

  const dayNumbers = window.weekDatesFor(weekOffset).map(d => d.getDate());

  // total members in the active scope (for intensity normalization)
  const scopeSize = filterGroupId
    ? window.GROUPS_BY_ID[filterGroupId].memberIds.length
    : window.FRIENDS.length;

  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '40px repeat(7, 1fr)',
      gap: 0,
      padding: wide ? 0 : '0 12px',
      fontFamily: 'Space Grotesk, system-ui',
    }}>
      <div />
      {days.map((d, i) => {
        const isToday = i === window.TODAY_DOW && weekOffset === 0;
        return (
          <div key={d} style={{
            textAlign: 'center', padding: '0 0 10px',
          }}>
            <div style={{
              fontSize: 10, fontWeight: 600, letterSpacing: 0.8, textTransform: 'uppercase',
              color: isToday ? 'var(--accent)' : 'var(--muted)',
            }}>{d}</div>
            <div style={{
              fontFamily: 'JetBrains Mono, monospace',
              fontSize: 14, fontWeight: 600, marginTop: 2,
              color: isToday ? 'var(--accent)' : 'var(--text)',
              width: 26, height: 26, borderRadius: '50%',
              margin: '2px auto 0',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              background: isToday ? 'color-mix(in oklab, var(--accent) 16%, transparent)' : 'transparent',
            }}>{dayNumbers[i]}</div>
          </div>
        );
      })}

      <div style={{ position: 'relative', borderTop: '1px solid var(--border)' }}>
        {Array.from({ length: HOURS_END - HOURS_START }).map((_, i) => (
          <div key={i} style={{
            height: HOUR_H,
            borderBottom: '1px dashed color-mix(in oklab, var(--border) 60%, transparent)',
            fontFamily: 'JetBrains Mono, monospace', fontSize: 10,
            color: 'var(--muted)',
            paddingTop: 2, paddingRight: 6, textAlign: 'right',
            opacity: (HOURS_START + i) % 2 === 0 ? 1 : 0.4,
          }}>
            {(HOURS_START + i) % 2 === 0 ? `${((HOURS_START + i) % 24).toString().padStart(2, '0')}` : ''}
          </div>
        ))}
      </div>
      {days.map((d, dow) => {
        const blocks = blocksByDay[dow] || [];
        const isToday = dow === window.TODAY_DOW && weekOffset === 0;
        return (
          <div key={dow} style={{
            position: 'relative',
            borderTop: '1px solid var(--border)',
            borderLeft: '1px solid color-mix(in oklab, var(--border) 60%, transparent)',
            background: isToday ? 'color-mix(in oklab, var(--accent) 5%, transparent)' : 'transparent',
          }}>
            {Array.from({ length: HOURS_END - HOURS_START }).map((_, i) => (
              <div key={i} style={{
                height: HOUR_H,
                borderBottom: '1px dashed color-mix(in oklab, var(--border) 30%, transparent)',
              }} />
            ))}
            {blocks.map((b, bi) => {
              const top = (b.from - HOURS_START) * HOUR_H;
              const height = (b.to - b.from) * HOUR_H - 2;
              const intensity = b.friends.length / scopeSize;
              const sg = window.sharedGames(b.friends);
              const topGame = sg[0]?.game;
              const sessionGroups = window.groupsForSession(b.friends);
              return (
                <button key={bi} onClick={() => onOpenSession({
                  dow, from: b.from, to: b.to, friends: b.friends,
                  topGame, topVotes: sg[0]?.votes || 0,
                  dayOffset: ((dow - window.TODAY_DOW) + 7) % 7 + weekOffset * 7,
                  groups: sessionGroups,
                })} style={{
                  appearance: 'none', cursor: 'pointer',
                  position: 'absolute', top, left: 2, right: 2, height,
                  borderRadius: 8, padding: '4px 5px',
                  background: `color-mix(in oklab, var(--accent) ${Math.round(20 + intensity * 50)}%, var(--surface))`,
                  border: `1px solid color-mix(in oklab, var(--accent) ${Math.round(40 + intensity * 40)}%, var(--border))`,
                  color: 'var(--text)',
                  display: 'flex', flexDirection: 'column', alignItems: 'flex-start',
                  justifyContent: 'flex-start', gap: 2,
                  overflow: 'hidden',
                  textAlign: 'left',
                }}>
                  <div style={{
                    fontFamily: 'JetBrains Mono, monospace',
                    fontSize: 9, fontWeight: 600, color: 'var(--bg-deep)',
                    background: 'var(--accent)', padding: '1px 4px', borderRadius: 3,
                  }}>{b.friends.length}</div>
                  {height > 38 && topGame && (
                    <div style={{
                      fontSize: 9, color: 'var(--text)', fontWeight: 600,
                      letterSpacing: 0.1,
                      overflow: 'hidden', textOverflow: 'ellipsis',
                      width: '100%', whiteSpace: 'nowrap',
                    }}>{topGame.title}</div>
                  )}
                </button>
              );
            })}
          </div>
        );
      })}
    </div>
  );
}

function Heatmap({ wide, onOpenSession, activeGroupId }) {
  const HOURS = Array.from({ length: 12 }, (_, i) => 14 + i);
  const days = window.dayLabelsShort();
  // The heatmap always shows the current week, so map each weekday column to its
  // real date for the per-date "freie Tage" override.
  const weekDates = window.weekDatesFor(0);
  const filterGroupId = activeGroupId === 'all' ? null : activeGroupId;
  const scopeSize = filterGroupId
    ? window.GROUPS_BY_ID[filterGroupId].memberIds.length
    : window.FRIENDS.length;
  const t = window.t;
  // On desktop, square cells would make the heatmap far taller than the
  // viewport. Cap the width and use short fixed-height rows so the whole grid
  // stays compact and fits on screen.
  const cellHeight = wide ? 32 : null;

  return (
    <div style={{ padding: wide ? 0 : '0 16px', maxWidth: wide ? 640 : 'none' }}>
      <div style={{
        fontFamily: 'Space Grotesk, system-ui', fontSize: 12, color: 'var(--muted)',
        marginBottom: 12,
      }}>{t('wie_viele_frei')}</div>

      <div style={{
        display: 'grid', gridTemplateColumns: '36px repeat(7, 1fr)', gap: 4,
      }}>
        <div />
        {days.map((d, i) => {
          const isToday = i === window.TODAY_DOW;
          return (
            <div key={d} style={{
              textAlign: 'center',
              fontFamily: 'Space Grotesk, system-ui', fontSize: 10, fontWeight: 600,
              letterSpacing: 0.8, textTransform: 'uppercase',
              color: isToday ? 'var(--accent)' : 'var(--muted)',
              paddingBottom: 4,
            }}>{d}</div>
          );
        })}
        {HOURS.map(h => (
          <React.Fragment key={h}>
            <div style={{
              fontFamily: 'JetBrains Mono, monospace', fontSize: 10,
              color: 'var(--muted)', display: 'flex', alignItems: 'center',
            }}>{String(h % 24).padStart(2, '0')}</div>
            {days.map((d, dow) => {
              const free = window.whoIsFree(dow, h, filterGroupId, window.freeDateKey(weekDates[dow]));
              const n = free.length;
              const intensity = n / scopeSize;
              const sg = window.sharedGames(free);
              return (
                <button key={d} onClick={() => n >= 2 && onOpenSession({
                  dow, from: h, to: h + 1, friends: free,
                  topGame: sg[0]?.game || null, topVotes: sg[0]?.votes || 0,
                  dayOffset: ((dow - window.TODAY_DOW) + 7) % 7,
                  groups: window.groupsForSession(free),
                })} style={{
                  appearance: 'none', cursor: n >= 2 ? 'pointer' : 'default',
                  aspectRatio: cellHeight ? 'auto' : '1',
                  height: cellHeight || 'auto',
                  borderRadius: 6,
                  background: n === 0 ? 'var(--surface)'
                    : `color-mix(in oklab, var(--accent) ${Math.round(15 + intensity * 70)}%, var(--surface))`,
                  border: '1px solid color-mix(in oklab, var(--border) 80%, transparent)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontFamily: 'JetBrains Mono, monospace', fontSize: 11, fontWeight: 600,
                  color: intensity >= 0.6 ? 'var(--bg-deep)' : n >= 2 ? 'var(--accent)' : 'var(--muted)',
                }}>{n || ''}</button>
              );
            })}
          </React.Fragment>
        ))}
      </div>

      <div style={{
        display: 'flex', alignItems: 'center', gap: 8, marginTop: 20,
        fontFamily: 'Space Grotesk, system-ui', fontSize: 11, color: 'var(--muted)',
      }}>
        <span>{t('weniger')}</span>
        {[0.1, 0.3, 0.5, 0.7, 0.9].map(i => (
          <div key={i} style={{
            width: 18, height: 18, borderRadius: 4,
            background: `color-mix(in oklab, var(--accent) ${Math.round(15 + i * 70)}%, var(--surface))`,
            border: '1px solid var(--border)',
          }} />
        ))}
        <span>{t('mehr_label')}</span>
      </div>
    </div>
  );
}

Object.assign(window, { ScreenKalender });
