'use client';

export const runtime = 'edge';

// Mira 搜尋頁 — 大眾化語義入口（leo 2026-07-05 拍板）
//   default = 語義搜尋（普通用戶記大概意思；語義 normalize：黃仁勳＝皮衣男＝Jensen Huang 歸一）
//   進階     = 關鍵字（懂的人用）
// 後端：self-hosted leo21c KBDB（新 ingest 產 triplet/gloss entry，非舊 index-entry blocks）。
//   過渡期直連 kbdb raw worker（cypher-proxy /kbdb/entries 尚未補，見 mira §1.7）。
//   舊後端 kbdb.finally.click 已移除（mira 鐵律：禁直打舊 SaaS KBDB 當主儲存）。
// graph 遍歷之後再補（本次不做）。

import { Suspense, useCallback, useEffect, useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import Link from 'next/link';
import '../mira.css';

// 新 KBDB（self-hosted leo21c）。過渡期直連 raw worker（無 auth、單租戶），
// 不帶 owner_id（Vectorize owner metadata index 未建，帶了會回 0；總管另修）。
const KBDB_BASE = 'https://arcrun-kbdb.leo21c.workers.dev';
// 登入 gate 仍走官方 cypher（session cookie 綁 arcrun.dev；leo21c 對應 URL 未定 → 保留原樣，見回報）。
const API_BASE = process.env.NEXT_PUBLIC_API_BASE ?? 'https://cypher.arcrun.dev';

type SearchMode = 'semantic' | 'keyword';

// KBDB /entries/search 回傳的 entry（gloss：content = "實體：描述"）
type SearchEntry = {
  id: string;
  content: string;
  entry_type?: string;
  owner_id?: string;
  score?: number;
};

type SearchResponse = {
  entries?: SearchEntry[];
  mode?: string;             // 實際採用的 mode（semantic 未開會誠實降級 keyword）
  capability_hint?: string;  // 降級時的提示
};

// 繁體異體字正規化（臺→台），讓 query 對得上多用「台」的 KB 內容
function normalizeQuery(q: string): string {
  return q.replace(/臺/g, '台');
}

// gloss content「實體：描述」→ { title, desc }（無冒號則整串當標題）
function splitGloss(content: string): { title: string; desc: string } {
  const m = content.match(/^\s*([^：:]+)[：:]\s*([\s\S]*)$/);
  if (m) return { title: m[1].trim(), desc: m[2].trim() };
  return { title: content.trim(), desc: '' };
}

function SearchInner() {
  const router = useRouter();
  const params = useSearchParams();
  const initialQ = params.get('q') ?? '';

  const [ready, setReady] = useState(false); // 登入檢查完成
  const [input, setInput] = useState(initialQ);
  const [mode, setMode] = useState<SearchMode>('semantic');
  const [results, setResults] = useState<SearchEntry[] | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [hint, setHint] = useState<string | null>(null);

  // 登入 gate（沿用官方 cypher /me；只確認登入，不需 api_key——raw worker 無 auth）
  useEffect(() => {
    (async () => {
      try {
        const meRes = await fetch(`${API_BASE}/me`, { credentials: 'include' });
        if (!meRes.ok) { window.location.href = '/login?redirect=/mira/search'; return; }
        setReady(true);
      } catch (e) {
        setError(e instanceof Error ? e.message : String(e));
      }
    })();
  }, []);

  // 語義/關鍵字搜尋：GET {KBDB_BASE}/entries/search?q=&mode=&limit=12（不帶 owner_id）
  const runSearch = useCallback(async (rawQuery: string, m: SearchMode) => {
    const q = normalizeQuery(rawQuery.trim());
    if (!q) { setResults(null); setHint(null); return; }
    setLoading(true);
    setError(null);
    setHint(null);
    try {
      const url = `${KBDB_BASE}/entries/search?q=${encodeURIComponent(q)}&mode=${m}&limit=12`;
      const res = await fetch(url);
      if (!res.ok) { setError(`搜尋失敗：${res.status}`); setResults([]); return; }
      const data = (await res.json()) as SearchResponse;
      const entries = (data.entries ?? [])
        .slice()
        .sort((a, b) => (b.score ?? 0) - (a.score ?? 0)); // 語義無門檻，照 score 排序顯示前 N
      setResults(entries);
      // 誠實降級提示：要了 semantic 卻回 keyword（Vectorize 未開）
      if (m === 'semantic' && data.mode && data.mode !== 'semantic') {
        setHint(data.capability_hint ?? '語義索引尚未啟用，暫以關鍵字比對代替。');
      }
    } catch (e) {
      setError(e instanceof Error ? e.message : String(e));
      setResults([]);
    } finally {
      setLoading(false);
    }
  }, []);

  // 進站帶 ?q= 且登入完成 → 自動查一次
  useEffect(() => {
    if (ready && initialQ.trim()) runSearch(initialQ, mode);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ready]);

  const submit = (e: React.FormEvent) => {
    e.preventDefault();
    const q = input.trim();
    router.replace(`/mira/search?q=${encodeURIComponent(q)}`);
    runSearch(q, mode);
  };

  // 切換 default 語義／進階 keyword；已有 query 就重查
  const switchMode = (m: SearchMode) => {
    if (m === mode) return;
    setMode(m);
    if (input.trim()) runSearch(input, m);
  };

  return (
    <main className="mira-page">
      <div className="mira-content">
        <header style={{ padding: '24px 0 8px' }}>
          <Link href="/mira/feed" style={{ color: '#888', fontSize: 14, textDecoration: 'none' }}>← 河道</Link>
          <h1 style={{ fontSize: 26, fontWeight: 700, color: '#fff', margin: '8px 0 0' }}>🔍 搜尋</h1>
          <p style={{ color: '#888', fontSize: 12, marginTop: 4 }}>
            會打字就能查——{mode === 'semantic' ? '語義搜尋（記大概意思即可）' : '關鍵字精確比對'}
          </p>
        </header>

        <form className="mira-search-form" onSubmit={submit}>
          <input
            className="mira-search-input"
            value={input}
            onChange={e => setInput(e.target.value)}
            placeholder={mode === 'semantic' ? '想找什麼？（例：那個穿皮衣的 AI 老闆、本地模型）' : '關鍵字（精確比對）'}
            autoFocus
          />
          <button type="submit" className="mira-btn-primary" disabled={!ready}>搜尋</button>
        </form>

        {/* default 語義／進階 keyword 切換 */}
        <div className="mira-search-mode" style={{ display: 'flex', gap: 8, marginTop: 10, fontSize: 13 }}>
          <button
            type="button"
            onClick={() => switchMode('semantic')}
            className={mode === 'semantic' ? 'mira-btn-primary' : 'mira-search-vec-toggle'}
            style={{ padding: '4px 12px' }}
          >語義（推薦）</button>
          <button
            type="button"
            onClick={() => switchMode('keyword')}
            className={mode === 'keyword' ? 'mira-btn-primary' : 'mira-search-vec-toggle'}
            style={{ padding: '4px 12px' }}
          >進階：關鍵字</button>
        </div>

        {error && <div className="mira-error" style={{ marginTop: 12 }}>{error}</div>}
        {hint && <div className="empty-state" style={{ padding: '10px 0', color: 'var(--mira-text-3)' }}>ℹ️ {hint}</div>}

        {loading && <div className="empty-state" style={{ padding: '16px 0' }}>搜尋中…</div>}

        {!loading && results && (
          <section style={{ marginTop: 14 }}>
            <div className="mira-search-section-head">
              {mode === 'semantic' ? '🧬 語義結果' : '📇 關鍵字結果'}（{results.length}）
            </div>
            {results.length === 0 ? (
              <div className="empty-state" style={{ padding: '16px 0' }}>沒有找到相關結果，換個說法試試。</div>
            ) : (
              results.map(e => <ResultRow key={e.id} entry={e} />)
            )}
          </section>
        )}
      </div>
    </main>
  );
}

function ResultRow({ entry }: { entry: SearchEntry }) {
  const { title, desc } = splitGloss(entry.content || '');
  const pct = entry.score != null ? Math.round(entry.score * 100) : null;
  return (
    <div className="mira-search-result">
      <div className="mira-search-result-meta">
        <span>📚 {title}</span>
        {pct != null && pct > 0 && <span className="mira-search-score">{pct}%</span>}
      </div>
      {desc && <div className="mira-search-snippet">{desc}</div>}
    </div>
  );
}

export default function MiraSearchPage() {
  return (
    <Suspense fallback={<div className="empty-state">載入中…</div>}>
      <SearchInner />
    </Suspense>
  );
}
