// Sessions screen — project list, each project shows up to 5 recent sessions.
// Model: Project (long-lived working directory) → Session (a Claude Code conversation).
//
// Filters — operate at SESSION level:
//   All    = project cards (5 recent sessions each). Pinned sessions float inside card.
//   Active = flat list of running / awaiting sessions across all projects.
//   Pinned = flat list of user-pinned sessions across all projects.
//
// Row indicators:
//   running → green accent spinner
//   unread  → amber dot (awaiting you or pending)
//   idle    → faint gray dot
//
// Pin UX: swipe the row left to reveal Pin / Archive. Pinned rows show a 📌 marker
// and float to the top of their project card (in All view).

const MAX_ROWS_PER_CARD = 5;

const SEEDEX_PROJECTS = [
  {
    id: 'auth-svc',
    name: 'auth-service',
    repo: 'vercel/auth',
    branch: 'main',
    sessions: [
      { id: 's1',  title: 'Refactor the auth middleware',      status: 'awaiting', lastBeatMins: 0,    pending: 1, pinnedByDefault: true },
      { id: 's2',  title: 'Add rate-limit tests',              status: 'editing',  lastBeatMins: 1,    pending: 0 },
      { id: 's3',  title: 'Fix cookie SameSite bug',           status: 'idle',     lastBeatMins: 47,   pending: 0 },
      { id: 's7',  title: 'Investigate OAuth token refresh',   status: 'idle',     lastBeatMins: 210,  pending: 0 },
      { id: 's8',  title: 'Audit password reset flow',         status: 'idle',     lastBeatMins: 1440, pending: 0 },
      { id: 's9',  title: 'Migrate to jose@5',                 status: 'idle',     lastBeatMins: 2880, pending: 0, pinnedByDefault: true },
      { id: 's10', title: 'Clean up legacy JWT helpers',       status: 'idle',     lastBeatMins: 4320, pending: 0 },
      { id: 's11', title: 'Wire up Clerk dev keys',            status: 'idle',     lastBeatMins: 5760, pending: 0 },
      { id: 's12', title: 'Add session revocation endpoint',   status: 'idle',     lastBeatMins: 7200, pending: 0 },
      { id: 's13', title: 'Explore WebAuthn support',          status: 'idle',     lastBeatMins: 10080, pending: 0 },
    ],
  },
  {
    id: 'billing',
    name: 'billing-web',
    repo: 'vercel/billing',
    branch: 'fix/invoice-pdf',
    sessions: [
      { id: 's4',  title: 'Generate PDF invoices',             status: 'thinking', lastBeatMins: 0,    pending: 0 },
      { id: 's5',  title: 'Stripe webhook retries',            status: 'idle',     lastBeatMins: 180,  pending: 0 },
      { id: 's14', title: 'Tax calc refactor',                 status: 'idle',     lastBeatMins: 2880, pending: 0 },
      { id: 's15', title: 'Usage-based billing spike',         status: 'idle',     lastBeatMins: 7200, pending: 0 },
    ],
  },
  {
    id: 'docs',
    name: 'docs-site',
    repo: 'vercel/docs',
    branch: 'main',
    sessions: [
      { id: 's6',  title: 'Update CLI reference for 0.4.1',    status: 'idle',     lastBeatMins: 2880, pending: 0 },
      { id: 's16', title: 'Rewrite getting-started guide',     status: 'idle',     lastBeatMins: 7200, pending: 0 },
    ],
  },
];

// Flatten project→sessions with projectId/Name stamped on each session
const ALL_SESSIONS = SEEDEX_PROJECTS.flatMap(p =>
  p.sessions.map(s => ({ ...s, projectId: p.id, projectName: p.name }))
);

const DEFAULT_PINNED_SESSION_IDS = ALL_SESSIONS.filter(s => s.pinnedByDefault).map(s => s.id);

// ——— helpers ——————————————————————————————————————————————————————————————

function rowState(s) {
  if (s.status === 'thinking' || s.status === 'editing') return 'running';
  if (s.status === 'awaiting' || s.pending > 0) return 'unread';
  return 'idle';
}

function formatBeat(mins) {
  if (mins === 0) return 'just now';
  if (mins < 60) return `${mins}m ago`;
  if (mins < 1440) return `${Math.round(mins / 60)}h ago`;
  return `${Math.round(mins / 1440)}d ago`;
}

// ——— atoms ————————————————————————————————————————————————————————————————

