"""
知识库 API — 上传 / 列表 / 删除 / 来源筛选 / 语义搜索
"""

from typing import Optional
from pydantic import BaseModel

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Query, status
from sqlmodel import Session

from app.core.deps import get_current_user, require_role
from app.db.session import get_session
from app.models.user import User, UserRole
from app.services.knowledge_service import KnowledgeService


router = APIRouter(prefix="/api/knowledge", tags=["知识库"])


@router.post("/upload")
async def upload_md_files(
    files: list[UploadFile] = File(...),
    session: Session = Depends(get_session),
    current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian)),
):
    """
    上传单个或多个 .md 文件，解析 frontmatter，写入知识库（含向量）。
    仅制片人/责编可用。
    """
    svc = KnowledgeService()
    results = []
    errors = []

    for f in files:
        if not f.filename.endswith(".md"):
            errors.append({"file": f.filename, "error": "仅支持 .md 文件"})
            continue
        try:
            content = await f.read()
            item = svc.store_md_file(content, f.filename)
            results.append({
                "id": item.id,
                "title": item.title,
                "source_type": item.source_type,
            })
        except Exception as e:
            errors.append({"file": f.filename, "error": str(e)})

    return {"uploaded": results, "errors": errors}


@router.get("/items")
def list_knowledge_items(
    source_type: Optional[str] = Query(None),
    session: Session = Depends(get_session),
    current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian, UserRole.biandao)),
):
    """
    知识库列表，支持按 source_type 筛选。三角色均可读。
    """
    svc = KnowledgeService()
    items = svc.list_items(source_type=source_type)
    return items


@router.delete("/items/{item_id}")
def delete_knowledge_item(
    item_id: int,
    session: Session = Depends(get_session),
    current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian)),
):
    """
    删除知识库条目（级联删除向量）。仅制片人/责编可用。
    """
    svc = KnowledgeService()
    deleted = svc.delete_item(item_id)
    if not deleted:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="条目不存在")
    return {"message": "删除成功"}


@router.get("/sources")
def list_distinct_sources(
    session: Session = Depends(get_session),
    current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian, UserRole.biandao)),
):
    """
    返回库里所有不重复的具体出处（source_detail），供来源筛选下拉动态生成。
    三角色均可读。
    """
    svc = KnowledgeService()
    sources = svc.get_distinct_sources()
    return [{"source": s} for s in sources]


@router.get("/grouped")
def get_grouped_knowledge_items(
    session: Session = Depends(get_session),
    current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian, UserRole.biandao)),
):
    """
    返回按 source_type → source_detail 两层聚合的树形结构，
    含「全部」根节点，供知识库树形导航使用。
    三角色均可读。
    """
    svc = KnowledgeService()
    return svc.get_grouped_items()


class SearchRequest(BaseModel):
    query: str
    top_k: int = 5


@router.post("/search")
def search_knowledge(
    body: SearchRequest,
    session: Session = Depends(get_session),
    current_user: User = Depends(require_role(UserRole.zhipianren, UserRole.zebian, UserRole.biandao)),
):
    """
    语义检索：输入一段文字，返回最相关的知识库条目及相似度。
    查询向量用 type="query"（区分于存入时的 type="db"）。
    三角色均可读。
    """
    svc = KnowledgeService()
    results = svc.search_similar(query_text=body.query, top_k=body.top_k)
    return {
        "results": results,
        "query": body.query,
        "count": len(results),
    }
