/* =========================================================
   三藏閣 — 사이드바 (탭: 목차 / 관련 / 출처 / 메모)
   기본은 목차(트리). 관련은 현재 본문에 등장한 개념·문헌,
   출처는 본문의 footnotes + sources, 메모는 사용자의 하이라이트.
   ========================================================= */

const { Icon: SbIcon } = window;

const PALI_VOLUME_COLORS = {
  dn: '#2e5c4a',
  mn: '#6b4a2e',
  sn: '#4a3870',
  an: '#8b5a14',
  kn: '#5d2a5a',
};

const NATURAL_TOC_COLLATOR = new Intl.Collator(['ko-KR', 'en'], {
  numeric: true,
  sensitivity: 'base',
});

const CorpusWorkRow = ({ work, depth, currentWorkId, externalLoading, onSelect }) => {
  const chunk = work.chunks?.[0];
  const loading = !!chunk && externalLoading === chunk.path;
  const title = work.displayTitle || work.title || work.id;
  const pali = work.displayPali || '';
  return (
    <button
      className={'r-tree__sutra r-tree__sutra--corpus' + (work.id === currentWorkId ? ' is-current' : '')}
      style={{ '--toc-depth': depth }}
      disabled={!chunk || loading}
      onClick={() => chunk && onSelect(work, chunk)}
    >
      <span className="r-tree__sutra-han">{work.publicId || work.id}</span>
      <span className="r-tree__sutra-title">{loading ? '본문을 불러오는 중…' : title}</span>
      {pali && pali !== title && <span className="r-tree__sutra-pali">{pali}</span>}
    </button>
  );
};

const CorpusHierarchyNode = ({
  node, depth, path, volumeId, currentWorkId, externalLoading,
  openNodes, onToggle, onSelect, searchActive,
}) => {
  const nodeKey = [volumeId, ...path, node.id].join(':');
  const hasStoredState = Object.prototype.hasOwnProperty.call(openNodes, nodeKey);
  const containsCurrent = window.CorpusToc.containsWork(node, currentWorkId);
  const expanded = searchActive || (hasStoredState ? openNodes[nodeKey] : containsCurrent);
  const nextPath = [...path, node.id];
  return (
    <div className={'r-corpus-node r-corpus-node--depth-' + depth} style={{ '--toc-depth': depth }}>
      <button
        className="r-corpus-node__head"
        aria-expanded={expanded}
        title={[node.label, node.pali].filter(Boolean).join(' · ')}
        onClick={() => onToggle(nodeKey, expanded)}
      >
        <span className="r-corpus-node__caret"><SbIcon name="caret" size={12}/></span>
        <span className="r-corpus-node__label">{node.label}</span>
        <span className="r-corpus-node__count">{node.count.toLocaleString('ko-KR')}편</span>
        {node.pali && <span className="r-corpus-node__pali">{node.pali}</span>}
      </button>
      {expanded && (
        <div className="r-corpus-node__body">
          {(node.children || []).map(child => (
            <CorpusHierarchyNode
              key={child.id}
              node={child}
              depth={depth + 1}
              path={nextPath}
              volumeId={volumeId}
              currentWorkId={currentWorkId}
              externalLoading={externalLoading}
              openNodes={openNodes}
              onToggle={onToggle}
              onSelect={onSelect}
              searchActive={searchActive}
            />
          ))}
          {(node.works || []).map(work => (
            <CorpusWorkRow
              key={work.id}
              work={work}
              depth={depth + 1}
              currentWorkId={currentWorkId}
              externalLoading={externalLoading}
              onSelect={onSelect}
            />
          ))}
        </div>
      )}
    </div>
  );
};

