const { useMemo, useRef, useState } = React;

const STAR = {
  exact: '⭐⭐⭐',
  tone_diff: '⭐⭐',
  near_sound: '⭐',
};

function matchLabel(level) {
  return STAR[level] || '⭐';
}

function makeMarkdown(text, segments) {
  const anchors = segments.filter((s) => s.is_anchor);
  const lines = [`# 文字雷達：${text}`, ''];

  for (const s of anchors) {
    lines.push(`## ${s.word}`);
    lines.push('### 🔊 諧音路徑');
    if (!s.homophones?.length) {
      lines.push('- （無）');
    } else {
      lines.push(`- ${s.word} ${s.pinyin}`);
      for (const h of s.homophones) {
        const dist = h.semantic_distance ? ` / 語義:${h.semantic_distance}` : '';
        lines.push(`  - ${h.word} ${h.pinyin} ${matchLabel(h.match_level)}${dist}`);
      }
    }

    lines.push('');
    lines.push('### 📖 成語碰撞');
    if (!s.idiom_hits?.length) {
      lines.push('- （無）');
    } else {
      for (const i of s.idiom_hits) {
        lines.push(`- **${i.matched_char}** → ${i.idiom}${i.explanation ? `：${i.explanation}` : ''}`);
      }
    }

    lines.push('');
    lines.push('### 🔪 拆字');
    if (!s.char_split?.length) {
      lines.push('- （無）');
    } else {
      for (const c of s.char_split) {
        lines.push(`- ${c.char} → ${(c.homophones || []).join('、') || '（無）'}`);
      }
    }
    lines.push('');
    lines.push('---');
    lines.push('');
  }

  return lines.join('\n');
}

