// Vanta App — drill-in detail screen + manage-sources screen.

function VBack({ P, onBack, label = 'garden' }) {
  const S = vStyles(P);
  return (
    <button onClick={onBack} style={{
      appearance: 'none', border: 0, cursor: 'pointer', fontFamily: 'inherit',
      display: 'flex', alignItems: 'center', gap: 6, padding: '8px 10px 8px 6px',
      margin: '6px 0 0 12px', borderRadius: 999, background: 'transparent',
      color: P.ink2, minHeight: 36,
    }}>
      <svg width="8" height="13" viewBox="0 0 7 12" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M6 1L1 6l5 5" /></svg>
      <span style={{ ...S.caps, color: P.ink2 }}>{label}</span>
    </button>
  );
}

// Areas the server accepts as an explicit thought pin (mirrors
// VANTA_THOUGHT_AREAS in server.js); anything else auto-classifies.
const V_PIN_AREAS = ['work', 'learning', 'professional', 'hobbies', 'home', 'sleep', 'finance', 'health'];

// A row's title, hyperlinked when it carries an href. Stops propagation so
// following a link never toggles the row it sits in.
function VRowTitle({ d, P, ring, serif, S }) {
  const base = { fontSize: 13.5, color: P.ink, ...(serif ? S.serif : {}) };
  if (!d.href) return <div style={base}>{d.k}</div>;
  return (
    <div style={base}>
      <a href={d.href} target="_blank" rel="noopener noreferrer"
        onClick={e => e.stopPropagation()}
        style={{ color: 'inherit', textDecoration: 'none', borderBottom: `1px dotted ${ring}` }}>
        {d.k}<span style={{ color: ring, marginLeft: 4, fontSize: 10 }}>↗</span>
      </a>
    </div>
  );
}