window.ReaderSidebar = ({
  activeCanonId, onSelectCanon,
  currentPassageId, onSelectPassage, onClose,
  corpusManifest, onSelectCorpusPassage, externalLoading,
  onOpenEncy, onOpenDict,
  bookmarks, highlights,
}) => {
  const canons = [window.CANON_DATA.daisho, window.CANON_DATA.pali, window.CANON_DATA.tibet];
  const canon = window.CANON_DATA[activeCanonId];
  const passage = currentPassageId ? window.PASSAGES[currentPassageId] : null;
  const paliCollection = window.CorpusClient.findCollection(corpusManifest, 'pali');
  const corpusVolumes = paliCollection?.volumes || [];
  const hasExternalPaliToc = activeCanonId === 'pali' && corpusVolumes.length > 0;
  const currentWorkId = passage?.head?.meta?.find(m => m.k === 'WORK')?.v || null;

  const [tab, setTab] = React.useState('toc');

  /* TOC 트리: 현재 본문이 속한 부 자동 펼침 */
  const [openBu, setOpenBu] = React.useState(() => {
    return passage ? { [passage.bu]: true } : (canon.bu[0] ? { [canon.bu[0].id]: true } : {});
  });
  React.useEffect(() => {
    if (passage && passage.canon === activeCanonId) setOpenBu(o => ({ ...o, [passage.bu]: true }));
  }, [currentPassageId, activeCanonId]);
  const toggleBu = (id) => setOpenBu(o => ({ ...o, [id]: !o[id] }));

  /* 외부 빨리 오부니까야 색인은 펼친 니까야만 지연 로드한다. */
  const [openCorpusVolume, setOpenCorpusVolume] = React.useState(
    passage?.canon === 'pali' ? passage.bu : null
  );
  const [corpusIndexes, setCorpusIndexes] = React.useState({});
  const [corpusStatus, setCorpusStatus] = React.useState({});
  const [corpusErrors, setCorpusErrors] = React.useState({});
  const [tocQuery, setTocQuery] = React.useState('');
  const [openCorpusNodes, setOpenCorpusNodes] = React.useState({});

  const ensureCorpusIndex = (volume) => {
    if (!volume || corpusIndexes[volume.id] || corpusStatus[volume.id] === 'loading') return;
    setCorpusStatus(s => ({ ...s, [volume.id]: 'loading' }));
    window.CorpusClient.loadIndex(volume)
      .then(index => {
        setCorpusIndexes(items => ({ ...items, [volume.id]: index }));
        setCorpusStatus(s => ({ ...s, [volume.id]: 'ready' }));
      })
      .catch(error => {
        setCorpusErrors(items => ({ ...items, [volume.id]: error }));
        setCorpusStatus(s => ({ ...s, [volume.id]: 'error' }));
      });
  };

  React.useEffect(() => {
    if (!hasExternalPaliToc) return;
    const passageVolume = passage?.canon === 'pali' ? passage.bu : null;
    const targetId = corpusVolumes.some(v => v.id === passageVolume)
      ? passageVolume
      : (openCorpusVolume || corpusVolumes[0]?.id);
    const target = corpusVolumes.find(v => v.id === targetId);
    if (!target) return;
    if (openCorpusVolume !== target.id) setOpenCorpusVolume(target.id);
    ensureCorpusIndex(target);
  }, [activeCanonId, currentPassageId, corpusManifest]);

  const toggleCorpusVolume = (volume) => {
    const expanding = openCorpusVolume !== volume.id;
    setOpenCorpusVolume(expanding ? volume.id : null);
    setTocQuery('');
    if (expanding) ensureCorpusIndex(volume);
  };

  const toggleCorpusNode = (nodeKey, expanded) => {
    setOpenCorpusNodes(nodes => ({ ...nodes, [nodeKey]: !expanded }));
  };

  /* 관련: 본문에 등장하는 TERM_LINKS 수집 */
  const related = React.useMemo(() => {
    if (!passage) return [];
    const text = passage.paragraphs.map(p => (p.body||'') + ' ' + (p.source||'')).join(' ');
    const out = []; const seen = new Set();
    for (const k of Object.keys(window.TERM_LINKS)) {
      if (text.includes(k)) {
        const link = window.TERM_LINKS[k];
        const sig = (link.dict||'') + '|' + (link.ency||'');
        if (seen.has(sig)) continue;
        seen.add(sig);
        const dict = link.dict ? window.DICT_ENTRIES.find(d => d.id===link.dict) : null;
        const ency = link.ency ? window.ENCY_ENTRIES[link.ency] : null;
        if (dict || ency) out.push({ term:k, dict, ency, label: link.label });
      }
    }
    return out;
  }, [currentPassageId]);

  return (
    <aside className="r-sidebar">
      <div className="r-sidebar__head">
        <div className="r-sidebar__title">경전 · 목차</div>
        <div className="r-sidebar__sub">{canon.title} · {canon.titleHan}</div>
      </div>

      <nav className="r-canon-tabs" aria-label="대장경 선택">
        {canons.map(c => (
          <button
            key={c.id}
            className={'r-canon-tab' + (c.id === activeCanonId ? ' is-active' : '')}
            style={{ '--c': c.color }}
            onClick={() => onSelectCanon(c.id)}
          >
            <span className="han">{c.titleHan.slice(0, 2)}</span>
            <span>{c.title.split(' ')[0]}</span>
          </button>
        ))}
      </nav>

      {/* 사이드바 탭 */}
      <div className="r-sidebar-tabs">
        <button className={'r-sidebar-tab'+(tab==='toc'?' is-active':'')} onClick={()=>setTab('toc')}>
          <SbIcon name="list" size={14}/><span>목차</span>
        </button>
        <button className={'r-sidebar-tab'+(tab==='related'?' is-active':'')} onClick={()=>setTab('related')}>
          <SbIcon name="related" size={14}/><span>관련<i>{related.length}</i></span>
        </button>
        <button className={'r-sidebar-tab'+(tab==='sources'?' is-active':'')} onClick={()=>setTab('sources')}>
          <SbIcon name="source" size={14}/><span>출처</span>
        </button>
        <button className={'r-sidebar-tab'+(tab==='notes'?' is-active':'')} onClick={()=>setTab('notes')}>
          <SbIcon name="note" size={14}/><span>메모<i>{(bookmarks?.length||0)+(highlights?.length||0)}</i></span>
        </button>
      </div>

      {/* 탭 콘텐츠 */}
      {tab === 'toc' && (
        <div className="r-tree">
          {hasExternalPaliToc ? corpusVolumes.map(volume => {
            const expanded = openCorpusVolume === volume.id;
            const index = corpusIndexes[volume.id];
            const query = tocQuery.trim().toLocaleLowerCase('ko');
            const works = [...(index?.works || [])].sort((a, b) => {
              const byId = NATURAL_TOC_COLLATOR.compare(String(a.id || ''), String(b.id || ''));
              return byId || NATURAL_TOC_COLLATOR.compare(String(a.title || ''), String(b.title || ''));
            });
            const hierarchy = window.CorpusToc.build(volume.id, works);
            const visibleHierarchy = window.CorpusToc.filter(hierarchy, query);
            const visibleCount = visibleHierarchy.reduce((sum, node) => sum + node.count, 0);
            const color = PALI_VOLUME_COLORS[volume.id] || canon.color;
            return (
              <div className="r-tree__group" key={volume.id} style={{ '--bu': color }}>
                <button
                  className="r-tree__bu"
                  aria-expanded={expanded}
                  onClick={() => toggleCorpusVolume(volume)}
                >
                  <span className="r-tree__bu-dot" />
                  <span className="r-tree__bu-han">{volume.han}</span>
                  <span className="r-tree__bu-name">{volume.name}</span>
                  <span className="r-tree__bu-count">{Number(volume.workCount || 0).toLocaleString('ko-KR')}편</span>
                  <span className="r-tree__bu-caret"><SbIcon name="caret" size={14}/></span>
                </button>

                {expanded && (
                  <div className="r-tree__sutras">
                    <div className="r-corpus-filter">
                      <input
                        type="search"
                        value={tocQuery}
                        onChange={e => setTocQuery(e.target.value)}
                        placeholder={`${volume.name} 제목·번호 검색`}
                        aria-label={`${volume.name} 목차 검색`}
                      />
                      {index && (
                        <span>{query ? `${visibleCount.toLocaleString('ko-KR')}편 검색됨` : `${works.length.toLocaleString('ko-KR')}편 전체 · 묶음을 열어 찾아보세요`}</span>
                      )}
                    </div>

                    {corpusStatus[volume.id] === 'loading' && (
                      <div className="r-corpus-state">목차를 불러오는 중입니다…</div>
                    )}
                    {corpusStatus[volume.id] === 'error' && (
                      <div className="r-corpus-state r-corpus-state--error">
                        목차를 불러오지 못했습니다. {corpusErrors[volume.id]?.message || ''}
                      </div>
                    )}
                    {index && visibleHierarchy.map(node => (
                      <CorpusHierarchyNode
                        key={node.id}
                        node={node}
                        depth={0}
                        path={[]}
                        volumeId={volume.id}
                        currentWorkId={currentWorkId}
                        externalLoading={externalLoading}
                        openNodes={openCorpusNodes}
                        onToggle={toggleCorpusNode}
                        searchActive={!!query}
                        onSelect={async (work, chunk) => {
                          await onSelectCorpusPassage({
                            ...chunk,
                            volumeId: volume.id,
                            workId: work.id,
                            workTitle: work.displayTitle || work.title,
                            workTitlePali: work.displayPali || work.titlePali,
                          });
                          onClose && onClose();
                        }}
                      />
                    ))}
                    {index && visibleCount === 0 && (
                      <div className="r-corpus-state">검색 결과가 없습니다.</div>
                    )}
                  </div>
                )}
              </div>
            );
          }) : canon.bu.map(bu => {
            const expanded = !!openBu[bu.id];
            return (
              <div className="r-tree__group" key={bu.id} style={{ '--bu': bu.color }}>
                <button
                  className="r-tree__bu"
                  aria-expanded={expanded}
                  onClick={() => toggleBu(bu.id)}
                >
                  <span className="r-tree__bu-dot" />
                  <span className="r-tree__bu-han">{bu.han}</span>
                  <span>{bu.name}</span>
                  <span className="r-tree__bu-caret"><SbIcon name="caret" size={14}/></span>
                </button>
                {expanded && (
                  <div className="r-tree__sutras">
                    {(bu.sutras || []).length === 0 && (
                      <div style={{padding:'8px 16px 8px 36px',fontSize:12,color:'var(--ink-dim)',fontStyle:'italic'}}>
                        준비 중 — 다음 결집 단계
                      </div>
                    )}
                    {(bu.sutras || []).map(s => {
                      const chapters = s.chapters || [];
                      if (chapters.length === 0) {
                        return (
                          <div key={s.id} className="r-tree__sutra" style={{opacity:0.55, cursor:'default'}}>
                            <span className="r-tree__sutra-han">{s.han}</span>
                            <span>{s.name} · {s.volumes}권</span>
                          </div>
                        );
                      }
                      return chapters.map(ch => (
                        <button
                          key={ch.id}
                          className={'r-tree__sutra' + (ch.id === currentPassageId ? ' is-current' : '')}
                          onClick={() => { onSelectPassage(ch.id); onClose && onClose(); }}
                        >
                          <span className="r-tree__sutra-han">{s.han} · {ch.vol}</span>
                          <span>{ch.name}</span>
                        </button>
                      ));
                    })}
                  </div>
                )}
              </div>
            );
          })}
          <div style={{height:80}} />
        </div>
      )}

      {tab === 'related' && (
        <div className="r-side-list">
          {related.length === 0 && (
            <div className="r-side-list__empty">이 본문에서 자동 수집된 관련 항목이 없습니다.</div>
          )}
          {related.map(r => (
            <button key={r.term} className="r-side-item"
              onClick={() => r.ency ? onOpenEncy(r.ency.id) : onOpenDict(r.dict.id)}>
              <div className="r-side-item__main">
                {r.ency ? (
                  <>
                    <span className="han">{r.ency.head.han}</span>
                    <span>{r.ency.head.kr}</span>
                  </>
                ) : (
                  <>
                    <span className="han">{r.dict.han}</span>
                    <span>{r.dict.kr}</span>
                  </>
                )}
              </div>
              <span className="r-side-item__kind">
                {r.ency ? ({concept:'개념',person:'인물',text:'문헌',school:'종파'})[r.ency.type] : '사전'}
              </span>
            </button>
          ))}
        </div>
      )}

      {tab === 'sources' && (
        <div className="r-side-list">
          <div className="r-side-list__head">본문 각주</div>
          {(passage?.footnotes || []).map(fn => (
            <button key={fn.n} className="r-side-item"
              onClick={() => {
                const el = document.getElementById('fn-'+fn.n);
                if (el) el.scrollIntoView({block:'center'});
                onClose && onClose();
              }}>
              <div className="r-side-item__main">
                <span className="r-side-item__num">{fn.n}</span>
                <span>{fn.key}</span>
              </div>
            </button>
          ))}
          <div className="r-side-list__head">서지</div>
          <div className="r-side-item r-side-item--info">
            <div className="r-side-item__main"><span>{passage?.location.canonLabel}</span></div>
            <span className="r-side-item__kind">대장경</span>
          </div>
          <div className="r-side-item r-side-item--info">
            <div className="r-side-item__main"><span>{passage?.head.meta[1]?.v || '-'}</span></div>
            <span className="r-side-item__kind">번역</span>
          </div>
        </div>
      )}

      {tab === 'notes' && (
        <div className="r-side-list">
          <div className="r-side-list__head">북마크</div>
          {(bookmarks || []).length === 0 && (
            <div className="r-side-list__empty">아직 저장한 북마크가 없습니다.</div>
          )}
          {(bookmarks || []).map((b, i) => (
            <button key={i} className="r-side-item"
              onClick={() => { onSelectPassage(b.passageId); onClose && onClose(); }}>
              <div className="r-side-item__main">
                <span>{b.loc}</span>
                <span className="r-side-item__excerpt">{b.excerpt}</span>
              </div>
              <span className="r-side-item__kind">{b.time}</span>
            </button>
          ))}
          <div className="r-side-list__head">하이라이트</div>
          {(highlights || []).length === 0 && (
            <div className="r-side-list__empty">드래그로 본문을 선택해 표시할 수 있습니다.</div>
          )}
        </div>
      )}
    </aside>
  );
};