function App() {
  const [text, setText] = useState('我在矽谷找工作，投了五十封履歷，結果只有三家回');
  const [matchLevel, setMatchLevel] = useState('tone_ignored');
  const [minFrequency, setMinFrequency] = useState(500);
  const [maxHomophones, setMaxHomophones] = useState(10);
  const [result, setResult] = useState(null);
  const [selected, setSelected] = useState(null);
  const [showAllIdioms, setShowAllIdioms] = useState(false);
  const [scanning, setScanning] = useState(false);
  const rightPanelRef = useRef(null);

  const segments = result?.segments || [];
  const anchors = useMemo(() => segments.filter((s) => s.is_anchor), [segments]);

  function selectAnchor(seg) {
    setSelected(seg);
    setShowAllIdioms(false);
    if (rightPanelRef.current) {
      rightPanelRef.current.scrollTop = 0;
    }
  }

  async function runScan() {
    setScanning(true);
    try {
      const resp = await fetch('/api/scan', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          text,
          config: {
            match_level: matchLevel,
            min_frequency: Number(minFrequency),
            max_homophones: Number(maxHomophones),
            include_idioms: true,
            include_split: true,
          },
        }),
      });
      const data = await resp.json();
      setResult(data);
      const first = data.segments.find((s) => s.is_anchor);
      selectAnchor(first || null);
    } finally {
      setScanning(false);
    }
  }

  function renderTextWithAnchors() {
    if (!segments.length) return <span className="small">先輸入文字並按「掃描」。</span>;

    const nodes = [];
    let cursor = 0;

    segments.forEach((seg, i) => {
      const [start, end] = seg.position;
      if (start > cursor) {
        nodes.push(<span key={`t-${i}`}>{text.slice(cursor, start)}</span>);
      }
      const content = text.slice(start, end);

      if (seg.is_anchor) {
        const active = selected?.position?.[0] === start && selected?.position?.[1] === end;
        nodes.push(
          <span
            key={`a-${i}`}
            className={`anchor ${active ? 'active' : ''}`}
            onClick={() => selectAnchor(seg)}
            title={`POS: ${seg.pos || '-'}`}
          >
            {content}
          </span>
        );
      } else {
        nodes.push(<span key={`n-${i}`}>{content}</span>);
      }
      cursor = end;
    });

    if (cursor < text.length) {
      nodes.push(<span key="tail">{text.slice(cursor)}</span>);
    }

    return nodes;
  }

  async function exportMarkdown() {
    if (!segments.length) return;
    const md = makeMarkdown(text, segments);
    await navigator.clipboard.writeText(md);
    alert('已複製 Markdown（可直接貼到 Obsidian）');
  }

  const groupedHomophones = useMemo(() => {
    if (!selected?.homophones) return [];
    const groups = [
      { level: 'exact', label: '⭐⭐⭐ 完全同音' },
      { level: 'tone_diff', label: '⭐⭐ 同音異調' },
      { level: 'near_sound', label: '⭐ 近音' },
    ];
    return groups
      .map((g) => ({ ...g, items: selected.homophones.filter((h) => h.match_level === g.level) }))
      .filter((g) => g.items.length > 0);
  }, [selected]);

  const idiomList = useMemo(() => {
    const list = selected?.idiom_hits || [];
    return showAllIdioms ? list : list.slice(0, 5);
  }, [selected, showAllIdioms]);

  return (
    <div className="wrap">
      <div className="toolbar">
        <textarea value={text} onChange={(e) => setText(e.target.value)} />
        <select value={matchLevel} onChange={(e) => setMatchLevel(e.target.value)}>
          <option value="exact">exact</option>
          <option value="tone_ignored">tone_ignored</option>
          <option value="near_sound">near_sound</option>
        </select>
        <input type="number" value={minFrequency} onChange={(e) => setMinFrequency(e.target.value)} title="min_frequency" />
        <input type="number" value={maxHomophones} onChange={(e) => setMaxHomophones(e.target.value)} title="max_homophones" />
        <button className="btn-primary" onClick={runScan} disabled={scanning}>{scanning ? '掃描中...' : '掃描'}</button>
        <button className="btn-secondary" onClick={exportMarkdown}>匯出 Markdown（複製）</button>
      </div>

      <div className="layout">
        <div className="panel">
          <p className="title">原文（可點擊 anchor）</p>
          <div className="article">{renderTextWithAnchors()}</div>
          <div style={{ marginTop: 16 }}>
            {anchors.map((a, idx) => (
              <span
                key={`${a.word}-${idx}`}
                className={`chip ${selected?.position?.[0] === a.position[0] ? 'active' : ''}`}
                onClick={() => selectAnchor(a)}
              >
                {a.word}
              </span>
            ))}
          </div>
          {result?.meta && <div className="small">words: {result.meta.total_words} / anchors: {result.meta.anchors_found}</div>}
        </div>

        <div className="panel" ref={rightPanelRef}>
          <p className="title">發散樹{selected ? `：${selected.word}` : ''}</p>
          {!selected ? (
            <div className="small">尚未選擇 anchor。</div>
          ) : (
            <>
              <div className="block">
                <h4>🔊 諧音路徑</h4>
                {groupedHomophones.length === 0 && <div className="small">（無）</div>}
                {groupedHomophones.map((g) => (
                  <div key={g.level} style={{ marginBottom: 10 }}>
                    <div className="small" style={{ marginBottom: 6 }}>{g.label}</div>
                    {g.items.map((h, idx) => (
                      <div className="line" key={`${g.level}-${h.word}-${idx}`}>
                        <span className={h.semantic_distance === 'far' ? 'far' : 'near'}>{h.word}</span>
                        <span className="mono"> {h.pinyin}</span>
                        <span className="small"> {matchLabel(h.match_level)} / {h.semantic_distance || 'near'}</span>
                      </div>
                    ))}
                  </div>
                ))}
              </div>

              <div className="block">
                <h4>📖 成語碰撞</h4>
                {(selected.idiom_hits || []).length === 0 && <div className="small">（無）</div>}
                {idiomList.map((i, idx) => (
                  <div className="line" key={`${i.idiom}-${idx}`}>
                    <strong>{i.idiom}</strong>
                    <span className="small">（命中：{i.matched_char}）</span>
                    {i.explanation ? <div className="small">{i.explanation}</div> : null}
                  </div>
                ))}
                {(selected.idiom_hits || []).length > 5 && (
                  <button className="btn-secondary" onClick={() => setShowAllIdioms((v) => !v)}>
                    {showAllIdioms ? '顯示較少' : '顯示更多'}
                  </button>
                )}
              </div>

              <div className="block">
                <h4>🔪 拆字</h4>
                {(selected.char_split || []).length === 0 && <div className="small">（無）</div>}
                {(selected.char_split || []).map((c, idx) => (
                  <div className="line" key={`${c.char}-${idx}`}>
                    <strong>{c.char}</strong>
                    <span className="small"> → {(c.homophones || []).join(' / ') || '（無）'}</span>
                  </div>
                ))}
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

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