// ─────────────────────────────────────────────────────────────
// FolkApp — orchestrator.
//
// Owns:
//   • view preference (ladder | rings), persisted to localStorage
//   • search query (transient)
//   • selected user → primary ConnectSheet
//   • activeSecondary: null | 'add-group' | 'invite-forest'
//   • proposals map for pending propose-closer
//   • adds: a log of side-effects so the UI can show "added to" toasts
// ─────────────────────────────────────────────────────────────

const LS_VIEW   = 'folk.view';
const LS_PROPOS = 'folk.proposals';

function FolkApp() {
  const [view, setView] = React.useState(() => {
    try { return localStorage.getItem(LS_VIEW) || 'ladder'; }
    catch { return 'ladder'; }
  });

  const [proposals, setProposals] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem(LS_PROPOS) || '{}'); }
    catch { return {}; }
  });

  const [searchQuery, setSearchQuery] = React.useState('');
  const [selectedHandle, setSelectedHandle] = React.useState(null);
  const [activeSecondary, setActiveSecondary] = React.useState(null);
  // 'trade' is a top-level secondary that runs without a primary ConnectSheet
  // below — when search → "Trade handles", we don't want a backdrop user.
  const [tradeOpen, setTradeOpen] = React.useState(false);

  const folk = INITIAL_FOLK;
  const isSearching = searchQuery.trim().length > 0;

  // Persist view + proposals
  React.useEffect(() => {
    try { localStorage.setItem(LS_VIEW, view); } catch {}
  }, [view]);
  React.useEffect(() => {
    try { localStorage.setItem(LS_PROPOS, JSON.stringify(proposals)); } catch {}
  }, [proposals]);

  const selectedUser = selectedHandle
    ? folk.find(f => f.handle === selectedHandle)
      || FOREST_FOLK.find(f => f.handle === selectedHandle)
      || coerceCanopyFolk(ACROSS_CANOPY.find(f => f.handle === selectedHandle))
    : null;

  // — handlers
  function tapUser(handle) { setSelectedHandle(handle); }
  function closeSheet()    { setSelectedHandle(null); setActiveSecondary(null); }
  function proposeUser(handle, targetStage) {
    setProposals(p => ({ ...p, [handle]: targetStage }));
  }

  function tapForestFolk(forestFolkUser) {
    // Forest-folk get a minimal preview — set them as the selected user.
    // We coerce them into a folk-shape with stage 'stranger'.
    const coerced = {
      ...forestFolkUser,
      stage: 'stranger',
      mutuals: forestFolkUser.mutualForestsCount || 1,
      joined: '—', online: false, lastTouch: 'seen recently',
      recentBlurb: '',
    };
    // Stuff into the folk array transiently by setting the selectedHandle to it
    // (selectedUser lookup falls back to FOREST_FOLK so this works).
    setSelectedHandle(forestFolkUser.handle);
  }

  function tapCanopyFolk(canopyUser) {
    setSelectedHandle(canopyUser.handle);
  }

  return (
    <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0,
                  background: '#0B1306', position: 'relative', overflow: 'hidden' }}>
      <FolkHeader
        view={view}
        onSetView={setView}
        searchQuery={searchQuery}
        onSearchChange={setSearchQuery}
        onSearchClear={() => setSearchQuery('')}/>

      {/* Pulse strip hides during search — gives results room and signals mode change */}
      {!isSearching && <PulseStrip folk={folk} onTap={tapUser}/>}

      {/* Body — three states: search results, ladder, rings */}
      <div style={{ flex: 1, overflowY: 'auto', position: 'relative', minHeight: 0 }}>
        {isSearching ? (
          <SearchResults
            query={searchQuery}
            folk={folk}
            proposals={proposals}
            onTapUser={tapUser}
            onTapForestFolk={tapForestFolk}
            onTapCanopyFolk={tapCanopyFolk}
            onTapTradeHandles={() => setTradeOpen(true)}/>
        ) : (
          <>
            <div style={{
              opacity: view === 'ladder' ? 1 : 0,
              pointerEvents: view === 'ladder' ? 'auto' : 'none',
              transition: 'opacity 200ms var(--ease-organic)',
            }}>
              <Ladder folk={folk} proposals={proposals} onTapUser={tapUser}/>
            </div>
            <div style={{
              position: 'absolute', inset: 0,
              opacity: view === 'rings' ? 1 : 0,
              pointerEvents: view === 'rings' ? 'auto' : 'none',
              transition: 'opacity 200ms var(--ease-organic)',
            }}>
              <Rings folk={folk} proposals={proposals} onTapUser={tapUser}/>
            </div>
          </>
        )}
      </div>

      <BottomNavFolk active="folk" onChange={() => {}}/>

      {/* Primary sheet */}
      <ConnectSheet
        user={selectedUser}
        isOpen={!!selectedUser && !activeSecondary}
        onClose={closeSheet}
        onPropose={proposeUser}
        alreadyProposed={selectedUser ? proposals[selectedUser.handle] : null}
        onOpenAddToGroup={() => setActiveSecondary('add-group')}
        onOpenInvite={() => setActiveSecondary('invite-forest')}/>

      {/* Secondary sheets — only one active at a time, mounted on top */}
      <AddToGroupSheet
        user={selectedUser}
        isOpen={activeSecondary === 'add-group'}
        onBack={() => setActiveSecondary(null)}
        onClose={closeSheet}
        onConfirm={() => {}}/>

      <InviteToForestSheet
        user={selectedUser}
        isOpen={activeSecondary === 'invite-forest'}
        onBack={() => setActiveSecondary(null)}
        onClose={closeSheet}
        onConfirm={() => {}}/>

      {/* Trade Handles — top-level, doesn't require a selected user. */}
      <TradeHandlesSheet
        isOpen={tradeOpen}
        onBack={() => setTradeOpen(false)}
        onClose={() => { setTradeOpen(false); setSearchQuery(''); }}
        onConfirm={() => {}}/>
    </div>
  );
}


// Coerce a canopy-folk entry into the full user shape ConnectSheet expects.
function coerceCanopyFolk(u) {
  if (!u) return null;
  return {
    ...u,
    stage: 'stranger',
    mutuals: 0,
    online: false,
    lastTouch: '—',
    recentBlurb: '',
  };
}


// ─── Mount ─────────────────────────────────────────────────────

function Root() {
  return (
    <div style={{
      background: 'linear-gradient(180deg, #1A2812 0%, #0B1306 100%)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: '12px 20px', boxSizing: 'border-box',
    }}>
      <Phone>
        <FolkApp/>
      </Phone>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Root/>);
