// ── App shell: state, filtering, navigation, bottom nav, tweaks ──
const { IOSDevice, Icon, Explore, Saved, MapView, Detail, Reels, FiltersSheet, LISTINGS, ME, CATEGORIES } = window;
const { Profile, Settings, ManageListings, MyRequests, PostSheet, RequestForm, ListingForm } = window;
const { AISearchScreen, GuidedFilterScreen } = window;
const { useTweaks, TweaksPanel, TweakSection, TweakColor, TweakRadio, TweakToggle } = window;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#2f7d62",
  "theme": "Warm",
  "radius": "Soft",
  "cardStyle": "Classic",
  "typeface": "Hanken Grotesk",
  "photoLabels": true
}/*EDITMODE-END*/;

const THEMES = {
  Warm: { bg: 'oklch(0.985 0.003 95)', surface: '#ffffff', ink: 'oklch(0.24 0.008 80)',
    muted: 'oklch(0.56 0.012 80)', line: 'oklch(0.92 0.004 95)', soft: 'oklch(0.94 0.004 95)' },
  Cool: { bg: 'oklch(0.985 0.004 240)', surface: '#ffffff', ink: 'oklch(0.24 0.012 250)',
    muted: 'oklch(0.56 0.014 250)', line: 'oklch(0.92 0.006 240)', soft: 'oklch(0.94 0.006 240)' },
  Paper: { bg: 'oklch(0.971 0.013 85)', surface: 'oklch(0.995 0.006 85)', ink: 'oklch(0.26 0.022 60)',
    muted: 'oklch(0.52 0.022 65)', line: 'oklch(0.91 0.016 85)', soft: 'oklch(0.945 0.016 85)' },
};
const RADII = { Sharp: 6, Soft: 18, Round: 28 };

const DEFAULT_FILTERS = { price: null, beds: 0, baths: 0, types: [], videoOnly: false };

function BottomNav({ tab, setTab, onReels, onPost, dark = false }) {
  const left = [['explore', 'rows', 'Explore'], ['map', 'map', 'Map']];
  const right = [['reels', 'play', 'Reels'], ['saved', 'heart', 'Saved']];
  const idleColor = dark ? 'rgba(255,255,255,0.7)' : 'var(--muted)';
  const TabBtn = ([k, ic, label]) => {
    const active = tab === k;
    const isReel = k === 'reels';
    return (
      <button key={k} data-tour={`re-nav-${k}`} onClick={() => isReel ? onReels() : setTab(k)} style={{ position: 'relative', zIndex: 1,
        background: active ? (dark ? 'rgba(255,255,255,0.16)' : 'rgba(255,255,255,0.7)') : 'transparent',
        border: 'none', cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3,
        width: 62, padding: '8px 0 6px', borderRadius: 20, transition: 'background .2s ease',
        boxShadow: active ? '0 1px 4px rgba(0,0,0,0.06)' : 'none' }}>
        <Icon name={ic} size={23} s={active ? 'var(--accent)' : idleColor}
          fill={active && (ic === 'heart' || ic === 'play') ? 'var(--accent)' : 'none'} sw={1.9} />
        <span style={{ fontFamily: 'var(--sans)', fontSize: 10, fontWeight: active ? 700 : 500, letterSpacing: -0.1,
          color: active ? 'var(--accent)' : idleColor }}>{label}</span>
      </button>
    );
  };
  return (
    <div style={{ position: 'absolute', bottom: 26, left: '50%', transform: 'translateX(-50%)', zIndex: 20 }}>
      <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 2, padding: 6, borderRadius: 32,
        overflow: 'hidden', boxShadow: '0 10px 34px rgba(0,0,0,0.18), 0 3px 10px rgba(0,0,0,0.07)' }}>
        <div style={{ position: 'absolute', inset: 0, borderRadius: 32,
          backdropFilter: 'blur(20px) saturate(180%)', WebkitBackdropFilter: 'blur(20px) saturate(180%)',
          background: dark ? 'rgba(40,40,42,0.55)' : 'rgba(255,255,255,0.62)' }} />
        <div style={{ position: 'absolute', inset: 0, borderRadius: 32,
          boxShadow: dark
            ? 'inset 1.5px 1.5px 1px rgba(255,255,255,0.18), inset -1px -1px 1px rgba(255,255,255,0.08)'
            : 'inset 1.5px 1.5px 1px rgba(255,255,255,0.75), inset -1px -1px 1px rgba(255,255,255,0.45)',
          border: dark ? '0.5px solid rgba(255,255,255,0.16)' : '0.5px solid rgba(0,0,0,0.05)', pointerEvents: 'none' }} />
        {left.map(TabBtn)}
        {/* center Post button */}
        <button onClick={onPost} style={{ position: 'relative', zIndex: 1, width: 50, height: 50, borderRadius: 999,
          margin: '0 4px', border: 'none', cursor: 'pointer', background: 'var(--accent)', display: 'flex',
          alignItems: 'center', justifyContent: 'center', boxShadow: '0 4px 12px color-mix(in srgb, var(--accent) 45%, transparent)' }}>
          <Icon name="plus" size={26} s="#fff" sw={2.4} />
        </button>
        {right.map(TabBtn)}
      </div>
    </div>
  );
}