function RowIndicator({ state, t }) {
  if (state === 'running') {
    return (
      <svg width="14" height="14" viewBox="0 0 14 14" style={{ flexShrink: 0, animation: 'sdxSpin 1.1s linear infinite' }}>
        <circle cx="7" cy="7" r="5.5" fill="none" stroke={t.accent} strokeOpacity="0.2" strokeWidth="1.5" />
        <path d="M7 1.5 A 5.5 5.5 0 0 1 12.5 7" fill="none" stroke={t.accent} strokeWidth="1.5" strokeLinecap="round" />
      </svg>
    );
  }
  if (state === 'unread') {
    return <span style={{ width: 8, height: 8, borderRadius: '50%', background: t.warn, flexShrink: 0, margin: '0 3px' }} />;
  }
  return <span style={{ width: 6, height: 6, borderRadius: '50%', background: t.inkFaint, opacity: 0.4, flexShrink: 0, margin: '0 4px' }} />;
}

// Tiny pushpin glyph — used to mark pinned sessions inline.
function PinGlyph({ color, size = 11 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 16 16" fill="none" style={{ flexShrink: 0 }}>
      <path
        d="M10.5 1.5 L14.5 5.5 L12 6 L9 9 L10 13 L7.5 10.5 L3 15 L4 11.5 L1 8.5 L5 7.5 L8 4.5 Z"
        fill={color} stroke={color} strokeWidth="1" strokeLinejoin="round"
      />
    </svg>
  );
}

// ——— swipeable session row ————————————————————————————————————————————————
// Renders pin/archive beneath; parent row slides left when swipedId matches.

function SessionRow({
  t,
  session,
  pinned,
  onOpen,
  onTogglePin,
  onArchive,
  swipedId,
  setSwipedId,
  showProject = false,
  isLast = false,
  compact = false,
}) {
  const s = session;
  const state = rowState(s);
  const swiped = swipedId === s.id;

  // Simple touch-swipe: if finger moved > 30px left, open; > 30px right, close.
  const startX = React.useRef(null);
  const onTouchStart = (e) => { startX.current = e.touches[0].clientX; };
  const onTouchEnd = (e) => {
    if (startX.current == null) return;
    const dx = e.changedTouches[0].clientX - startX.current;
    if (dx < -30) setSwipedId(s.id);
    else if (dx > 30) setSwipedId(null);
    startX.current = null;
  };

  const REVEAL_WIDTH = 124; // 56 + 60 + gap buffer

  return (
    <div
      style={{
        position: 'relative',
        overflow: 'hidden',
        borderBottom: isLast ? 'none' : `1px solid ${t.line}`,
      }}
      onTouchStart={onTouchStart}
      onTouchEnd={onTouchEnd}
    >
      {/* Revealed actions */}
      <div style={{
        position: 'absolute', inset: 0,
        display: 'flex', justifyContent: 'flex-end', alignItems: 'stretch',
      }}>
        <button
          onClick={(e) => { e.stopPropagation(); onTogglePin(s.id); setSwipedId(null); }}
          style={{
            width: 56, border: 'none', background: t.accentSoft, color: t.accentInk,
            fontFamily: SEEDEX_FONTS.mono, fontSize: 9, letterSpacing: 1.2, textTransform: 'uppercase',
            cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 4,
          }}
        >
          <PinGlyph color={t.accentInk} size={13} />
          {pinned ? 'Unpin' : 'Pin'}
        </button>
        <button
          onClick={(e) => { e.stopPropagation(); onArchive && onArchive(s.id); setSwipedId(null); }}
          style={{
            width: 60, border: 'none', background: t.warn, color: '#fff',
            fontFamily: SEEDEX_FONTS.mono, fontSize: 9, letterSpacing: 1.2, textTransform: 'uppercase',
            cursor: 'pointer',
          }}
        >
          Archive
        </button>
      </div>

      {/* Row content — slides left when swiped */}
      <div
        onClick={() => {
          if (swiped) { setSwipedId(null); return; }
          onOpen && onOpen(s.id);
        }}
        onContextMenu={(e) => { e.preventDefault(); onTogglePin(s.id); }}
        style={{
          position: 'relative',
          display: 'flex', gap: 12, alignItems: 'center',
          padding: compact ? '10px 2px' : '11px 2px',
          background: t.surface,
          transform: swiped ? `translateX(-${REVEAL_WIDTH}px)` : 'translateX(0)',
          transition: 'transform .25s cubic-bezier(.2,.8,.2,1)',
          cursor: 'pointer',
        }}
      >
        <RowIndicator state={state} t={t} />

        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}>
            {pinned && <PinGlyph color={t.accent} size={10} />}
            <div style={{
              fontFamily: SEEDEX_FONTS.display, fontSize: 15, letterSpacing: -0.2, lineHeight: 1.25,
              color: t.ink, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1, minWidth: 0,
            }}>
              {s.title}
            </div>
          </div>
          <div style={{
            marginTop: 2, fontFamily: SEEDEX_FONTS.mono, fontSize: 10, color: t.inkFaint, letterSpacing: 0.2,
            overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
          }}>
            {showProject && <span>{s.projectName} · </span>}
            {formatBeat(s.lastBeatMins)}
            {state === 'running' && <span style={{ color: t.accent, marginLeft: 8 }}>· running</span>}
            {state === 'unread' && <span style={{ color: t.warn, marginLeft: 8 }}>· needs you</span>}
          </div>
        </div>

        <span style={{ color: t.inkFaint, fontSize: 14, flexShrink: 0, lineHeight: 1, opacity: 0.5 }}>›</span>
      </div>
    </div>
  );
}

