/* Question Bank — React app
   Reads window.QUESTIONS, renders filterable list with sticky rail. */

const { useState, useMemo, useEffect, useCallback } = React;

const TWEAK_DEFAULTS = window.TWEAK_DEFAULTS || {
  density: 'regular',
  numStyle: 'serif',
  pills: 'all',
  accent: '#F6891F',
  questionFont: 'serif',
  pageSize: 25,
};

// ---------- Constants ----------
const CATEGORY_ORDER = [
  ['product_sense',   'Product sense'],
  ['behavioral',      'Behavioral'],
  ['technical_fluency','Technical fluency'],
  ['stakeholder',     'Stakeholder'],
  ['trust_safety',    'Trust & safety'],
  ['metrics',         'Metrics'],
  ['strategy',        'Strategy'],
  ['evals',           'Evals'],
  ['case_study',      'Case study'],
  ['go_to_market',    'Go-to-market'],
  ['experimentation', 'Experimentation'],
  ['data',            'Data'],
  ['communication',   'Communication'],
];
const CAT_LABEL = Object.fromEntries(CATEGORY_ORDER);

const DIFFICULTY_ORDER = [
  ['easy',   'Easy'],
  ['medium', 'Medium'],
  ['hard',   'Hard'],
  ['senior', 'Senior'],
];

const EVIDENCE_LABEL = {
  reported_paraphrased: 'Real Interview',
  synthesized_from_real_interview_patterns: 'AI Generated',
};

const PAGE_SIZE_DEFAULT = 25;

// ---------- Helpers ----------
function unique(arr) { return [...new Set(arr)]; }
function countBy(items, key) {
  const m = new Map();
  for (const it of items) {
    const v = (it[key] || '').trim();
    if (!v) continue;
    m.set(v, (m.get(v) || 0) + 1);
  }
  return [...m.entries()].sort((a,b) => b[1] - a[1]);
}
function shortenSrc(s) {
  return (s || '')
    .replace(/^glassdoor_/, 'glassdoor · ')
    .replace(/^exponent_/, 'exponent · ')
    .replace(/_ai_pm.*$/, ' AI PM')
    .replace(/_2026$/, ' 2026')
    .replace(/_/g,' ');
}

// ---------- Components ----------

function Chip({ on, onClick, label, n, modifier }) {
  return (
    <button
      type="button"
      className={`chip ${on ? 'on' : ''} ${modifier || ''}`}
      onClick={onClick}
    >
      <span>{label}</span>
      {typeof n === 'number' && <span className="chip-n">{n}</span>}
    </button>
  );
}

function FilterListItem({ on, onClick, name, num }) {
  return (
    <div className={`filter-item ${on ? 'on' : ''}`} onClick={onClick}>
      <span className="check"></span>
      <span className="name">{name}</span>
      <span className="num">{num}</span>
    </div>
  );
}

function QuestionCard({ q, open, onToggle }) {
  const [showAns, setShowAns] = useState(false);
  useEffect(() => { if (!open) setShowAns(false); }, [open]);

  const catLabel = CAT_LABEL[q.cat] || q.cat;

  return (
    <article className={`qcard ${open ? 'open' : ''}`} data-id={q.id}>
      <header className="qcard-head" onClick={onToggle}>
        <div className="qcard-body">
          <div className="qcard-meta">
            <span className="pill pill-cat">
              <span className={`cdot ${q.cat}`}></span>
              {catLabel}
            </span>
            <span className={`pill pill-diff ${q.diff}`}>{q.diff}</span>
            {q.co && <span className="pill pill-co">{q.co}</span>}
            {q.role && <span className="pill pill-role">{q.role}</span>}
            {q.ev && (
              <span className="pill pill-ev" title={EVIDENCE_LABEL[q.ev] || q.ev}>
                {EVIDENCE_LABEL[q.ev] || q.ev}
              </span>
            )}
            {q.src && (
              <span className="pill pill-src" title={`Source: ${shortenSrc(q.src)}`}>
                {shortenSrc(q.src)}
              </span>
            )}
          </div>
          <p className="qcard-question">{q.q}</p>
        </div>
        <button
          type="button"
          className="qcard-expand"
          aria-label={open ? 'Close' : 'Open'}
          onClick={(e) => { e.stopPropagation(); onToggle(); }}
        ></button>
      </header>

      {open && (
        <>
          <div className="qcard-content">
            <div className="content-block">
              <div className="content-label">Answer framework</div>
              <div className="framework-text">{q.fw}</div>
            </div>

            <div className="content-block">
              <button
                type="button"
                className="answer-toggle"
                onClick={() => setShowAns(s => !s)}
              >
                {showAns ? '− Hide sample answer' : '+ Show full sample answer'}
              </button>
              <div className={`answer-text ${showAns ? 'show' : ''}`}>
                {q.ans}
              </div>
            </div>

            <div className="qcard-foot">
              <span className="src">Source: {shortenSrc(q.src)}</span>
              <div className="actions">
                <button
                  type="button"
                  className="icon-btn"
                  title="Copy question"
                  onClick={() => {
                    navigator.clipboard?.writeText(q.q);
                  }}
                >⎘</button>
              </div>
            </div>
          </div>
        </>
      )}
    </article>
  );
}

