/* global React, ReactDOM, SAMPLE, fmt, I, MiniMap, CardHybrid, CardEditorial, CardUtility, HeroImg, SourceBadge, VisibilityDot, StatusPip */
// Interactive board prototype. Masonry-with-rhythm grid, top bar, filters,
// detail drawer, save-via-URL flow.

const { useState, useEffect, useMemo } = React;

// ── App shell ─────────────────────────────────────────────────
function HHDApp({ initialConcept = 'hybrid', initialDensity = 'balanced', initialVisMode = 'medium', initialLayout = 'masonry', initialDetail = 'drawer', boardWidth = 1280 }) {
  const [items, setItems] = useState(SAMPLE);
  const [openId, setOpenId] = useState(null);
  const [saveOpen, setSaveOpen] = useState(false);
  const [filter, setFilter] = useState('all'); // all | shortlisted | visited | favorite | private | public
  const [region, setRegion] = useState('all');
  const [search, setSearch] = useState('');
  const [sort, setSort] = useState('recent'); // recent | price-asc | price-desc
  const [viewportWidth, setViewportWidth] = useState(typeof window !== 'undefined' ? window.innerWidth : boardWidth);

  useEffect(() => {
    const onResize = () => setViewportWidth(window.innerWidth);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);

  const visible = useMemo(() => {
    let v = items.slice();
    if (filter === 'shortlisted' || filter === 'visited' || filter === 'favorite') v = v.filter((p) => p.status === filter);
    if (filter === 'public') v = v.filter((p) => p.visibility === 'public');
    if (filter === 'private') v = v.filter((p) => p.visibility === 'private');
    if (region !== 'all') v = v.filter((p) => p.region === region);
    if (search.trim()) {
      const q = search.toLowerCase();
      v = v.filter((p) => (p.title + ' ' + p.neighborhood + ' ' + p.note).toLowerCase().includes(q));
    }
    if (sort === 'price-asc') v.sort((a, b) => (a.price || 0) - (b.price || 0));
    if (sort === 'price-desc') v.sort((a, b) => (b.price || 0) - (a.price || 0));
    return v;
  }, [items, filter, region, search, sort]);

  const open = items.find((p) => p.id === openId);
  const regions = ['all', ...Array.from(new Set(items.map((p) => p.region)))];
  const isMobile = viewportWidth <= 820;
  const isTablet = viewportWidth > 820 && viewportWidth < 1280;
  const effectiveDetail = isMobile ? 'sheet' : initialDetail;

  return (
    <div style={{ minHeight: '100%', background: 'var(--paper)' }}>
      <TopBar onSave={() => setSaveOpen(true)} search={search} setSearch={setSearch} isMobile={isMobile} />
      <FilterBar filter={filter} setFilter={setFilter} region={region} setRegion={setRegion} regions={regions} sort={sort} setSort={setSort} count={visible.length} isMobile={isMobile} isTablet={isTablet} />
      <main style={{ maxWidth: boardWidth, margin: '0 auto', padding: isMobile ? '18px 12px 88px' : (isTablet ? '24px 24px 88px' : '24px 32px 80px') }}>
        <BoardHeader count={visible.length} total={items.length} isMobile={isMobile} />
        <Board
          items={visible}
          concept={initialConcept}
          density={initialDensity}
          visMode={initialVisMode}
          layout={initialLayout}
          onOpen={(id) => setOpenId(id)}
          viewportWidth={viewportWidth}
          isMobile={isMobile}
        />
      </main>
      {open && effectiveDetail === 'drawer' && (
        <DetailDrawer p={open} onClose={() => setOpenId(null)} onUpdate={(patch) => setItems((xs) => xs.map((x) => x.id === open.id ? { ...x, ...patch } : x))} />
      )}
      {open && effectiveDetail === 'modal' && (
        <DetailModal p={open} onClose={() => setOpenId(null)} onUpdate={(patch) => setItems((xs) => xs.map((x) => x.id === open.id ? { ...x, ...patch } : x))} />
      )}
      {open && effectiveDetail === 'sheet' && (
        <DetailSheet p={open} onClose={() => setOpenId(null)} onUpdate={(patch) => setItems((xs) => xs.map((x) => x.id === open.id ? { ...x, ...patch } : x))} />
      )}
      {saveOpen && (
        <SaveModal onClose={() => setSaveOpen(false)} onSave={(item) => { setItems((xs) => [item, ...xs]); setSaveOpen(false); }} />
      )}
    </div>
  );
}

// ── Top bar ─────────────────────────────────────────────────
function TopBar({ onSave, search, setSearch, isMobile }) {
  return (
    <header style={{
      position: 'sticky', top: 0, zIndex: 10,
      borderBottom: '1px solid var(--line-2)',
      background: 'rgba(247,243,236,.85)', backdropFilter: 'blur(12px)',
    }}>
      <div style={{
        maxWidth: 1280, margin: '0 auto', padding: isMobile ? '12px 12px' : '14px 32px',
        display: 'flex', alignItems: 'center', gap: isMobile ? 10 : 24,
        flexWrap: isMobile ? 'wrap' : 'nowrap',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <Wordmark />
        </div>
        {!isMobile && (
          <nav style={{ display: 'flex', gap: 4, marginLeft: 8 }}>
            {['Diary', 'Visited', 'Public', 'Map'].map((n, i) => (
              <button key={n} style={{
                padding: '6px 12px', borderRadius: 6, fontSize: 13,
                fontWeight: i === 0 ? 600 : 500,
                color: i === 0 ? 'var(--ink)' : 'var(--ink-3)',
                background: i === 0 ? 'var(--paper-3)' : 'transparent',
              }}>{n}</button>
            ))}
          </nav>
        )}
        <div style={{
          flex: 1, maxWidth: isMobile ? '100%' : 360, marginLeft: isMobile ? 0 : 'auto', position: 'relative',
          minWidth: isMobile ? '100%' : 0,
          order: isMobile ? 3 : 0,
        }}>
          <span style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', color: 'var(--ink-3)' }}>{I.search(14)}</span>
          <input
            value={search} onChange={(e) => setSearch(e.target.value)}
            placeholder="Search by neighborhood, note, or word..."
            style={{
              width: '100%', padding: '8px 12px 8px 34px',
              border: '1px solid var(--line-2)', borderRadius: 999,
              background: 'var(--paper-2)',
              fontSize: 13, color: 'var(--ink)',
              fontFamily: 'inherit', outline: 'none',
            }}
            onFocus={(e) => e.target.style.borderColor = 'var(--accent)'}
            onBlur={(e) => e.target.style.borderColor = 'var(--line-2)'}
          />
        </div>
        <button onClick={onSave} style={{
          display: isMobile ? 'none' : 'inline-flex', alignItems: 'center', gap: 6,
          padding: '8px 14px', borderRadius: 999,
          background: 'var(--ink)', color: 'var(--paper)',
          fontSize: 13, fontWeight: 500,
        }}>{I.plus(13)} Save a home</button>
        <div style={{
          width: 32, height: 32, borderRadius: 999,
          background: 'var(--accent-soft)', color: 'var(--accent-ink)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          fontSize: 12, fontWeight: 600, fontFamily: 'var(--serif)',
        }}>EM</div>
      </div>
    </header>
  );
}

function Wordmark() {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <div style={{
        width: 24, height: 24, borderRadius: 5,
        background: 'var(--accent)', color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: 'var(--serif)', fontWeight: 600, fontSize: 14,
      }}>H</div>
      <div style={{ display: 'flex', flexDirection: 'column', lineHeight: 1 }}>
        <span style={{ fontFamily: 'var(--serif)', fontSize: 16, fontWeight: 600, letterSpacing: -0.2 }}>House Hunt Diary</span>
      </div>
    </div>
  );
}

// ── Filter bar ─────────────────────────────────────────────
function FilterBar({ filter, setFilter, region, setRegion, regions, sort, setSort, count, isMobile, isTablet }) {
  const tabs = [
    { id: 'all',         label: 'All saves' },
    { id: 'shortlisted', label: 'Shortlisted' },
    { id: 'favorite',    label: 'Favorites' },
    { id: 'visited',     label: 'Visited' },
    { id: 'private',     label: 'Private' },
    { id: 'public',      label: 'Public' },
  ];
  return (
    <div style={{
      borderBottom: '1px solid var(--line-2)',
      background: 'var(--paper)',
    }}>
      <div style={{
        maxWidth: 1280, margin: '0 auto', padding: isMobile ? '10px 12px' : (isTablet ? '10px 24px' : '10px 32px'),
        display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap',
      }}>
        <div className={isMobile ? 'no-scrollbar' : ''} style={{ display: 'flex', gap: 2, overflowX: isMobile ? 'auto' : 'visible', maxWidth: '100%', whiteSpace: isMobile ? 'nowrap' : 'normal' }}>
          {tabs.map((t) => (
            <button key={t.id} onClick={() => setFilter(t.id)}
              style={{
                padding: '6px 10px', borderRadius: 6,
                fontSize: 12.5, fontWeight: filter === t.id ? 600 : 500,
                color: filter === t.id ? 'var(--ink)' : 'var(--ink-3)',
                background: filter === t.id ? 'var(--paper-3)' : 'transparent',
              }}>{t.label}</button>
          ))}
        </div>
        {!isMobile && <div style={{ width: 1, height: 18, background: 'var(--line-2)' }} />}
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, color: 'var(--ink-3)' }}>
          {I.pin(13)}
          <select value={region} onChange={(e) => setRegion(e.target.value)} style={{
            border: 0, background: 'transparent', fontSize: 12.5, fontWeight: 500,
            color: 'var(--ink-2)', cursor: 'pointer', fontFamily: 'inherit', padding: '4px 6px',
            borderRadius: 4,
          }}>
            {regions.map((r) => <option key={r} value={r}>{r === 'all' ? 'All regions' : r}</option>)}
          </select>
        </div>
        {!isMobile && <div style={{ flex: 1 }} />}
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, color: 'var(--ink-3)' }}>
          <span>{count} {count === 1 ? 'home' : 'homes'}</span>
          <span className="dot" />
          <select value={sort} onChange={(e) => setSort(e.target.value)} style={{
            border: 0, background: 'transparent', fontSize: 12.5, fontWeight: 500,
            color: 'var(--ink-2)', cursor: 'pointer', fontFamily: 'inherit', padding: '4px 6px',
            borderRadius: 4,
          }}>
            <option value="recent">Recently saved</option>
            <option value="price-asc">Price · low → high</option>
            <option value="price-desc">Price · high → low</option>
          </select>
        </div>
      </div>
    </div>
  );
}