// ——— project card (used in All view) ——————————————————————————————————————

function ProjectCard({ t, project, pinnedIds, onOpen, onOpenProject, onTogglePin, onArchive, swipedId, setSwipedId }) {
  const p = project;
  // Within a project: pinned first, then running/unread, then by recency.
  const sorted = [...p.sessions].sort((a, b) => {
    const pa = pinnedIds.includes(a.id) ? 0 : 1;
    const pb = pinnedIds.includes(b.id) ? 0 : 1;
    if (pa !== pb) return pa - pb;
    const rank = x => { const st = rowState(x); return st === 'running' ? 0 : st === 'unread' ? 1 : 2; };
    const ra = rank(a), rb = rank(b);
    if (ra !== rb) return ra - rb;
    return a.lastBeatMins - b.lastBeatMins;
  });
  const shown = sorted.slice(0, MAX_ROWS_PER_CARD);
  const hidden = p.sessions.length - shown.length;
  const activeCount = p.sessions.filter(s => rowState(s) !== 'idle').length;

  return (
    <div style={{
      background: t.surface,
      border: `1px solid ${t.line}`,
      borderRadius: 18,
      padding: '14px 16px 4px',
    }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '0 0 12px' }}>
        <div
          onClick={() => onOpenProject && onOpenProject(p.id)}
          style={{ flex: 1, minWidth: 0, cursor: 'pointer' }}
        >
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
            <div style={{
              fontFamily: SEEDEX_FONTS.display, fontSize: 20, letterSpacing: -0.3, lineHeight: 1.1,
              color: t.ink, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            }}>
              {p.name}
            </div>
            {activeCount > 0 && (
              <span style={{
                fontFamily: SEEDEX_FONTS.mono, fontSize: 9, letterSpacing: 1, color: t.accent,
                textTransform: 'uppercase',
              }}>
                {activeCount} live
              </span>
            )}
          </div>
          <div style={{
            marginTop: 3, fontFamily: SEEDEX_FONTS.mono, fontSize: 10, color: t.inkFaint, letterSpacing: 0.3,
          }}>
            {p.repo} · {p.branch}
          </div>
        </div>

        <button
          onClick={(e) => { e.stopPropagation(); onOpen && onOpen(`new:${p.id}`); }}
          aria-label="New session"
          style={{
            display: 'flex', alignItems: 'center', gap: 4,
            padding: '6px 10px', borderRadius: 99,
            border: `1px solid ${t.line}`,
            background: 'transparent',
            color: t.ink,
            fontFamily: SEEDEX_FONTS.mono, fontSize: 10, letterSpacing: 1, textTransform: 'uppercase',
            cursor: 'pointer', flexShrink: 0,
          }}
        >
          <span style={{ fontSize: 12, lineHeight: 1 }}>+</span> New
        </button>
      </div>

      {/* Sessions */}
      <div style={{ borderTop: `1px solid ${t.line}` }}>
        {shown.map((s, i) => (
          <SessionRow
            key={s.id}
            t={t}
            session={s}
            pinned={pinnedIds.includes(s.id)}
            onOpen={onOpen}
            onTogglePin={onTogglePin}
            onArchive={onArchive}
            swipedId={swipedId}
            setSwipedId={setSwipedId}
            isLast={i === shown.length - 1 && hidden === 0}
          />
        ))}

        {hidden > 0 && (
          <button
            onClick={() => onOpenProject && onOpenProject(p.id)}
            style={{
              width: '100%', border: 'none', background: 'transparent',
              color: t.inkSoft, fontFamily: SEEDEX_FONTS.mono,
              fontSize: 10, letterSpacing: 1.2, textTransform: 'uppercase',
              padding: '11px 0 11px', cursor: 'pointer', textAlign: 'left',
              display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            }}
          >
            <span>{hidden} older session{hidden === 1 ? '' : 's'}</span>
            <span style={{ opacity: 0.6 }}>view all ›</span>
          </button>
        )}
      </div>
    </div>
  );
}

