/* Sohbet Arama — full search page with multi-select filters */
const { useState: sUseState, useMemo: sUseMemo, useRef: sUseRef, useEffect: sUseEffect } = React;

/* topic dictionary → derive tags from a talk's title (no fabricated data, just keyword tagging) */
const SK_TOPICS = [
  'Hac','Umre','Oruç','Namaz','Zekât','Sabır','Merhamet','İlim','Takvâ','Tevbe',
  'Rızık','Edep','Tasavvuf','Peygamber','Hadis','Tefsir','Nefis','Ahlâk','Selâm','Münafık','Vefât','Şeref'
];
function tagsFor(talk) {
  const hay = (talk.title + ' ' + talk.category).toLocaleLowerCase('tr');
  const out = SK_TOPICS.filter(tp => hay.includes(tp.toLocaleLowerCase('tr')));
  // always include the lesson family as an implicit tag-ish chip source via category (handled separately)
  return out;
}
function parseYear(greg) { const m = (greg || '').match(/\b(\d{4})\b/); return m ? +m[1] : null; }
function durBucket(sec) {
  if (sec <= 300) return 'd5';
  if (sec <= 1200) return 'd520';
  if (sec <= 3600) return 'd2060';
  return 'd60';
}

/* ---- year range as two numeric inputs ---- */
function YearInputs({ min, max, lo, hi, onChange, t }) {
  return (
    <div className="sf-yr">
      <label className="sf-yr-fld">
        <span>{t('yr_from')}</span>
        <input type="number" inputMode="numeric" min={min} max={max} value={lo}
          onChange={e => onChange(e.target.value === '' ? min : +e.target.value, hi)} />
      </label>
      <span className="sf-yr-dash" aria-hidden="true">–</span>
      <label className="sf-yr-fld">
        <span>{t('yr_to')}</span>
        <input type="number" inputMode="numeric" min={min} max={max} value={hi}
          onChange={e => onChange(lo, e.target.value === '' ? max : +e.target.value)} />
      </label>
    </div>
  );
}

/* ---- a collapsible filter group ---- */
function FGroup({ title, count, children, defaultOpen = true }) {
  const [open, setOpen] = sUseState(defaultOpen);
  return (
    <div className={'fg' + (open ? ' is-open' : '')}>
      <button className="fg-head" onClick={() => setOpen(o => !o)}>
        <span>{title}{count > 0 && <span className="fg-badge">{count}</span>}</span>
        <Icon name="chevD" size={16} />
      </button>
      {open && <div className="fg-body">{children}</div>}
    </div>
  );
}

function Check({ on, onClick, label, sub, mono }) {
  return (
    <button className={'ck' + (on ? ' on' : '')} onClick={onClick} role="checkbox" aria-checked={on}>
      <span className="ck-box">{on && <Icon name="check" size={13} />}</span>
      {mono}
      <span className="ck-label">{label}{sub != null && <em>{sub}</em>}</span>
    </button>
  );
}

