// Savvie · top-level App
// Routes welcome → inbox, manages state, hosts Tweaks

const { useState, useEffect, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "layout": "rows",
  "density": "comfortable",
  "annotations": true,
  "emptyState": false,
  "showWelcome": true
}/*EDITMODE-END*/;

function ApiKeyInput() {
  const [key, setKey] = useState(window.__savvieApiKey || '');
  const [status, setStatus] = useState(key ? 'saved' : 'none');

  const save = () => {
    const trimmed = key.trim();
    window.__savvieApiKey = trimmed;
    try { localStorage.setItem('savvie-api-key', trimmed); } catch(e) {}
    setStatus(trimmed ? 'saved' : 'none');
  };

  const clear = () => {
    setKey('');
    window.__savvieApiKey = '';
    try { localStorage.removeItem('savvie-api-key'); } catch(e) {}
    setStatus('none');
  };

  return React.createElement('div', { style: { padding: '4px 0' } },
    React.createElement('div', {
      style: { display: 'flex', gap: 6, alignItems: 'center' }
    },
      React.createElement('input', {
        type: 'password',
        placeholder: 'sk-ant-api03-…',
        value: key,
        onChange: (e) => { setKey(e.target.value); setStatus('editing'); },
        onBlur: save,
        onKeyDown: (e) => { if (e.key === 'Enter') save(); },
        style: {
          flex: 1, padding: '5px 8px', fontSize: 11,
          fontFamily: 'var(--vz-mono)', border: '1px solid var(--vz-ink-10)',
          borderRadius: 6, background: 'var(--vz-cream)',
        },
      }),
      key && React.createElement('button', {
        onClick: clear,
        style: {
          fontSize: 10, padding: '3px 6px', cursor: 'pointer',
          border: '1px solid var(--vz-ink-10)', borderRadius: 4,
          background: 'transparent', fontFamily: 'var(--vz-mono)',
        },
      }, '×'),
    ),
    React.createElement('div', {
      style: { fontSize: 10, marginTop: 3, fontFamily: 'var(--vz-mono)', color: 'var(--vz-ink-40)' },
    }, status === 'saved' ? '✓ key saved · claude vision active'
       : status === 'editing' ? 'press enter to save'
       : 'paste your anthropic api key for vision')
  );
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  const { ITEMS } = window.SAVVIE_DATA;
  const [items, setItems] = useState([]);
  const [extraCategories, setExtraCategories] = useState([]);

  // Auth state — only trust Supabase sessions, not localStorage placeholders
  const [user, setUser] = useState(null);
  const [authModal, setAuthModal] = useState(null); // null | 'signup' | 'signin'

  // Clear stale placeholder auth on mount
  useEffect(() => {
    try { localStorage.removeItem('savvie-user'); } catch(e) {}
  }, []);

  const handleAuth = (u) => {
    setUser(u);
    setAuthModal(null);
    setToast({ hand: 'welcome.', message: `signed in as ${u.email}.` });
  };

  const handleSignOut = () => {
    setUser(null);
    if (window.__supabase) {
      window.__supabase.auth.signOut().catch(() => {});
    }
    setToast({ hand: 'signed out.', message: 'your saves are still here.' });
  };

  const handleAuthClick = (mode, u) => {
    if (mode === 'authed' && u) {
      handleAuth(u);
    } else {
      setAuthModal(mode);
    }
  };

  // Listen for Supabase auth state changes (handles Google OAuth redirect)
  useEffect(() => {
    if (!window.__supabase) return;
    const { data: { subscription } } = window.__supabase.auth.onAuthStateChange((event, session) => {
      if (session?.user && !user) {
        handleAuth({ email: session.user.email, id: session.user.id });
      }
      if (event === 'SIGNED_OUT') {
        setUser(null);
      }
    });
    // Check for existing session on mount
    window.__supabase.auth.getSession().then(({ data: { session } }) => {
      if (session?.user && !user) {
        handleAuth({ email: session.user.email, id: session.user.id });
      }
    });
    return () => subscription.unsubscribe();
  }, []);

  const initialView = (() => {
    if (t.showWelcome) return 'welcome';
    try { return localStorage.getItem('savvie-seen-welcome') ? 'inbox' : 'welcome'; }
    catch (e) { return 'welcome'; }
  })();
  const [view, setView] = useState(initialView);

  const [selected, setSelected] = useState(null);
  const [saveOpen, setSaveOpen] = useState(false);
  const [toast, setToast] = useState(null);
  const [celebration, setCelebration] = useState(null);
  const [reorgBusy, setReorgBusy] = useState(false);

  // Process incoming shares from PWA share target or URL scheme
  useEffect(() => {
    if (!window.__processIncomingShare) return;
    window.__processIncomingShare().then((shareData) => {
      if (!shareData) return;
      // Skip welcome screen
      enterApp();
      // Build the save content from shared data
      const hint = shareData.url || shareData.text || shareData.title || 'shared save';
      const type = shareData.images?.length > 0 ? 'screenshot' : (shareData.url ? 'link' : 'note');
      const thumb = shareData.images?.[0] || null;
      // Auto-save it
      setToast({ hand: 'incoming.', message: 'processing your share…' });
      (async () => {
        try {
          const inferred = await window.inferSave?.(hint, type, thumb);
          handleSave({
            type,
            title: inferred?.title || hint.slice(0, 60),
            category: inferred?.category || 'home',
            platform: inferred?.platform || type,
            account: inferred?.account || '',
            thumb,
          });
        } catch(e) {
          handleSave({ type, title: hint.slice(0, 60), category: 'home', platform: type, account: '', thumb });
        }
      })();
    });
  }, []);

  const counts = useMemo(() => ({
    total: items.length,
    fresh: items.filter(i => i.decay === 'fresh').length,
    aging: items.filter(i => i.decay === 'aging').length,
    stale: items.filter(i => i.decay === 'stale').length,
  }), [items]);

  // Inbox toolbar fires layout-change events
  useEffect(() => {
    const onLayout = (e) => setTweak('layout', e.detail);
    window.addEventListener('sv-set-layout', onLayout);
    return () => window.removeEventListener('sv-set-layout', onLayout);
  }, []);

  // ⌘K opens save modal
  useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault();
        setSaveOpen(true);
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, []);

  const handleSave = (payload) => {
    const cat = window.SAVVIE_DATA.CATEGORIES[payload.category] || window.SAVVIE_DATA.CATEGORIES.home;
    const actions = window.SAVVIE_DATA.CATEGORY_ACTIONS[payload.category] || [];
    const newItem = {
      id: 'new-' + Date.now() + '-' + Math.random().toString(36).slice(2, 6),
      type: payload.type,
      title: payload.title,
      source: payload.account || (payload.type === 'note' ? 'note to self' : payload.type === 'link' ? 'link' : 'screenshot'),
      platform: payload.platform || payload.type,
      savedDate: '2026-05-13',
      category: payload.category,
      tags: [],
      thumb: payload.thumb || null,
      note: payload.title,
      daysOld: 0,
      decay: 'fresh',
      age: 'today',
      cat,
      actions,
    };
    // Functional updater so back-to-back calls don't clobber each other
    setItems((prev) => [newItem, ...prev]);
    setSaveOpen(false);
    setToast({ hand: 'got it.', message: `filed under ${cat.label}.` });
  };

  // "execute" from list row / digest spotlight opens the detail with the top action pre-suggested
  const handleExecute = (item) => {
    setSelected(item);
  };

  const handleDone = (item) => {
    setItems(items.filter(i => i.id !== item.id));
    setSelected(null);
    const cheers = ['nailed it.', 'one down.', 'shipped.', 'done and dusted.', 'crushed it.'];
    setCelebration({ caption: cheers[Math.floor(Math.random() * cheers.length)] });
  };

  const handleDropToCategory = (itemId, newCategoryId) => {
    const built = window.SAVVIE_DATA.CATEGORIES[newCategoryId];
    const extra = extraCategories.find(c => c.id === newCategoryId);
    const cat = built || extra;
    if (!cat) return;
    const actions = window.SAVVIE_DATA.CATEGORY_ACTIONS[newCategoryId] || [];
    setItems((prev) => prev.map((it) => {
      if (it.id !== itemId) return it;
      if (it.category === newCategoryId) return it;
      return { ...it, category: newCategoryId, cat, actions };
    }));
    setToast({ hand: 'moved.', message: `now in ${cat.label}.` });
  };

  // Drop on the "new category" zone — claude names a category based on the item,
  // we add it to extraCategories, and move the item into it.
  const handleDropToNewCategory = async (itemId) => {
    const item = items.find(i => i.id === itemId);
    if (!item) return;

    setToast({ hand: 'thinking…', message: 'claude is naming a new category.' });

    // Ask Claude to pick a single-word category name based on the item title.
    const existingIds = [
      ...Object.keys(window.SAVVIE_DATA.CATEGORIES),
      ...extraCategories.map(c => c.id),
    ];
    const prompt = `I'm creating a new category in my saved-items app for the item: "${item.title}"

Existing categories I already have (do NOT duplicate any of these): ${existingIds.join(', ')}

Pick a NEW category name that:
- is 1-2 lowercase words, no hyphens
- is distinct from the existing ones above
- captures the theme of "${item.title}"
- pick a single emoji glyph for it (e.g. ⚡ ⌖ ◇ ☰ ✦ ◈ ◐ ⌬ ⌂ ♪ ★ ☁ ❀ ☘ ⌘ ✈ ⌗ ◉)

Respond with ONLY JSON: {"id":"slugified-name","label":"display name","emoji":"X"}`;

    let newCat = null;
    try {
      const text = await window.claude.complete(prompt);
      const m = text.match(/\{[\s\S]*?\}/);
      if (m) {
        const parsed = JSON.parse(m[0]);
        if (parsed.id && parsed.label && parsed.emoji && !existingIds.includes(parsed.id)) {
          newCat = {
            id: parsed.id,
            label: String(parsed.label).toLowerCase().slice(0, 16),
            emoji: parsed.emoji,
            order: 99,
          };
        }
      }
    } catch (e) {}

    if (!newCat) {
      // Fallback — use the first noun of the title
      const slug = item.title.split(/\s+/)[0].toLowerCase().replace(/[^a-z]/g, '') || 'new';
      newCat = { id: `c-${slug}-${Date.now()}`, label: slug, emoji: '✦', order: 99 };
    }

    const actions = []; // user-created categories start with no preset actions
    setExtraCategories(prev => [...prev, newCat]);
    setItems(prev => prev.map(it =>
      it.id === itemId ? { ...it, category: newCat.id, cat: newCat, actions } : it
    ));
    setToast({ hand: 'new.', message: `created "${newCat.label}".` });
  };

  // Re-org: claude reshuffles your inbox. Visual: brief overlay, then a
  // light shuffle of within-category ordering.
  const handleReorg = async () => {
    setReorgBusy(true);
    // Small artificial pause + visual ramble
    await new Promise(r => setTimeout(r, 1500));
    // Reset to original order (with a hint of shuffling within each category)
    const shuffled = [...items].sort(() => Math.random() - 0.5);
    setItems(shuffled);
    setReorgBusy(false);
    setToast({ hand: 're-shuffled.', message: '14 items, re-graded.' });
  };

  const enterApp = () => {
    try { localStorage.setItem('savvie-seen-welcome', '1'); } catch (e) {}
    setTweak('showWelcome', false);
    setView('inbox');
  };

  // Welcome takes over the whole viewport — no sidebar.
  if (view === 'welcome') {
    return (
      <>
        <Welcome
          onEnter={enterApp}
          onSave={(payload) => {
            handleSave(payload);
            setTimeout(() => enterApp(), 600);
          }}
          user={user}
          onAuthClick={handleAuthClick}
          onSignOut={handleSignOut}
        />
        {authModal && (
          <AuthModal
            mode={authModal}
            onClose={() => setAuthModal(null)}
            onAuth={handleAuth}
          />
        )}
        <TweaksPanel title="tweaks">
          <TweakSection label="entry" />
          <TweakButton onClick={enterApp}>enter the app →</TweakButton>
          <TweakToggle label="welcome on launch" value={t.showWelcome} onChange={(v) => setTweak('showWelcome', v)} />
        </TweaksPanel>
      </>
    );
  }

  const showEmpty = t.emptyState || items.length === 0;

  return (
    <div className={`sv-app ${t.annotations ? '' : 'no-annotations'}`}>
      <Sidebar view={view} setView={setView} counts={counts} items={items} extraCategories={extraCategories} user={user} onAuthClick={handleAuthClick} onSignOut={handleSignOut} />

      <main className="sv-main">
        {showEmpty && view === 'inbox' && (
          <EmptyState onOpenSave={() => setSaveOpen(true)} />
        )}

        {!showEmpty && view === 'inbox' && (
          <Inbox
            items={items}
            layout={t.layout}
            density={t.density}
            annotations={t.annotations}
            onOpenItem={setSelected}
            onExecute={handleExecute}
            onArchive={handleDone}
            onOpenSave={() => setSaveOpen(true)}
            onReorg={handleReorg}
            reorgBusy={reorgBusy}
            onDropToCategory={handleDropToCategory}
            onDropToNewCategory={handleDropToNewCategory}
            extraCategories={extraCategories}
          />
        )}

        {view === 'digest' && (
          <Digest
            items={items}
            onOpenItem={setSelected}
            onExecute={handleExecute}
            onArchive={handleDone}
            annotations={t.annotations}
          />
        )}

      </main>

      {saveOpen && <SaveModal onClose={() => setSaveOpen(false)} onSave={handleSave} user={user} onAuthClick={handleAuthClick} />}
      {selected && (
        <ItemDetail
          item={selected}
          onClose={() => setSelected(null)}
          onActioned={handleDone}
          user={user}
          onAuthClick={(mode) => handleAuthClick(mode || 'signup')}
        />
      )}
      {toast && <Toast {...toast} onDone={() => setToast(null)} />}
      {celebration && <Celebration caption={celebration.caption} onDone={() => setCelebration(null)} />}
      {reorgBusy && <ReorgOverlay caption="claude is re-grading every save…" />}
      {authModal && (
        <AuthModal
          mode={authModal}
          onClose={() => setAuthModal(null)}
          onAuth={handleAuth}
        />
      )}

      <TweaksPanel title="tweaks">
        <TweakSection label="view" />
        <TweakRadio
          label="inbox layout"
          value={t.layout}
          options={['rows', 'grid']}
          onChange={(v) => setTweak('layout', v)}
        />
        <TweakRadio
          label="density"
          value={t.density}
          options={['comfortable', 'compact']}
          onChange={(v) => setTweak('density', v)}
        />
        <TweakSection label="personality" />
        <TweakToggle
          label="handwritten annotations"
          value={t.annotations}
          onChange={(v) => setTweak('annotations', v)}
        />
        <TweakSection label="states" />
        <TweakToggle
          label="show empty inbox"
          value={t.emptyState}
          onChange={(v) => setTweak('emptyState', v)}
        />
        <TweakSection label="jump" />
        <TweakButton onClick={() => setView('welcome')}>back to welcome</TweakButton>
        <TweakButton onClick={() => setView('digest')}>weekly digest</TweakButton>
        <TweakButton onClick={() => setSaveOpen(true)}>open save dialog</TweakButton>
        <TweakSection label="seed data" />
        <TweakButton onClick={() => setItems(ITEMS)}>load 14 sample saves</TweakButton>
        <TweakButton onClick={() => setItems([])}>clear all saves</TweakButton>
      </TweaksPanel>
    </div>
  );
}


const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