// ——— flat list (used in Active / Pinned views) ———————————————————————————

function FlatSessionList({ t, sessions, pinnedIds, onOpen, onTogglePin, onArchive, swipedId, setSwipedId }) {
  return (
    <div style={{
      margin: '0 16px',
      background: t.surface,
      border: `1px solid ${t.line}`,
      borderRadius: 18,
      padding: '4px 16px',
    }}>
      {sessions.map((s, i) => (
        <SessionRow
          key={s.id}
          t={t}
          session={s}
          pinned={pinnedIds.includes(s.id)}
          onOpen={onOpen}
          onTogglePin={onTogglePin}
          onArchive={onArchive}
          swipedId={swipedId}
          setSwipedId={setSwipedId}
          showProject
          isLast={i === sessions.length - 1}
        />
      ))}
    </div>
  );
}

// ——— filter chips ———————————————————————————————————————————————————————

function FilterChips({ t, value, onChange, counts }) {
  const chips = [
    { id: 'all',    label: 'All',    count: counts.all },
    { id: 'active', label: 'Active', count: counts.active },
    { id: 'pinned', label: 'Pinned', count: counts.pinned },
  ];
  return (
    <div style={{ padding: '0 24px 18px', display: 'flex', gap: 6 }}>
      {chips.map(c => {
        const selected = value === c.id;
        return (
          <button
            key={c.id}
            onClick={() => onChange(c.id)}
            style={{
              padding: '6px 12px', borderRadius: 99,
              border: `1px solid ${selected ? t.ink : t.line}`,
              background: selected ? t.ink : 'transparent',
              color: selected ? t.bg : t.inkSoft,
              fontFamily: SEEDEX_FONTS.mono, fontSize: 10, letterSpacing: 1, textTransform: 'uppercase',
              cursor: 'pointer', whiteSpace: 'nowrap',
              display: 'inline-flex', alignItems: 'center', gap: 6,
            }}
          >
            <span>{c.label}</span>
            <span style={{
              opacity: selected ? 0.7 : 0.5,
              fontVariantNumeric: 'tabular-nums',
            }}>{c.count}</span>
          </button>
        );
      })}
    </div>
  );
}

// ——— empty state ————————————————————————————————————————————————————————

function EmptyState({ t, filter }) {
  const msg = filter === 'active'
    ? { big: 'All quiet.', sub: 'Nothing running or waiting on you. Sessions you start here will appear as Active.' }
    : filter === 'pinned'
    ? { big: 'No pins yet.', sub: 'Swipe a session left and tap Pin to keep it close.' }
    : { big: 'No projects yet.', sub: 'Connect a working directory from your computer to get started.' };
  return (
    <div style={{
      margin: '24px 16px', padding: '36px 20px',
      border: `1px dashed ${t.line}`, borderRadius: 18,
      textAlign: 'center', color: t.inkSoft,
    }}>
      <div style={{ fontFamily: SEEDEX_FONTS.display, fontSize: 22, letterSpacing: -0.3, color: t.ink }}>
        {msg.big}
      </div>
      <div style={{ marginTop: 8, fontSize: 13, lineHeight: 1.5, maxWidth: 280, margin: '8px auto 0' }}>
        {msg.sub}
      </div>
    </div>
  );
}

// ——— main ————————————————————————————————————————————————————————————————

