"""
Knowledge Base API Router
==========================
Knowledge Base Phase 1: REST API

端點: /api/v1/knowledge

建立時間: 2026-04-02 (台北時區)
建立者: Claude Code (Knowledge Base Phase 1)

遵循 leWOOOgo 積木化原則:
- Router 層只做 HTTP 轉發
- 業務邏輯在 Service 層
- 禁止直接存取 DB/Redis
"""

import structlog
from fastapi import APIRouter, HTTPException, Query

from src.models.knowledge import (
    EntryStatus,
    EntryType,
    KnowledgeEntry,
    KnowledgeEntryCreate,
    KnowledgeEntryUpdate,
    KnowledgeListResponse,
)
from src.services.knowledge_service import get_knowledge_service

logger = structlog.get_logger(__name__)

router = APIRouter(prefix="/knowledge", tags=["Knowledge Base"])


# =============================================================================
# Endpoints
# =============================================================================

@router.get("", response_model=KnowledgeListResponse)
async def list_entries(
    category: str | None = Query(None, description="篩選分類"),
    entry_type: EntryType | None = Query(None, description="篩選類型"),
    status: EntryStatus | None = Query(None, description="篩選狀態"),
    q: str | None = Query(None, description="關鍵字搜尋"),
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
) -> KnowledgeListResponse:
    """列出知識條目"""
    service = get_knowledge_service()
    return await service.list_entries(
        category=category,
        entry_type=entry_type,
        status=status,
        q=q,
        limit=limit,
        offset=offset,
    )


@router.get("/search", response_model=list[KnowledgeEntry])
async def search_entries(
    q: str = Query(..., min_length=1, description="搜尋關鍵字"),
    limit: int = Query(20, ge=1, le=100),
) -> list[KnowledgeEntry]:
    """關鍵字搜尋 (title + content + tags)"""
    service = get_knowledge_service()
    return await service.search(q, limit)


@router.get("/semantic-search")
async def semantic_search(
    q: str = Query(..., min_length=1, description="語意搜尋查詢"),
    limit: int = Query(10, ge=1, le=50),
    threshold: float = Query(0.5, ge=0.0, le=1.0, description="相似度門檻 (0-1)"),
) -> list[dict]:
    """
    語意搜尋 (pgvector cosine similarity)

    使用 nomic-embed-text 向量模型，回傳含相似度分數的結果。
    """
    service = get_knowledge_service()
    results = await service.semantic_search(q, limit=limit, threshold=threshold)
    return [
        {**entry.model_dump(), "score": round(score, 4)}
        for entry, score in results
    ]


@router.post("/embed-all", status_code=200)
async def embed_all_entries() -> dict:
    """
    管理端點: 批次為所有未 embed 的條目產生 embedding

    Returns: {"total": N, "success": N, "failed": N}
    """
    service = get_knowledge_service()
    return await service.embed_all_entries()


@router.get("/categories")
async def get_categories() -> list[dict]:
    """取得分類樹 (含各類數量)"""
    service = get_knowledge_service()
    cats = await service.get_categories()
    return [cat.model_dump() for cat in cats]


@router.get("/{entry_id}", response_model=KnowledgeEntry)
async def get_entry(entry_id: str) -> KnowledgeEntry:
    """取得單筆知識條目 (view_count +1)"""
    service = get_knowledge_service()
    entry = await service.get_entry(entry_id)
    if not entry:
        raise HTTPException(status_code=404, detail="Knowledge entry not found")
    return entry


@router.post("", response_model=KnowledgeEntry, status_code=201)
async def create_entry(data: KnowledgeEntryCreate) -> KnowledgeEntry:
    """建立新知識條目"""
    service = get_knowledge_service()
    return await service.create_entry(data)


@router.patch("/{entry_id}", response_model=KnowledgeEntry)
async def update_entry(
    entry_id: str,
    data: KnowledgeEntryUpdate,
) -> KnowledgeEntry:
    """更新知識條目"""
    service = get_knowledge_service()
    entry = await service.update_entry(entry_id, data)
    if not entry:
        raise HTTPException(status_code=404, detail="Knowledge entry not found")
    return entry


@router.post("/{entry_id}/approve", response_model=KnowledgeEntry)
async def approve_entry(entry_id: str) -> KnowledgeEntry:
    """審核通過"""
    service = get_knowledge_service()
    entry = await service.approve_entry(entry_id)
    if not entry:
        raise HTTPException(status_code=404, detail="Knowledge entry not found")
    return entry


@router.delete("/{entry_id}", status_code=204)
async def archive_entry(entry_id: str) -> None:
    """封存知識條目 (軟刪除)"""
    service = get_knowledge_service()
    success = await service.archive_entry(entry_id)
    if not success:
        raise HTTPException(status_code=404, detail="Knowledge entry not found")


# =============================================================================
# Phase 33 (ADR-067 2026-04-10): RAG pgvector 端點
# =============================================================================

@router.post("/rag/index", status_code=200)
async def rag_index_document(body: dict) -> dict:
    """
    索引文件到 RAG 知識庫 (pgvector rag_chunks 表)

    body: {source, source_id, title, text, metadata?}
    """
    from src.services.knowledge_rag_service import get_knowledge_rag_service
    svc = get_knowledge_rag_service()
    ok = await svc.index_document(
        source=body.get("source", "manual"),
        source_id=body.get("source_id", ""),
        title=body.get("title", ""),
        text=body.get("text", ""),
        metadata=body.get("metadata", {}),
    )
    return {"ok": ok, "title": body.get("title", "")}


@router.get("/rag/query")
async def rag_query(
    q: str = Query(..., min_length=1, description="RAG 查詢問題"),
    top_k: int = Query(5, ge=1, le=20),
) -> dict:
    """
    RAG 查詢 — embedding → pgvector knn → 生成繁中回答
    """
    from src.services.knowledge_rag_service import get_knowledge_rag_service
    svc = get_knowledge_rag_service()
    answer = await svc.query(q, top_k=top_k)
    return {"question": q, "answer": answer}


@router.get("/rag/stats")
async def rag_stats() -> dict:
    """RAG 知識庫統計"""
    from src.services.knowledge_rag_service import get_knowledge_rag_service
    svc = get_knowledge_rag_service()
    return await svc.get_stats()
