"""管理端知识中心接口。

接口顺序对应管理页面的发布流程：创建/上传、建立索引、检索测试、正式发布。
权限在每个接口再次校验，不能只依赖前端隐藏按钮。
"""

from typing import Annotated, Any, Literal

from fastapi import APIRouter, Depends, File, Form, Request, UploadFile
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from pydantic import BaseModel, Field

from zbt.api.responses import success_response
from zbt.core.errors import AppError
from zbt.domains.identity.models import AdminUser
from zbt.domains.identity.service import AdminAuthService
from zbt.domains.knowledge.service import KnowledgeService
from zbt.infrastructure.documents.parser import extract_document_text

admin_knowledge_bearer = HTTPBearer(auto_error=False)


class KnowledgeDocumentCreateRequest(BaseModel):
    title: str = Field(min_length=2, max_length=200)
    document_type: Literal["INSURANCE_TERMS", "PRODUCT_GUIDE", "SERVICE_RULES", "FAQ"]
    source_name: str = Field(min_length=1, max_length=255)
    product_code: str | None = Field(default=None, max_length=64)
    content: str = Field(min_length=10, max_length=2_000_000)


class KnowledgeSearchTestRequest(BaseModel):
    query: str = Field(min_length=2, max_length=500)
    limit: int = Field(default=5, ge=1, le=10)


def create_admin_knowledge_router(
    service: KnowledgeService,
    auth_service: AdminAuthService,
) -> APIRouter:
    """创建知识中心路由，并注入知识服务与后台认证服务。"""

    router = APIRouter(tags=["admin-knowledge"])

    def current_admin(
        credentials: Annotated[
            HTTPAuthorizationCredentials | None,
            Depends(admin_knowledge_bearer),
        ],
    ) -> AdminUser:
        if credentials is None:
            raise AppError("AUTH_REQUIRED", "请先登录后台", 401)
        return auth_service.authenticate_access(credentials.credentials)

    def require_permission(user: AdminUser, permission: str) -> None:
        if "*" not in user.permissions and permission not in user.permissions:
            raise AppError("PERMISSION_DENIED", "当前角色无权管理知识库", 403)

    @router.get("/admin/knowledge/documents")
    def list_documents(
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        require_permission(user, "knowledge:read")
        return success_response(request, service.list_documents())

    @router.post("/admin/knowledge/documents", status_code=201)
    def create_document(
        payload: KnowledgeDocumentCreateRequest,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        require_permission(user, "knowledge:write")
        return success_response(
            request,
            service.create_document(
                title=payload.title,
                document_type=payload.document_type,
                source_name=payload.source_name,
                product_code=payload.product_code,
                content=payload.content,
                created_by=user.id,
            ),
        )

    @router.post("/admin/knowledge/documents/upload", status_code=201)
    async def upload_document(
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
        file: Annotated[UploadFile, File()],
        title: Annotated[str, Form(min_length=2, max_length=200)],
        document_type: Annotated[
            Literal["INSURANCE_TERMS", "PRODUCT_GUIDE", "SERVICE_RULES", "FAQ"],
            Form(),
        ],
        product_code: Annotated[str | None, Form(max_length=64)] = None,
    ) -> dict[str, Any]:
        """读取上传文件正文并创建草稿，上传动作本身不会自动发布知识。"""

        require_permission(user, "knowledge:write")
        source_name = file.filename or "uploaded-document"
        content = extract_document_text(source_name, await file.read())
        return success_response(
            request,
            service.create_document(
                title=title,
                document_type=document_type,
                source_name=source_name,
                product_code=product_code,
                content=content,
                created_by=user.id,
            ),
        )

    @router.post("/admin/knowledge/documents/{document_id}/index")
    def index_document(
        document_id: str,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        """触发切片、向量化和 Milvus 索引替换。"""

        require_permission(user, "knowledge:write")
        return success_response(request, service.index_document(document_id))

    @router.post("/admin/knowledge/documents/{document_id}/publish")
    def publish_document(
        document_id: str,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        """通过发布门禁后，将知识开放给客户 Agent 检索。"""

        require_permission(user, "knowledge:publish")
        return success_response(request, service.publish_document(document_id))

    @router.post("/admin/knowledge/documents/{document_id}/search-test")
    def test_document_search(
        document_id: str,
        payload: KnowledgeSearchTestRequest,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        """执行并保存检索测试；有效记录是发布的必要条件。"""

        require_permission(user, "knowledge:write")
        return success_response(
            request,
            service.test_search(
                document_id,
                payload.query,
                limit=payload.limit,
                tested_by=user.id,
            ),
        )

    @router.get("/admin/knowledge/documents/{document_id}/search-tests")
    def list_document_search_tests(
        document_id: str,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        require_permission(user, "knowledge:read")
        return success_response(request, service.list_search_tests(document_id))

    @router.post("/admin/knowledge/documents/{document_id}/disable")
    def disable_document(
        document_id: str,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        require_permission(user, "knowledge:publish")
        return success_response(request, service.disable_document(document_id))

    return router