function SessionsScreen({ theme }) {
  const t = theme;
  const [filter, setFilter] = React.useState('all');
  const [pinnedIds, setPinnedIds] = React.useState(DEFAULT_PINNED_SESSION_IDS);
  const [swipedId, setSwipedId] = React.useState(null);

  const togglePin = (id) => {
    setPinnedIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);
  };
  const archive = (id) => {
    // stub — would remove the session from the list
    const el = document.activeElement; if (el && el.blur) el.blur();
  };
  const openSession = (id) => {
    setSwipedId(null);
    const el = document.activeElement; if (el && el.blur) el.blur();
  };
  const openProject = (id) => {
    setSwipedId(null);
    const el = document.activeElement; if (el && el.blur) el.blur();
  };

  // Derived: session-level filter results.
  const activeSessions = ALL_SESSIONS
    .filter(s => rowState(s) !== 'idle')
    .sort((a, b) => a.lastBeatMins - b.lastBeatMins);
  const pinnedSessions = ALL_SESSIONS
    .filter(s => pinnedIds.includes(s.id))
    .sort((a, b) => a.lastBeatMins - b.lastBeatMins);

  const counts = {
    all: SEEDEX_PROJECTS.length,
    active: activeSessions.length,
    pinned: pinnedSessions.length,
  };

  const totalSessions = ALL_SESSIONS.length;
  const totalAwaiting = ALL_SESSIONS.filter(s => rowState(s) === 'unread').length;
  const totalRunning = ALL_SESSIONS.filter(s => rowState(s) === 'running').length;

  return (
    <div style={{ padding: '72px 0 0', height: '100%', overflow: 'auto', background: t.bg, color: t.ink, fontFamily: SEEDEX_FONTS.sans }}>
      <style>{`@keyframes sdxSpin { to { transform: rotate(360deg) } }`}</style>

      {/* Eyebrow */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '0 24px 8px' }}>
        <div style={{ fontFamily: SEEDEX_FONTS.mono, fontSize: 11, letterSpacing: 1.4, textTransform: 'uppercase', color: t.inkFaint }}>
          SEEDEX · Sessions
        </div>
        {totalRunning > 0 && (
          <div style={{ display: 'flex', gap: 6, alignItems: 'center', fontFamily: SEEDEX_FONTS.mono, fontSize: 11, color: t.accent }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: t.accent }} />
            {totalRunning} LIVE
          </div>
        )}
      </div>

      {/* Hero */}
      <div style={{ padding: '8px 24px 20px' }}>
        <div style={{ fontFamily: SEEDEX_FONTS.display, fontSize: 36, lineHeight: 1.1, letterSpacing: -0.8, fontWeight: 400 }}>
          <span style={{ fontStyle: 'italic', color: t.accent }}>{SEEDEX_PROJECTS.length}</span> gardens,{' '}
          <span style={{ fontStyle: 'italic', color: t.accent }}>{totalSessions}</span> sprouts.
        </div>
        <div style={{ marginTop: 12, fontSize: 13, color: t.inkSoft, lineHeight: 1.5, maxWidth: 320 }}>
          {totalAwaiting > 0 ? (
            <>
              <span style={{ color: t.warn, fontWeight: 500 }}>
                {totalAwaiting} session{totalAwaiting !== 1 ? 's' : ''} awaiting you.
              </span> The rest tend themselves.
            </>
          ) : (
            <>Nothing needs you right now. Your twin is tending.</>
          )}
        </div>
      </div>

      {/* Filter chips */}
      <FilterChips t={t} value={filter} onChange={setFilter} counts={counts} />

      {/* Body */}
      {filter === 'all' && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12, padding: '0 16px 28px' }}>
          {SEEDEX_PROJECTS.map(p => (
            <ProjectCard
              key={p.id}
              t={t}
              project={p}
              pinnedIds={pinnedIds}
              onOpen={openSession}
              onOpenProject={openProject}
              onTogglePin={togglePin}
              onArchive={archive}
              swipedId={swipedId}
              setSwipedId={setSwipedId}
            />
          ))}
        </div>
      )}

      {filter === 'active' && (
        activeSessions.length > 0 ? (
          <div style={{ padding: '0 0 28px' }}>
            <FlatSessionList
              t={t} sessions={activeSessions} pinnedIds={pinnedIds}
              onOpen={openSession} onTogglePin={togglePin} onArchive={archive}
              swipedId={swipedId} setSwipedId={setSwipedId}
            />
          </div>
        ) : <EmptyState t={t} filter={filter} />
      )}

      {filter === 'pinned' && (
        pinnedSessions.length > 0 ? (
          <div style={{ padding: '0 0 28px' }}>
            <FlatSessionList
              t={t} sessions={pinnedSessions} pinnedIds={pinnedIds}
              onOpen={openSession} onTogglePin={togglePin} onArchive={archive}
              swipedId={swipedId} setSwipedId={setSwipedId}
            />
          </div>
        ) : <EmptyState t={t} filter={filter} />
      )}

      {/* Footer hint */}
      <div style={{ padding: '4px 24px 32px', fontFamily: SEEDEX_FONTS.mono, fontSize: 9, letterSpacing: 1.2, color: t.inkFaint, textTransform: 'uppercase', textAlign: 'center' }}>
        swipe a session left to pin or archive
      </div>
    </div>
  );
}

Object.assign(window, { SessionsScreen });