// One checkable row — visible tick, strikethrough when done, streak chip.
// Habits are squares (they toggle back off); everything else is a circle
// that completes once.
function VTendRow({ d, P, S, ring, rowBg, done, onTick }) {
  const square = (d.act?.type ?? 'habit') === 'habit';
  return (
    <button onClick={onTick} style={{
      appearance: 'none', border: 0, cursor: 'pointer', fontFamily: 'inherit', textAlign: 'left',
      width: '100%', boxSizing: 'border-box', minHeight: 44,
      display: 'grid', gridTemplateColumns: '22px 1fr auto', gap: 11, alignItems: 'center',
      padding: '10px 14px', borderRadius: 14, background: rowBg,
    }}>
      <span style={{
        width: 19, height: 19, borderRadius: square ? 6 : '50%',
        border: `1.2px solid ${done ? ring : P.ink4}`,
        background: done ? ring : 'transparent',
        display: 'grid', placeItems: 'center', transition: 'background .15s',
      }}>
        {done && <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke={P.bg} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M20 6L9 17l-5-5" /></svg>}
      </span>
      <div style={{ minWidth: 0 }}>
        <VRowTitle d={d} P={P} ring={ring} S={S} />
        {d.note && <div style={{ fontSize: 11, color: P.ink4, marginTop: 1 }}>{d.note}</div>}
      </div>
      <span style={{ textAlign: 'right' }}>
        <span style={{ ...S.num, fontSize: 13, fontWeight: 500, color: done ? P.ink3 : P.ink }}>{d.v}</span>
        {(d.goal || d.streak) ? (
          <span style={{ ...S.num, fontSize: 11, color: P.ink4, marginLeft: 6 }}>{d.goal || `${d.streak}d`}</span>
        ) : null}
      </span>
    </button>
  );
}

// Shared body for one area: source chip, connect state, or sectioned detail —
// planted thoughts, checkable to-tend rows, measures with progress — plus an
// inline plant-here composer and the log action. Used by the desktop overlay
// (variant 'page') and mobile expanded cards (variant 'card', translucent-ink
// row fills so rows read against the card's tile color).
function VAreaBody({ areaKey, area, data, P, store, update, variant = 'page' }) {
  const S = vStyles(P);
  const ring = V_RING(P, areaKey);
  const src = V_SOURCES[areaKey] || { kind: 'manual', label: 'logged by you' };
  const isConnect = area.connect && !store.linked[areaKey];
  const touched = vantaAgo(store.lastTouch[areaKey]);
  const inCard = variant === 'card';
  const rowBg = inCard ? P.chip : V_TILE_BG(P, areaKey);
  const isThoughts = areaKey === 'thoughts';

  const [draft, setDraft] = React.useState('');

  // ── Sections ──
  // Planted: your thoughts, sorted into this area (or all of them, here).
  const planted = isThoughts
    ? [...store.thoughts.map(t => ({ k: `“${t.text}”`, v: vantaAgo(t.ts) })), ...area.details].slice(0, 8)
    : (window.VANTA_LIVE?.areaThoughts?.[areaKey] || []).map(t => ({ k: `“${t.text}”`, v: vantaAgo(t.ts) }));

  // To tend: anything actionable. Live rows carry an `act`; habit rows and
  // home chores stay checkable on seed data too (local + store only).
  const isTendable = (d) => !isThoughts && (!!d.act || areaKey === 'habits' || (areaKey === 'home' && typeof d.pct === 'number'));
  const tend = isThoughts ? [] : area.details.filter(isTendable);
  const measures = isThoughts ? [] : area.details.filter(d => !isTendable(d));

  // Store overrides seed when it has spoken (matches the habits sheet).
  const rowDone = (d) => {
    if (areaKey === 'habits' && store.habits[d.k] !== undefined) return !!store.habits[d.k];
    return d.done === true || d.pct === 1;
  };

  const stamp = () => update(s => ({ lastTouch: { ...s.lastTouch, [areaKey]: Date.now() } }));

  const tick = (d) => {
    if (areaKey === 'habits') {
      // Habits toggle both ways; sync the server when the row has a real key.
      const next = !rowDone(d);
      const key = d.act?.key || d.hk;
      if (key) vantaPost('/vanta/habit', { habit: key, completed: next });
      d.done = next; d.v = next ? '✓' : '·';
      area.headline = `${area.details.filter(r => r.done).length} of ${area.details.length}`;
      update(s => ({ habits: { ...s.habits, [d.k]: next }, lastTouch: { ...s.lastTouch, [areaKey]: Date.now() } }));
      return;
    }
    if (d.act) { if (vantaTapAct(d, data)) stamp(); return; }
    if (areaKey === 'home' && d.pct !== 1) {
      // Seed chore — no server row to hit; tend it locally.
      d.v = 'done'; d.pct = 1;
      const due = area.details.filter(r => r.pct !== 1);
      area.headline = due.length ? `${due.length} to do` : 'all tended';
      area.sub = due.length ? due.slice(0, 3).map(r => r.k.toLowerCase()).join(' · ') : 'nothing due today';
      update(s => ({ chores: { ...s.chores, [d.k]: true }, lastTouch: { ...s.lastTouch, [areaKey]: Date.now() } }));
    }
  };

  // Learning gets a reading logger when a live book is present.
  const book = areaKey === 'learning' ? (window.VANTA_LIVE?.book || null) : null;
  const [pageDraft, setPageDraft] = React.useState('');
  const logPages = () => {
    const page = parseInt(pageDraft, 10);
    if (!book || !Number.isInteger(page) || page < 0) return;
    vantaPost('/vanta/book/progress', { id: book.id, page });
    // Roll the visible row + headline forward optimistically.
    book.currentPage = page;
    if (book.totalPages) book.pct = Math.min(1, page / book.totalPages);
    const row = area.details.find(r => r.k === book.title);
    if (row) {
      row.v = book.totalPages ? `p. ${page} / ${book.totalPages}` : `p. ${page}`;
      row.pct = book.pct;
    }
    area.headline = book.pct != null ? `${Math.round(book.pct * 100)}% through` : `p. ${page}`;
    if (book.totalPages && page >= book.totalPages) {
      area.headline = 'finished ✓';
      area.sub = book.title;
    }
    setPageDraft('');
    stamp();
  };

  const plantHere = () => {
    const t = draft.trim();
    if (!t) return;
    vantaPost('/vanta/thought', { text: t, ...(V_PIN_AREAS.includes(areaKey) ? { area: areaKey } : {}) });
    if (!isThoughts) {
      window.VANTA_LIVE = window.VANTA_LIVE || {};
      const at = window.VANTA_LIVE.areaThoughts = window.VANTA_LIVE.areaThoughts || {};
      at[areaKey] = [{ text: t, ts: Date.now() }, ...(at[areaKey] || [])].slice(0, 3);
    }
    update(s => ({
      thoughts: [{ text: t, ts: Date.now() }, ...s.thoughts].slice(0, 50),
      lastTouch: { ...s.lastTouch, [areaKey]: Date.now() },
    }));
    setDraft('');
  };

  const secHead = (label) => (
    <div style={{ ...S.caps, color: ring, margin: '14px 2px 6px' }}>{label}</div>
  );

  const staticRow = (d, i, serif) => (
    <div key={i} style={{
      display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'baseline',
      padding: '11px 14px', borderRadius: 14, background: rowBg,
    }}>
      <div style={{ minWidth: 0 }}>
        <VRowTitle d={d} P={P} ring={ring} serif={serif} S={S} />
        {d.note && <div style={{ fontSize: 11, color: P.ink4, marginTop: 1 }}>{d.note}</div>}
        {!serif && typeof d.pct === 'number' && (
          <div style={{ marginTop: 7, maxWidth: 180 }}>
            <ProgBar pct={d.pct} h={2} color={ring} track={P.rule} radius={999} />
          </div>
        )}
      </div>
      <div style={{ textAlign: 'right' }}>
        <span style={{ ...S.num, fontSize: 13.5, fontWeight: 500, color: P.ink }}>{d.v}</span>
        {(d.goal || d.streak) ? (
          <span style={{ ...S.num, fontSize: 11, color: P.ink4, marginLeft: 6 }}>
            {d.goal || `${d.streak}d`}
          </span>
        ) : null}
      </div>
    </div>
  );

  return (
    <React.Fragment>
      {/* Source + status — only shown in depth, per your call */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 8, marginTop: inCard ? 4 : 14,
        padding: '8px 12px', borderRadius: 12, background: P.chip,
      }}>
        <span style={{
          width: 7, height: 7, borderRadius: '50%',
          background: isConnect ? P.ink4 : P.accent,
        }} />
        <span style={{ ...S.caps, color: P.ink3 }}>
          {isConnect ? src.label : `${src.label}${touched ? ` · touched ${touched}` : ''}`}
        </span>
      </div>

      {isConnect ? (
        <div style={{ marginTop: inCard ? 14 : 20, background: inCard ? P.chip : V_TILE_BG(P, areaKey), borderRadius: 22, padding: '20px 20px' }}>
          <p style={{ fontSize: 13.5, color: P.ink2, margin: '0 0 16px', lineHeight: 1.5 }}>{area.connectCopy}</p>
          <button onClick={() => update(s => ({ linked: { ...s.linked, [areaKey]: true }, lastTouch: { ...s.lastTouch, [areaKey]: Date.now() } }))} style={{
            appearance: 'none', border: 0, cursor: 'pointer', fontFamily: 'inherit',
            padding: '11px 20px', borderRadius: 999, background: P.ink, color: P.bg,
            fontSize: 13, fontWeight: 500, minHeight: 44,
          }}>Link accounts →</button>
          <span style={{ ...S.caps, color: P.ink4, marginLeft: 12 }}>prototype · nothing real is touched</span>
        </div>
      ) : (
        <React.Fragment>
          {!inCard && (
            <div style={{ marginTop: 20 }}>
              <Spark data={area.trend} w={310} h={44} stroke={ring} fill={ring + '22'} strokeWidth={1.6} showDots />
              <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 4 }}>
                <span style={{ ...S.caps, color: P.ink4 }}>{store.horizon === 'today' ? 'last 7 days' : `by ${store.horizon}`}</span>
              </div>
            </div>
          )}

          {planted.length > 0 && (
            <React.Fragment>
              {secHead(isThoughts ? 'planted' : 'planted here')}
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {planted.map((d, i) => staticRow(d, i, true))}
              </div>
            </React.Fragment>
          )}

          {tend.length > 0 && (
            <React.Fragment>
              {secHead('to tend')}
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {tend.map((d, i) => (
                  <VTendRow key={i} d={d} P={P} S={S} ring={ring} rowBg={rowBg}
                    done={rowDone(d)} onTick={() => tick(d)} />
                ))}
              </div>
            </React.Fragment>
          )}

          {measures.length > 0 && (
            <React.Fragment>
              {secHead('measures')}
              <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                {measures.map((d, i) => staticRow(d, i, false))}
              </div>
            </React.Fragment>
          )}

          {/* Reading logger — "stopped at page N" rolls the book forward. */}
          {book && (
            <div style={{
              display: 'grid', gridTemplateColumns: '1fr auto', gap: 8, alignItems: 'center',
              marginTop: 14, padding: '4px 4px 4px 14px', borderRadius: 999,
              background: rowBg, boxSizing: 'border-box', minHeight: 44,
            }}>
              <input
                value={pageDraft}
                onChange={e => setPageDraft(e.target.value.replace(/[^\d]/g, ''))}
                onKeyDown={e => { if (e.key === 'Enter') logPages(); }}
                inputMode="numeric"
                placeholder={`stopped at page… (now p. ${book.currentPage})`}
                style={{
                  appearance: 'none', border: 0, outline: 'none', background: 'transparent',
                  color: P.ink, fontFamily: 'inherit', fontSize: 13,
                  width: '100%', padding: 0, minWidth: 0,
                }}
              />
              <button onClick={logPages} aria-label="log reading" disabled={!pageDraft} style={{
                appearance: 'none', border: 0, cursor: pageDraft ? 'pointer' : 'default',
                padding: '0 14px', height: 34, borderRadius: 999,
                background: pageDraft ? ring : 'transparent',
                color: pageDraft ? P.bg : P.ink4,
                boxShadow: pageDraft ? 'none' : `inset 0 0 0 1px ${P.rule}`,
                fontFamily: 'inherit', fontSize: 12, fontWeight: 600,
                display: 'grid', placeItems: 'center', transition: 'background .15s',
              }}>log</button>
            </div>
          )}

          {/* Plant a thought straight into this area — pinned server-side. */}
          <div style={{
            display: 'grid', gridTemplateColumns: '1fr auto', gap: 8, alignItems: 'center',
            marginTop: book ? 8 : 14, padding: '4px 4px 4px 14px', borderRadius: 999,
            background: rowBg, boxSizing: 'border-box', minHeight: 44,
          }}>
            <input
              value={draft}
              onChange={e => setDraft(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') plantHere(); }}
              placeholder={isThoughts ? 'plant a thought…' : `plant a thought in ${area.label.toLowerCase()}…`}
              style={{
                appearance: 'none', border: 0, outline: 'none', background: 'transparent',
                color: P.ink, fontFamily: '"Instrument Serif", serif', fontStyle: 'italic', fontSize: 14.5,
                width: '100%', padding: 0, minWidth: 0,
              }}
            />
            <button onClick={plantHere} aria-label="plant here" disabled={!draft.trim()} style={{
              appearance: 'none', border: 0, cursor: draft.trim() ? 'pointer' : 'default',
              width: 34, height: 34, borderRadius: '50%',
              background: draft.trim() ? P.ink : 'transparent',
              color: draft.trim() ? P.bg : P.ink4,
              boxShadow: draft.trim() ? 'none' : `inset 0 0 0 1px ${P.rule}`,
              display: 'grid', placeItems: 'center', transition: 'background .15s',
            }}>
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M12 5v14M5 12h14" /></svg>
            </button>
          </div>

          {!isThoughts && (
            <button onClick={stamp} style={{
              appearance: 'none', border: 0, cursor: 'pointer', fontFamily: 'inherit',
              marginTop: 12, padding: '11px 20px', borderRadius: 999,
              background: 'transparent', boxShadow: `inset 0 0 0 1px ${P.ink3}`,
              color: P.ink2, fontSize: 13, fontWeight: 500, minHeight: 44,
            }}>log an interaction · now</button>
          )}
        </React.Fragment>
      )}
    </React.Fragment>
  );
}