function applyFilters(list, deal, f, sort) {
  let out = list.filter(l => {
    if (deal !== 'all' && l.deal !== deal) return false;
    if (f.price && deal !== 'all') {
      if (l.price < f.price.min || l.price > f.price.max) return false;
    }
    if (l.beds < f.beds) return false;
    if (l.baths < f.baths) return false;
    if (f.types.length && !f.types.includes(l.type)) return false;
    if (f.videoOnly && !l.video) return false;
    return true;
  });
  out = [...out].sort((a, b) => sort === 'price' ? a.price - b.price : a.days - b.days);
  return out;
}

function countActive(deal, f) {
  let n = 0;
  if (f.price) n++;
  if (f.beds) n++;
  if (f.baths) n++;
  if (f.types.length) n++;
  if (f.videoOnly) n++;
  return n;
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [tab, setTab] = React.useState('explore');
  const [deal, setDeal] = React.useState('all');
  const [filters, setFilters] = React.useState(DEFAULT_FILTERS);
  const [layout, setLayout] = React.useState('list');
  const [sort, setSort] = React.useState('new');
  const [saved, setSaved] = React.useState(() => new Set(['l5']));
  const [detailId, setDetailId] = React.useState(null);
  const [reel, setReel] = React.useState({ open: false, id: null });
  const [mapSel, setMapSel] = React.useState(null);

  // post + screen stack
  const [showPost, setShowPost] = React.useState(false);
  const [aiOpen, setAiOpen] = React.useState(false);
  const [guidedOpen, setGuidedOpen] = React.useState(false);
  const [stack, setStack] = React.useState([]);
  const [userListings, setUserListings] = React.useState([]);
  const [userRequests, setUserRequests] = React.useState([]);
  const push = (s) => setStack(p => [...p, s]);
  const pop = () => setStack(p => p.slice(0, -1));
  const top = stack[stack.length - 1];

  const navigate = (s) => {
    if (s === 'saved') { setStack([]); setTab('saved'); return; }
    push(s);
  };
  const createRequest = (d) => {
    const cat = CATEGORIES.find(c => c.id === d.cat) || {};
    const budget = d.bMin || d.bMax
      ? `$${(+d.bMin || 0).toLocaleString()} – $${(+d.bMax || 0).toLocaleString()}${d.deal === 'rent' ? ' / mo' : ''}`
      : 'Open';
    setUserRequests(p => [{ id: 'ur' + Date.now(), deal: d.deal, cat: d.cat, area: d.area || 'Anywhere',
      budget, beds: cat.residential ? '2+' : null, baths: cat.residential ? '1+' : null, when: 'Flexible',
      note: '', status: 'Active', matches: 0, created: 'Just now' }, ...p]);
  };
  const createListing = (d) => {
    const typeMap = { home: 'House', apartment: 'Apartment', townhouse: 'Townhouse', shop: 'Shop',
      building: 'Commercial', office: 'Office', farm: 'Farm', land: 'Land' };
    setUserListings(p => [{ id: 'ul' + Date.now(), deal: d.deal, price: d.price || 0, beds: d.beds || 0,
      baths: d.baths || 0, sqft: d.sqft || 0, type: typeMap[d.cat] || 'House', address: d.addr,
      hood: d.hood || 'San Francisco', city: 'San Francisco', hue: 40 + Math.floor(Math.random() * 280),
      photos: 6, video: !!d.reel, badge: 'New', open: null, built: 2020, lot: null, hoa: null, days: 0,
      agent: { name: ME.name, firm: ME.firm, hue: ME.hue }, blurb: '', features: d.feats || [], reelCap: '',
      status: 'Pending' }, ...p]);
  };
  const agentListings = React.useMemo(
    () => [...userListings, ...LISTINGS.filter(l => l.agent.name === ME.name)], [userListings]);
  const allRequests = [...userRequests, ...window.MY_REQUESTS];

  // filter sheet
  const [sheetOpen, setSheetOpen] = React.useState(false);
  const [draft, setDraft] = React.useState({ deal, ...filters });

  const fontMap = {
    'Hanken Grotesk': "'Hanken Grotesk', system-ui, sans-serif",
    'Schibsted Grotesk': "'Schibsted Grotesk', system-ui, sans-serif",
    'System': "-apple-system, system-ui, sans-serif",
  };
  React.useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty('--accent', t.accent);
    r.style.setProperty('--sans', fontMap[t.typeface] || fontMap['Hanken Grotesk']);
    const th = THEMES[t.theme] || THEMES.Warm;
    r.style.setProperty('--bg', th.bg);
    r.style.setProperty('--surface', th.surface);
    r.style.setProperty('--ink', th.ink);
    r.style.setProperty('--muted', th.muted);
    r.style.setProperty('--line', th.line);
    r.style.setProperty('--r-img', (RADII[t.radius] ?? 18) + 'px');
    document.body.dataset.labels = t.photoLabels ? 'on' : 'off';
  }, [t.accent, t.typeface, t.photoLabels, t.theme, t.radius]);

  const filtered = React.useMemo(() => applyFilters(LISTINGS, deal, filters, sort), [deal, filters, sort]);
  const activeFilterCount = countActive(deal, filters);
  const reels = React.useMemo(() => LISTINGS.filter(l => l.video), []);

  const toggleSave = (id) => setSaved(s => {
    const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n;
  });
  const openDetail = (id) => { setReel({ open: false, id: null }); setDetailId(id); };
  const openReel = (id) => { setDetailId(null); setReel({ open: true, id }); };
  const openReelsTab = () => setReel({ open: true, id: reels[0] && reels[0].id });

  const openSheet = () => { setDraft({ deal, ...filters }); setSheetOpen(true); };
  const draftResults = React.useMemo(() => {
    const f = { price: draft.price, beds: draft.beds, baths: draft.baths, types: draft.types, videoOnly: draft.videoOnly };
    return applyFilters(LISTINGS, draft.deal, f, sort).length;
  }, [draft, sort]);
  const applyDraft = () => {
    setDeal(draft.deal);
    let price = draft.price;
    // normalize: if full-range, treat as no filter
    const bounds = draft.deal === 'rent' ? [1000, 6000] : [400000, 2500000];
    if (price && price.min <= bounds[0] && price.max >= bounds[1]) price = null;
    setFilters({ price, beds: draft.beds, baths: draft.baths, types: draft.types, videoOnly: draft.videoOnly });
    setSheetOpen(false);
  };
  const resetDraft = () => setDraft({ deal: draft.deal, ...DEFAULT_FILTERS });

  // draft needs a default price object when slider used
  const draftForSheet = { ...draft, priceMin: draft.price ? draft.price.min : (draft.deal === 'rent' ? 1000 : 400000),
    priceMax: draft.price ? draft.price.max : (draft.deal === 'rent' ? 6000 : 2500000) };
  const setDraftSheet = (next) => {
    // capture price edits
    if (next.priceMin !== undefined || next.priceMax !== undefined) {
      setDraft({ ...next, price: { min: next.priceMin, max: next.priceMax } });
    } else {
      setDraft(next);
    }
  };

  const detail = detailId ? [...userListings, ...LISTINGS].find(l => l.id === detailId) : null;
  const fullScreen = reel.open || detailId || stack.length > 0 || aiOpen || guidedOpen; // hide bottom nav

  return (
    <IOSDevice>
      <div style={{ position: 'relative', width: '100%', height: '100%', overflow: 'hidden', background: 'var(--bg)' }}>
        {/* base tab content */}
        {tab === 'map' ? (
          <div style={{ position: 'absolute', inset: 0 }}>
            <MapView listings={filtered} saved={saved} selected={mapSel} setSelected={setMapSel}
              onOpen={openDetail} onToggleSave={toggleSave} onOpenReel={openReel}
              onOpenFilters={() => setGuidedOpen(true)} deal={deal} />
          </div>
        ) : (
          <div className="no-scrollbar" style={{ position: 'absolute', inset: 0, overflowY: 'auto', paddingTop: 50 }}>
            {tab === 'explore' && (
              <Explore listings={filtered} deal={deal} setDeal={setDeal} saved={saved}
                layout={layout} setLayout={setLayout} sort={sort} setSort={setSort}
                activeFilterCount={activeFilterCount} onOpenSearch={() => setAiOpen(true)} onOpenFilters={() => setGuidedOpen(true)}
                onOpen={openDetail} onToggleSave={toggleSave} onOpenReel={openReel}
                onOpenProfile={() => push('profile')} cardStyle={t.cardStyle} />
            )}
            {tab === 'saved' && (
              <Saved listings={LISTINGS} saved={saved} onOpen={openDetail} onToggleSave={toggleSave}
                onOpenReel={openReel} goExplore={() => setTab('explore')} />
            )}
          </div>
        )}

        {/* bottom nav */}
        {!fullScreen && <BottomNav tab={tab} setTab={setTab} onReels={openReelsTab} onPost={() => setShowPost(true)} />}

        {/* stack screens (profile / settings / manage / requests / forms) */}
        {top === 'profile' && (
          <Profile onBack={pop} onNavigate={navigate} savedCount={saved.size}
            requestCount={allRequests.length} listingCount={agentListings.length} />
        )}
        {top === 'settings' && <Settings onBack={pop} />}
        {top === 'manage' && (
          <ManageListings listings={agentListings} onBack={pop} onOpen={openDetail} onNew={() => push('listing')} />
        )}
        {top === 'requests' && (
          <MyRequests requests={allRequests} onBack={pop} onNew={() => push('request')} />
        )}
        {top === 'request' && <RequestForm onClose={pop} onCreate={createRequest} />}
        {top === 'listing' && <ListingForm onClose={pop} onCreate={createListing} />}

        {/* detail overlay */}
        {detail && (
          <Detail l={detail} saved={saved.has(detail.id)} onBack={() => setDetailId(null)}
            onToggleSave={toggleSave} onOpenReel={openReel} />
        )}

        {/* reels overlay */}
        {reel.open && (
          <Reels reels={reels} startId={reel.id} saved={saved} onToggleSave={toggleSave}
            onOpen={openDetail} onClose={() => setReel({ open: false, id: null })} />
        )}

        {/* post chooser sheet */}
        <PostSheet open={showPost} onClose={() => setShowPost(false)}
          onRequest={() => { setShowPost(false); push('request'); }}
          onListing={() => { setShowPost(false); push('listing'); }} />

        {/* AI search overlay (primary search) */}
        {aiOpen && (
          <AISearchScreen onClose={() => setAiOpen(false)} onOpenDetail={openDetail}
            saved={saved} onToggleSave={toggleSave} />
        )}

        {/* Guided filter overlay (primary filter) */}
        {guidedOpen && (
          <GuidedFilterScreen onClose={() => setGuidedOpen(false)} onOpenDetail={openDetail} />
        )}
      </div>

      <TweaksPanel>
        <TweakSection label="Theme" />
        <TweakColor label="Accent" value={t.accent}
          options={['#2f7d62', '#b9603a', '#3a63b8', '#7a5bd0', '#2b2b29']}
          onChange={(v) => setTweak('accent', v)} />
        <TweakRadio label="Background" value={t.theme}
          options={['Warm', 'Cool', 'Paper']}
          onChange={(v) => setTweak('theme', v)} />
        <TweakRadio label="Typeface" value={t.typeface}
          options={['Hanken Grotesk', 'Schibsted Grotesk', 'System']}
          onChange={(v) => setTweak('typeface', v)} />
        <TweakSection label="Layout" />
        <TweakRadio label="Card style" value={t.cardStyle}
          options={['Classic', 'Overlay', 'Compact']}
          onChange={(v) => setTweak('cardStyle', v)} />
        <TweakRadio label="Corners" value={t.radius}
          options={['Sharp', 'Soft', 'Round']}
          onChange={(v) => setTweak('radius', v)} />
        <TweakToggle label="Photo labels" value={t.photoLabels}
          onChange={(v) => setTweak('photoLabels', v)} />
      </TweaksPanel>
    </IOSDevice>
  );
}

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