// ── Board header ─────────────────────────────────────────────
function BoardHeader({ count, total, isMobile }) {
  return (
    <div style={{ marginBottom: isMobile ? 16 : 24, paddingTop: 8 }}>
      <h1 style={{
        margin: 0, fontFamily: 'var(--serif)', fontSize: isMobile ? 26 : 32, fontWeight: 500,
        letterSpacing: -0.5, color: 'var(--ink)',
      }}>Your diary</h1>
      <p style={{
        margin: '6px 0 0', fontFamily: 'var(--serif)', fontSize: 14, fontStyle: 'italic',
        color: 'var(--ink-3)',
      }}>
        {total === 0
          ? "An empty page, ready for the first home you fall for."
          : `${total} homes you've thought about so far. Take your time.`}
      </p>
    </div>
  );
}

// ── Board (masonry) ─────────────────────────────────────────
function Board({ items, concept, density, visMode, layout, onOpen, viewportWidth, isMobile }) {
  const Card = concept === 'editorial' ? CardEditorial : (concept === 'utility' ? CardUtility : CardHybrid);
  const colCount = viewportWidth <= 820 ? 2 : (viewportWidth < 1280 ? 3 : 4);
  const gap = viewportWidth <= 820 ? 12 : 24;
  const usableWidth = Math.min(viewportWidth <= 820 ? viewportWidth - 24 : (viewportWidth < 1280 ? viewportWidth - 48 : 1216), 1216);
  const cardWidth = Math.floor((usableWidth - gap * (colCount - 1)) / colCount);
  if (items.length === 0) {
    return <EmptyState />;
  }
  if (isMobile || layout === 'grid') {
    return (
      <div style={{
        display: 'grid', gridTemplateColumns: `repeat(${colCount}, 1fr)`,
        gap,
      }}>
        {items.map((p) => (
          <button key={p.id} onClick={() => onOpen(p.id)} style={{ textAlign: 'left', display: 'block', width: '100%' }}>
            <Card p={p} w={cardWidth} />
          </button>
        ))}
      </div>
    );
  }
  return (
    <div style={{ columnCount: colCount, columnGap: gap }}>
      {items.map((p) => (
        <button key={p.id} onClick={() => onOpen(p.id)} style={{
          breakInside: 'avoid', display: 'block', width: '100%',
          marginBottom: gap, textAlign: 'left',
        }}>
          <Card p={p} w={cardWidth} />
        </button>
      ))}
    </div>
  );
}

function EmptyState() {
  return (
    <div style={{
      padding: '80px 0', textAlign: 'center',
    }}>
      <div style={{ fontFamily: 'var(--serif)', fontSize: 18, color: 'var(--ink-2)', fontStyle: 'italic' }}>
        Nothing on this page yet.
      </div>
      <div style={{ marginTop: 6, color: 'var(--ink-3)', fontSize: 13 }}>
        Try a different filter, or save a new home.
      </div>
    </div>
  );
}

Object.assign(window, { HHDApp });