// Detail view for one area — legacy full-screen drill-in (cards now expand
// in place on the dashboard; the sources screen still navigates here-style).
function VAreaDetail({ areaKey, data, P, store, update, onBack }) {
  const S = vStyles(P);
  const area = data.areas[areaKey];
  const ring = V_RING(P, areaKey);
  const isConnect = area.connect && !store.linked[areaKey];

  return (
    <div style={{ display: 'flex', flexDirection: 'column', minHeight: '100%' }}>
      <VBack P={P} onBack={onBack} />
      <div style={{ padding: '10px 20px 24px', flex: 1 }}>
        <div style={{ ...S.caps, color: ring, marginBottom: 6 }}>{area.label.toLowerCase()}</div>
        <h1 style={{ ...S.serif, fontSize: 34, margin: 0, color: P.ink, lineHeight: 1.05 }}>
          {isConnect ? 'Not linked' : area.headline}
        </h1>
        <div style={{ fontSize: 13, color: P.ink3, marginTop: 4 }}>{area.sub}</div>
        <VAreaBody areaKey={areaKey} area={area} data={data} P={P} store={store} update={update} variant="page" />
      </div>
    </div>
  );
}

// Manage data sources — connect states live here.
function VSourcesScreen({ data, P, store, update, onBack }) {
  const S = vStyles(P);
  // Real connections from the server when available; prototype rows otherwise.
  const liveSources = window.VANTA_LIVE?.sources;
  const sources = liveSources || [
    { key: 'health',  name: 'Apple Health', desc: 'steps · workouts · state of mind', linked: store.linked.health },
    { key: 'sleep',   name: 'Sleep app',    desc: 'pushed nightly · manual override', linked: store.linked.sleep },
    { key: 'finance', name: 'Accounts',     desc: 'plaid · read-only',                linked: store.linked.finance },
    { key: 'vault',   name: 'Obsidian vault', desc: 'notes → thoughts · tags → areas', linked: store.linked.vault },
  ];
  return (
    <div style={{ minHeight: '100%' }}>
      <VBack P={P} onBack={onBack} />
      <div style={{ padding: '10px 20px 24px' }}>
        <div style={{ ...S.caps, color: P.accent, marginBottom: 6 }}>manage sources</div>
        <h1 style={{ ...S.serif, fontSize: 30, margin: '0 0 6px', color: P.ink }}>What feeds the garden</h1>
        <p style={{ fontSize: 12.5, color: P.ink3, margin: '0 0 18px', maxWidth: 300 }}>
          {liveSources
            ? 'These are the live feeds tending the garden right now. Everything else you plant by hand.'
            : 'Everything else you plant by hand. Prototype — connections are pretend, but the states are real.'}
        </p>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {sources.map((s) => (
            <div key={s.key} style={{
              display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'center',
              padding: '14px 16px', borderRadius: 18, background: P.tile,
            }}>
              <div>
                <div style={{ fontSize: 14.5, fontWeight: 500, color: P.ink }}>{s.name}</div>
                <div style={{ fontSize: 11.5, color: P.ink3, marginTop: 1 }}>{s.desc}</div>
              </div>
              <button onClick={() => { if (!liveSources) update(st => ({ linked: { ...st.linked, [s.key]: !s.linked } })); }} style={{
                appearance: 'none', border: 0, cursor: liveSources ? 'default' : 'pointer', fontFamily: 'inherit',
                padding: '9px 16px', borderRadius: 999, minHeight: 36,
                background: s.linked ? 'transparent' : P.ink,
                boxShadow: s.linked ? `inset 0 0 0 1px ${P.ink3}` : 'none',
                color: s.linked ? P.ink2 : P.bg,
                fontSize: 12, fontWeight: 500,
              }}>{liveSources ? (s.linked ? 'linked ✓' : 'quiet ·') : (s.linked ? 'linked ✓' : 'link →')}</button>
            </div>
          ))}
        </div>
        <p style={{ fontSize: 11.5, color: P.ink4, marginTop: 18, lineHeight: 1.5 }}>
          {liveSources
            ? 'Next to grow: Health via HealthKit, accounts via Plaid, and the vault through a small Obsidian plugin that pushes note events into Vanta.'
            : "When this goes live: Health via HealthKit, sleep via your app's export webhook, accounts via Plaid, and the vault through a small Obsidian plugin that pushes note events into Vanta."}
        </p>
      </div>
    </div>
  );
}

Object.assign(window, { VAreaDetail, VAreaBody, VSourcesScreen, VBack });