function ActiveFilters({ filters, onRemove }) {
  const chips = [];
  filters.cats.forEach(c => chips.push({k:'category', v:c, label: CAT_LABEL[c] || c, fn:() => onRemove('cats', c)}));
  filters.diffs.forEach(d => chips.push({k:'difficulty', v:d, label: d, fn:() => onRemove('diffs', d)}));
  filters.evs.forEach(e => chips.push({k:'evidence', v:e, label: EVIDENCE_LABEL[e] || e, fn:() => onRemove('evs', e)}));
  filters.cos.forEach(c => chips.push({k:'company', v:c, label: c, fn:() => onRemove('cos', c)}));
  filters.roles.forEach(r => chips.push({k:'role', v:r, label: r, fn:() => onRemove('roles', r)}));
  if (filters.search) chips.push({k:'search', v:filters.search, label: `"${filters.search}"`, fn:() => onRemove('search', null)});

  if (chips.length === 0) return null;
  return (
    <div className="active-filters">
      {chips.map((c, i) => (
        <span className="af" key={c.k + c.v + i}>
          <span className="af-key">{c.k}</span>
          <span>{c.label}</span>
          <button type="button" className="x" onClick={c.fn} aria-label="Remove">×</button>
        </span>
      ))}
    </div>
  );
}