function SearchApp() {
  const D = window.SK_DATA;
  const I18 = window.SK_I18N;
  const { t, lang } = I18.useLang();
  const all = sUseMemo(() => [D.featured, ...D.talks].map(tk => ({ ...tk, _year: parseYear(tk.greg), _tags: tagsFor(tk) })), []);

  const years = all.map(t => t._year).filter(Boolean);
  const YMIN = Math.min(...years), YMAX = Math.max(...years);

  const params = new URLSearchParams(location.search);
  const [kw, setKw] = sUseState(params.get('q') || '');
  const [spk, setSpk] = sUseState(() => {
    const sp = params.get('sp');
    return new Set(sp && D.speakers.some(s => s.id === sp) ? [sp] : []);
  });
  const [cats, setCats] = sUseState(new Set());
  const [topics, setTopics] = sUseState(new Set());
  const [durs, setDurs] = sUseState(new Set());
  const [yr, setYr] = sUseState([YMIN, YMAX]);
  const [sort, setSort] = sUseState('rel');
  const [page, setPage] = sUseState(1);
  const PER_PAGE = 10;
  // İçerik araması (FTS): transkriptlerde geçen ama başlıkta olmayan sohbetleri de bul.
  const [content, setContent] = sUseState({ map: {}, order: [] });

  const [tw, setTw] = useTweaks(window.SK_TWEAK_DEFAULTS);
  window.applyTweaks(tw);

  const toggle = (set, setter) => (v) => {
    const n = new Set(set); n.has(v) ? n.delete(v) : n.add(v); setter(n);
  };
  const yrActive = yr[0] !== YMIN || yr[1] !== YMAX;
  const clearAll = () => { setKw(''); setSpk(new Set()); setCats(new Set()); setTopics(new Set()); setDurs(new Set()); setYr([YMIN, YMAX]); };
  const activeCount = spk.size + cats.size + topics.size + durs.size + (yrActive ? 1 : 0) + (kw.trim() ? 1 : 0);

  const catList = sUseMemo(() => {
    const s = new Set(); all.forEach(t => s.add(t.category)); return [...s];
  }, []);
  const topicList = sUseMemo(() => {
    const c = {}; all.forEach(t => t._tags.forEach(tg => c[tg] = (c[tg] || 0) + 1));
    return Object.keys(c).sort((a, b) => c[b] - c[a]);
  }, []);

  // kw değişince transkript içeriğinde de ara (debounced, sunucu FTS).
  sUseEffect(() => {
    const q = kw.trim();
    if (q.length < 2) { setContent({ map: {}, order: [] }); return; }
    let alive = true;
    const base = window.SK_API_BASE || '';
    const id = setTimeout(() => {
      fetch(base + '/api/search?q=' + encodeURIComponent(q) + '&limit=100')
        .then(r => r.ok ? r.json() : null)
        .then(d => {
          if (!alive || !d || !d.results) return;
          const map = {}, order = [];
          d.results.forEach(r => { map[r.slug] = r.snippet || ''; order.push(r.slug); });
          setContent({ map, order });
        })
        .catch(() => {});
    }, 250);
    return () => { alive = false; clearTimeout(id); };
  }, [kw]);

  const results = sUseMemo(() => {
    const n = kw.trim().toLocaleLowerCase('tr');
    const cmap = content.map;
    let list = all.filter(t => {
      if (n) {
        const hay = (t.title + ' ' + t.speaker.name + ' ' + t.category + ' ' + t._tags.join(' ')).toLocaleLowerCase('tr');
        if (!hay.includes(n) && !(t.slug in cmap)) return false;   // başlık VEYA içerik eşleşmesi
      }
      if (spk.size && !spk.has(t.speaker.id)) return false;
      if (cats.size && !cats.has(t.category)) return false;
      if (topics.size && !t._tags.some(tg => topics.has(tg))) return false;
      if (durs.size && !durs.has(durBucket(t.dur))) return false;
      if (yrActive) { const yLo = Math.min(yr[0], yr[1]), yHi = Math.max(yr[0], yr[1]); if (!t._year) return false; if (t._year < yLo || t._year > yHi) return false; }
      return true;
    });
    const byYear = (a, b) => (a._year || 0) - (b._year || 0);
    if (sort === 'new') list = [...list].sort((a, b) => byYear(b, a));
    else if (sort === 'old') list = [...list].sort(byYear);
    else if (sort === 'long') list = [...list].sort((a, b) => b.dur - a.dur);
    else if (sort === 'short') list = [...list].sort((a, b) => a.dur - b.dur);
    else if (sort === 'rel' && n && content.order.length) {
      const rank = {}; content.order.forEach((s, i) => rank[s] = i);   // FTS ilgi sırası öne
      list = [...list].sort((a, b) => (a.slug in rank ? rank[a.slug] : 1e9) - (b.slug in rank ? rank[b.slug] : 1e9));
    }
    return list;
  }, [kw, spk, cats, topics, durs, yr, sort, content]);

  // reset to first page whenever the result set changes
  sUseEffect(() => { setPage(1); }, [kw, spk, cats, topics, durs, yr, sort, content]);
  const pageCount = Math.max(1, Math.ceil(results.length / PER_PAGE));
  const curPage = Math.min(page, pageCount);
  const shown = results.slice((curPage - 1) * PER_PAGE, curPage * PER_PAGE);

  const durDefs = [['d5', t('dur_5')], ['d520', t('dur_5_20')], ['d2060', t('dur_20_60')], ['d60', t('dur_60')]];

  // active filter chips
  const chips = [];
  spk.forEach(id => { const p = D.speakers.find(s => s.id === id); chips.push({ k: 'spk:' + id, label: p.short, off: () => toggle(spk, setSpk)(id) }); });
  cats.forEach(c => chips.push({ k: 'cat:' + c, label: c, off: () => toggle(cats, setCats)(c) }));
  topics.forEach(c => chips.push({ k: 'top:' + c, label: c, off: () => toggle(topics, setTopics)(c) }));
  durs.forEach(c => { const d = durDefs.find(x => x[0] === c); chips.push({ k: 'dur:' + c, label: d[1], off: () => toggle(durs, setDurs)(c) }); });
  if (yrActive) chips.push({ k: 'yr', label: `${yr[0]} – ${yr[1]}`, off: () => setYr([YMIN, YMAX]) });

  return (
    <>
      <Header />
      <main className="srch">
        <div className="wrap">
          <div className="crumb">
            <a href="index.html">{t('discover')}</a><span className="dot">›</span>
            <span style={{ color: 'var(--ink-2)' }}>{t('search_title')}</span>
          </div>

          <header className="srch-head">
            <h1>{t('search_title')}</h1>
            <p>{t('search_sub')}</p>
            <div className="srch-bar">
              <Icon name="search" size={22} style={{ color: 'var(--ink-3)' }} />
              <input autoFocus value={kw} onChange={e => setKw(e.target.value)} placeholder={t('kw_ph')} aria-label={t('search_title')} />
              {kw && <button className="srch-clear" onClick={() => setKw('')} aria-label="Temizle"><Icon name="close" size={18} /></button>}
            </div>
          </header>

          <div className="srch-grid">
            {/* ---- filters ---- */}
            <aside className="srch-filters">
              <div className="sf-head">
                <h2><Icon name="sliders" size={18} /> {t('f_filters')}</h2>
                {activeCount > 0 && <button className="sf-clear" onClick={clearAll}>{t('f_clear')} ({activeCount})</button>}
              </div>

              <FGroup title={t('f_speaker')} count={spk.size}>
                {D.speakers.map(s => (
                  <Check key={s.id} on={spk.has(s.id)} onClick={() => toggle(spk, setSpk)(s.id)}
                    label={s.short}
                    sub={all.filter(t => t.speaker.id === s.id).length} />
                ))}
              </FGroup>

              <FGroup title={t('f_category')} count={cats.size}>
                {catList.map(c => (
                  <Check key={c} on={cats.has(c)} onClick={() => toggle(cats, setCats)(c)}
                    label={c} sub={all.filter(t => t.category === c).length} />
                ))}
              </FGroup>

              <FGroup title={t('f_topic')} count={topics.size}>
                <div className="sf-tags">
                  {topicList.map(tg => (
                    <button key={tg} className={'sf-tag' + (topics.has(tg) ? ' on' : '')} onClick={() => toggle(topics, setTopics)(tg)}>
                      {tg}
                    </button>
                  ))}
                </div>
              </FGroup>

              <FGroup title={t('f_year')} count={yrActive ? 1 : 0}>
                <YearInputs min={YMIN} max={YMAX} lo={yr[0]} hi={yr[1]} onChange={(a, b) => setYr([a, b])} t={t} />
              </FGroup>

              <FGroup title={t('f_duration')} count={durs.size}>
                {durDefs.map(([k, lbl]) => (
                  <Check key={k} on={durs.has(k)} onClick={() => toggle(durs, setDurs)(k)} label={lbl} />
                ))}
              </FGroup>
            </aside>

            {/* ---- results ---- */}
            <section className="srch-results">
              <div className="sr-bar">
                <div className="sr-count"><b>{results.length}</b> {t('res_count')}</div>
                <div className="sr-sort">
                  <span>{t('sort_by')}:</span>
                  <div className="ds-sel">
                    <select value={sort} onChange={e => setSort(e.target.value)}>
                      <option value="rel">{t('sort_rel')}</option>
                      <option value="new">{t('sort_new')}</option>
                      <option value="old">{t('sort_old')}</option>
                      <option value="long">{t('sort_long')}</option>
                      <option value="short">{t('sort_short')}</option>
                    </select>
                    <Icon name="chevD" size={15} />
                  </div>
                </div>
              </div>

              {chips.length > 0 && (
                <div className="sr-chips">
                  {chips.map(c => (
                    <button key={c.k} className="sr-chip" onClick={c.off}>{c.label} <Icon name="close" size={13} /></button>
                  ))}
                  <button className="sr-chip clear" onClick={clearAll}>{t('f_clear')}</button>
                </div>
              )}

              {results.length === 0 ? (
                <div className="sr-empty">
                  <Icon name="search" size={34} style={{ color: 'var(--ink-4)' }} />
                  <p className="sr-empty-h">{t('no_res_filter')}</p>
                  <p className="sr-empty-s">{t('no_res_hint')}</p>
                  <button className="btn btn-ghost" onClick={clearAll}>{t('f_clear')}</button>
                </div>
              ) : (
                <>
                <div className="sr-list">
                  {shown.map(tk => (
                    <a key={tk.slug} className="sr-row" href={`watch.html?v=${tk.slug}`}>
                      <div className="sr-thumb" data-cat={tk.category}>
                        <span className="sr-kind"><Icon name={tk.kind === 'audio' ? 'headphones' : 'video'} size={13} /></span>
                      </div>
                      <div className="sr-main">
                        <span className="tag">{tk.category}</span>
                        <h3>{highlight(tk.title, kw)}</h3>
                        <div className="sr-meta">
                          <span>{tk.speaker.short}</span>
                          {tk.greg !== '—' && <><span className="dot">·</span><span>{tk.greg}</span></>}
                          {tk._tags.slice(0, 3).map(tg => <span key={tg} className="sr-tagchip">{tg}</span>)}
                        </div>
                        {content.map[tk.slug] && (
                          <p className="sr-snippet" dangerouslySetInnerHTML={{ __html: snippetHtml(content.map[tk.slug]) }} />
                        )}
                      </div>
                      <span className="sr-dur">{tk.durLabel}</span>
                    </a>
                  ))}
                </div>
                {pageCount > 1 && (
                  <nav className="sr-pager" aria-label="Sayfalar">
                    <button className="sr-pg-btn" disabled={curPage === 1} onClick={() => setPage(p => Math.max(1, p - 1))}>
                      <Icon name="chevL" size={16} /> {t('page_prev')}
                    </button>
                    <div className="sr-pg-nums">
                      {(() => {
                        // Pencereli pager: 1 … (cur-1) cur (cur+1) … son  → çok sayıda sayfada taşmayı önler
                        const first = 1, last = pageCount, win = 1;
                        const lo = Math.max(first + 1, curPage - win);
                        const hi = Math.min(last - 1, curPage + win);
                        const items = [first];
                        if (lo > first + 1) items.push('gapL');
                        for (let n = lo; n <= hi; n++) items.push(n);
                        if (hi < last - 1) items.push('gapR');
                        if (last > first) items.push(last);
                        return items.map((it) => typeof it === 'number'
                          ? <button key={it} className={'sr-pg-num' + (it === curPage ? ' on' : '')}
                              onClick={() => setPage(it)} aria-current={it === curPage ? 'page' : undefined}>{it}</button>
                          : <span key={it} className="sr-pg-num" style={{ pointerEvents: 'none', background: 'none', border: 'none', opacity: .5 }}>…</span>);
                      })()}
                    </div>
                    <button className="sr-pg-btn" disabled={curPage === pageCount} onClick={() => setPage(p => Math.min(pageCount, p + 1))}>
                      {t('page_next')} <Icon name="chevR" size={16} />
                    </button>
                  </nav>
                )}
                </>
              )}
            </section>
          </div>
        </div>
      </main>
      <Footer />
      <SKTweaks t={tw} setTweak={setTw} />
      <ModalHost />
    </>
  );
}

/* highlight keyword in a title */
function highlight(text, kw) {
  const n = kw.trim();
  if (!n) return text;
  const low = text.toLocaleLowerCase('tr'), nl = n.toLocaleLowerCase('tr');
  const i = low.indexOf(nl);
  if (i === -1) return text;
  return <>{text.slice(0, i)}<mark className="sr-mark">{text.slice(i, i + n.length)}</mark>{text.slice(i + n.length)}</>;
}

/* FTS snippet → güvenli HTML (〈 〉 işaretlerini <mark> yap, gerisini escape et) */
function snippetHtml(s) {
  const esc = String(s || '').replace(/[&<>]/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[c]));
  return esc.replace(/〈/g, '<mark class="sr-mark">').replace(/〉/g, '</mark>');
}

(window.SK_READY || Promise.resolve()).then(() =>
  ReactDOM.createRoot(document.getElementById('root')).render(<SearchApp />));
