"""Agent HTTP 接口。

本模块只处理请求参数、登录身份和 HTTP/SSE 响应。
会话归属、限流、模型调用与持久化统一交给 ``AgentThreadService``。
"""

from typing import Annotated, Any

from fastapi import APIRouter, Depends, Request, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from pydantic import BaseModel, Field
from starlette.responses import StreamingResponse

from zbt.api.responses import success_response
from zbt.core.errors import AppError
from zbt.domains.agent.service import AgentThreadService
from zbt.domains.identity.models import AdminUser, H5User
from zbt.domains.identity.service import AdminAuthService, H5AuthService

agent_bearer_scheme = HTTPBearer(auto_error=False)


class CreateThreadRequest(BaseModel):
    """创建会话时允许客户端提交的字段。"""

    title: str | None = Field(default=None, max_length=128)


class TextContent(BaseModel):
    """当前阶段只支持文本消息。"""

    type: str = Field(pattern="^text$")
    text: str = Field(min_length=1, max_length=4000)


class SendMessageRequest(BaseModel):
    """发送消息的请求体；客户端消息 ID 用于标识一次提交。"""

    content: TextContent
    page_context: dict[str, Any] | None = None
    client_message_id: str = Field(min_length=1, max_length=64)


def create_agent_router(
    thread_service: AgentThreadService,
    h5_auth_service: H5AuthService,
    admin_auth_service: AdminAuthService,
) -> APIRouter:
    """创建 Agent 路由，并使用应用启动时装配好的服务对象。"""

    router = APIRouter(tags=["agent"])

    def current_h5_user(
        credentials: Annotated[
            HTTPAuthorizationCredentials | None,
            Depends(agent_bearer_scheme),
        ],
    ) -> H5User:
        """FastAPI 依赖：解析 Bearer Token，得到当前 H5 用户。"""

        if credentials is None:
            raise AppError("AUTH_REQUIRED", "请先登录", 401)
        return h5_auth_service.authenticate_access(credentials.credentials)

    def current_admin(
        credentials: Annotated[
            HTTPAuthorizationCredentials | None,
            Depends(agent_bearer_scheme),
        ],
    ) -> AdminUser:
        """FastAPI 依赖：解析 Bearer Token，得到当前后台账号。"""

        if credentials is None:
            raise AppError("AUTH_REQUIRED", "请先登录后台", 401)
        return admin_auth_service.authenticate_access(credentials.credentials)

    @router.post("/agent/threads", status_code=status.HTTP_201_CREATED)
    def create_customer_thread(
        payload: CreateThreadRequest,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.create_customer_thread(user, title=payload.title),
        )

    @router.post(
        "/agent/threads/{thread_id}/messages",
        status_code=status.HTTP_202_ACCEPTED,
    )
    def send_customer_message(
        thread_id: str,
        payload: SendMessageRequest,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.send_customer_message(
                user,
                thread_id=thread_id,
                text=payload.content.text,
            ),
        )

    @router.post("/agent/threads/{thread_id}/messages/stream")
    def stream_customer_message(
        thread_id: str,
        payload: SendMessageRequest,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> StreamingResponse:
        """以 SSE 持续返回运行事件，无需等待整次模型调用结束。"""

        events = thread_service.stream_customer_message(
            user,
            thread_id=thread_id,
            text=payload.content.text,
        )
        return StreamingResponse(
            (event.to_sse() for event in events),
            media_type="text/event-stream",
            headers={
                "Cache-Control": "no-cache",
                "X-Accel-Buffering": "no",
            },
        )

    @router.get("/agent/threads/{thread_id}/messages")
    def list_customer_messages(
        thread_id: str,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.list_customer_messages(user, thread_id=thread_id),
        )

    @router.get("/agent/runs/{run_id}")
    def get_customer_run(
        run_id: str,
        request: Request,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.get_customer_run(user, run_id=run_id),
        )

    @router.get("/agent/runs/{run_id}/events")
    def replay_customer_run_events(
        run_id: str,
        user: Annotated[H5User, Depends(current_h5_user)],
    ) -> StreamingResponse:
        """重放已保存事件，供页面刷新或网络恢复后继续展示进度。"""

        events = thread_service.list_customer_run_events(user, run_id=run_id)
        return StreamingResponse(
            (event.to_sse() for event in events),
            media_type="text/event-stream",
            headers={"Cache-Control": "no-cache"},
        )

    @router.post(
        "/admin/agent/threads",
        status_code=status.HTTP_201_CREATED,
    )
    def create_operation_thread(
        payload: CreateThreadRequest,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.create_operation_thread(user, title=payload.title),
        )

    @router.post(
        "/admin/agent/threads/{thread_id}/messages",
        status_code=status.HTTP_202_ACCEPTED,
    )
    def send_operation_message(
        thread_id: str,
        payload: SendMessageRequest,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.send_operation_message(
                user,
                thread_id=thread_id,
                text=payload.content.text,
            ),
        )

    @router.get("/admin/agent/threads/{thread_id}/messages")
    def list_operation_messages(
        thread_id: str,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.list_operation_messages(user, thread_id=thread_id),
        )

    @router.get("/admin/agent/runs/{run_id}")
    def get_operation_run(
        run_id: str,
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
    ) -> dict[str, Any]:
        return success_response(
            request,
            thread_service.get_operation_run(user, run_id=run_id),
        )

    @router.get("/admin/agent/runs")
    def list_operation_runs(
        request: Request,
        user: Annotated[AdminUser, Depends(current_admin)],
        limit: int = 20,
    ) -> dict[str, Any]:
        """返回当前后台账号自己的运行历史，并限制最大查询数量。"""

        return success_response(
            request,
            thread_service.list_operation_runs(user, limit=min(max(limit, 1), 100)),
        )

    return router