// ---------- Main App ----------
function App() {
  const data = window.QUESTIONS || [];
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Apply body data attrs for CSS hooks
  useEffect(() => {
    document.body.dataset.density = t.density;
    document.body.dataset.pills = t.pills;
    document.documentElement.style.setProperty('--orange', t.accent);
  }, [t.density, t.numStyle, t.pills, t.questionFont, t.accent]);

  const [search, setSearch] = useState('');
  const [cats, setCats] = useState(new Set());
  const [diffs, setDiffs] = useState(new Set());
  const [evs, setEvs] = useState(new Set());
  const [cos, setCos] = useState(new Set());
  const [roles, setRoles] = useState(new Set());
  const [sort, setSort] = useState('relevance');
  const [page, setPage] = useState(1);
  const [openId, setOpenId] = useState(null);
  const [showAllCompanies, setShowAllCompanies] = useState(false);
  const [showAllRoles, setShowAllRoles] = useState(false);
  const [companySearch, setCompanySearch] = useState('');

  // counts (global)
  const catCounts = useMemo(() => {
    const m = {};
    for (const q of data) m[q.cat] = (m[q.cat]||0)+1;
    return m;
  }, [data]);
  const diffCounts = useMemo(() => {
    const m = {};
    for (const q of data) m[q.diff] = (m[q.diff]||0)+1;
    return m;
  }, [data]);
  const evCounts = useMemo(() => {
    const m = {};
    for (const q of data) m[q.ev] = (m[q.ev]||0)+1;
    return m;
  }, [data]);

  const companies = useMemo(() => countBy(data, 'co'), [data]);
  const rolesList = useMemo(() => countBy(data, 'role'), [data]);

  // toggle helpers
  const toggle = (setFn) => (v) => setFn(prev => {
    const n = new Set(prev);
    n.has(v) ? n.delete(v) : n.add(v);
    return n;
  });
  const toggleCat = toggle(setCats);
  const toggleDiff = toggle(setDiffs);
  const toggleEv = toggle(setEvs);
  const toggleCo = toggle(setCos);
  const toggleRole = toggle(setRoles);

  // reset page when filters change
  useEffect(() => { setPage(1); }, [search, cats, diffs, evs, cos, roles, sort]);

  const filtered = useMemo(() => {
    const sq = search.trim().toLowerCase();
    let r = data.filter(q => {
      if (cats.size && !cats.has(q.cat)) return false;
      if (diffs.size && !diffs.has(q.diff)) return false;
      if (evs.size && !evs.has(q.ev)) return false;
      if (cos.size && !cos.has(q.co)) return false;
      if (roles.size && !roles.has(q.role)) return false;
      if (sq) {
        const hay = `${q.q} ${q.co} ${q.role} ${q.cat}`.toLowerCase();
        if (!hay.includes(sq)) return false;
      }
      return true;
    });
    if (sort === 'difficulty') {
      const order = {easy:0, medium:1, hard:2, senior:3};
      r = [...r].sort((a,b) => (order[a.diff]??9) - (order[b.diff]??9));
    } else if (sort === 'category') {
      r = [...r].sort((a,b) => (a.cat||'').localeCompare(b.cat||''));
    } else if (sort === 'company') {
      r = [...r].sort((a,b) => ((b.co||'zzz').localeCompare(a.co||'zzz') === 0 ? 0 : (a.co?'0':'1').localeCompare(b.co?'0':'1') || (a.co||'').localeCompare(b.co||'')));
    } else if (sort === 'id-asc') {
      r = [...r].sort((a,b) => a.id - b.id);
    }
    return r;
  }, [data, search, cats, diffs, evs, cos, roles, sort]);

  const PAGE_SIZE = t.pageSize || PAGE_SIZE_DEFAULT;
  const visible = filtered.slice(0, page * PAGE_SIZE);
  const hasMore = visible.length < filtered.length;

  const totalFilters = cats.size + diffs.size + evs.size + cos.size + roles.size + (search ? 1 : 0);
  const clearAll = () => {
    setCats(new Set()); setDiffs(new Set()); setEvs(new Set());
    setCos(new Set()); setRoles(new Set()); setSearch('');
  };
  const removeFilter = (key, v) => {
    if (key === 'search') setSearch('');
    if (key === 'cats') setCats(s => { const n = new Set(s); n.delete(v); return n; });
    if (key === 'diffs') setDiffs(s => { const n = new Set(s); n.delete(v); return n; });
    if (key === 'evs') setEvs(s => { const n = new Set(s); n.delete(v); return n; });
    if (key === 'cos') setCos(s => { const n = new Set(s); n.delete(v); return n; });
    if (key === 'roles') setRoles(s => { const n = new Set(s); n.delete(v); return n; });
  };

  // companies filtered by search
  const companiesShown = useMemo(() => {
    const cs = companySearch.trim().toLowerCase();
    let list = companies;
    if (cs) list = list.filter(([n]) => n.toLowerCase().includes(cs));
    return showAllCompanies ? list : list.slice(0, 12);
  }, [companies, showAllCompanies, companySearch]);

  const rolesShown = showAllRoles ? rolesList : rolesList.slice(0, 6);

  return (
    <>
    <TweaksPanel>
      <TweakSection label="Layout" />
      <TweakRadio label="Density" value={t.density}
        options={['compact','regular','comfy']}
        onChange={(v) => setTweak('density', v)} />
      <TweakRadio label="Meta pills" value={t.pills}
        options={['all','minimal','none']}
        onChange={(v) => setTweak('pills', v)} />
      <TweakSection label="Style" />
      <TweakColor label="Accent" value={t.accent}
        options={['#F6891F','#2A5BD7','#4A6D3A','#D7423E','#6B3B7A','#2C7A7B']}
        onChange={(v) => setTweak('accent', v)} />
      <TweakSection label="Pagination" />
      <TweakSlider label="Per page" value={t.pageSize} min={10} max={100} step={5}
        onChange={(v) => setTweak('pageSize', v)} />
    </TweaksPanel>
    <div className="bank-grid">

      {/* ===== RAIL ===== */}
      <aside className="rail">
        <div className="rail-head">
          <strong>Filter</strong>
          <button
            type="button"
            className={`rail-clear ${totalFilters ? 'has-filters' : ''}`}
            onClick={clearAll}
            disabled={!totalFilters}
          >
            {totalFilters ? `Clear (${totalFilters})` : 'Clear'}
          </button>
        </div>

        <div className="search-wrap">
          <input
            className="search"
            placeholder="Search questions, companies…"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>

        <div className="filter-block">
          <div className="filter-label">Difficulty <span className="count">{DIFFICULTY_ORDER.length}</span></div>
          <div className="chips">
            {DIFFICULTY_ORDER.map(([k, label]) => (
              <Chip
                key={k}
                label={label}
                n={diffCounts[k] || 0}
                on={diffs.has(k)}
                onClick={() => toggleDiff(k)}
                modifier={`diff-${k}`}
              />
            ))}
          </div>
        </div>

        <div className="filter-block">
          <div className="filter-label">Category <span className="count">{CATEGORY_ORDER.length}</span></div>
          <div className="filter-list">
            {CATEGORY_ORDER.map(([k, label]) => (
              catCounts[k] ? (
                <FilterListItem
                  key={k}
                  name={label}
                  num={catCounts[k]}
                  on={cats.has(k)}
                  onClick={() => toggleCat(k)}
                />
              ) : null
            ))}
          </div>
        </div>

        <div className="filter-block">
          <div className="filter-label">Evidence <span className="count">2</span></div>
          <div className="filter-list">
            <FilterListItem
              name="Real Interview"
              num={evCounts.reported_paraphrased || 0}
              on={evs.has('reported_paraphrased')}
              onClick={() => toggleEv('reported_paraphrased')}
            />
            <FilterListItem
              name="AI Generated"
              num={evCounts.synthesized_from_real_interview_patterns || 0}
              on={evs.has('synthesized_from_real_interview_patterns')}
              onClick={() => toggleEv('synthesized_from_real_interview_patterns')}
            />
          </div>
        </div>

        <div className="filter-block">
          <div className="filter-label">
            Role variant <span className="count">{rolesList.length}</span>
          </div>
          <div className="filter-list">
            {rolesShown.map(([name, n]) => (
              <FilterListItem
                key={name}
                name={name}
                num={n}
                on={roles.has(name)}
                onClick={() => toggleRole(name)}
              />
            ))}
          </div>
          {rolesList.length > 6 && (
            <button type="button" className="show-more" onClick={() => setShowAllRoles(s => !s)}>
              {showAllRoles ? '− Show fewer' : `+ ${rolesList.length - 6} more roles`}
            </button>
          )}
        </div>

        <div className="filter-block">
          <div className="filter-label">
            Company <span className="count">{companies.length}</span>
          </div>
          <input
            className="search"
            placeholder="Find a company…"
            value={companySearch}
            onChange={(e) => setCompanySearch(e.target.value)}
            style={{marginBottom:10, paddingLeft:14, fontSize:13, padding:'9px 12px'}}
          />
          <div className="filter-list">
            {companiesShown.map(([name, n]) => (
              <FilterListItem
                key={name}
                name={name}
                num={n}
                on={cos.has(name)}
                onClick={() => toggleCo(name)}
              />
            ))}
          </div>
          {companies.length > 12 && !companySearch && (
            <button type="button" className="show-more" onClick={() => setShowAllCompanies(s => !s)}>
              {showAllCompanies ? '− Show fewer' : `+ ${companies.length - 12} more companies`}
            </button>
          )}
        </div>
      </aside>

      {/* ===== RESULTS ===== */}
      <section>
        <div className="results-head">
          <div className="results-count">
            {filtered.length.toLocaleString()}
            <span className="of">of {data.length.toLocaleString()} questions</span>
          </div>
          <div className="results-controls">
            <select
              className="sort-select"
              value={sort}
              onChange={(e) => setSort(e.target.value)}
            >
              <option value="relevance">Sort: featured</option>
              <option value="id-asc">Sort: ID (asc)</option>
              <option value="difficulty">Sort: difficulty</option>
              <option value="category">Sort: category</option>
              <option value="company">Sort: company first</option>
            </select>
          </div>
        </div>

        <ActiveFilters
          filters={{cats, diffs, evs, cos, roles, search}}
          onRemove={removeFilter}
        />

        {filtered.length === 0 ? (
          <div className="empty">
            <h3>No matches.</h3>
            <p>Try loosening a filter or clearing search.</p>
            <button type="button" className="load-more" onClick={clearAll}>Clear filters</button>
          </div>
        ) : (
          <>
            <div className="cards">
              {visible.map(q => (
                <QuestionCard
                  key={q.id}
                  q={q}
                  open={openId === q.id}
                  onToggle={() => setOpenId(openId === q.id ? null : q.id)}
                />
              ))}
            </div>

            {hasMore && (
              <div className="load-more-wrap">
                <button
                  type="button"
                  className="load-more"
                  onClick={() => setPage(p => p + 1)}
                >
                  Load {Math.min(PAGE_SIZE, filtered.length - visible.length)} more →
                </button>
                <div className="load-more-meta">
                  {visible.length.toLocaleString()} of {filtered.length.toLocaleString()} shown
                </div>
              </div>
            )}
            {!hasMore && filtered.length > PAGE_SIZE && (
              <div className="load-more-wrap">
                <div className="load-more-meta">
                  — End of results · {filtered.length.toLocaleString()} questions —
                </div>
              </div>
            )}
          </>
        )}
      </section>
    </div>
    </>
  );
}

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