"""AI 对话（聊天记录）端点（AC-2 / ai-chat-history-plan §3.3）。

作者↔AI 五类往复交换（refine/rewrite/clarify/continue/generator）落库，供每章「AI 对话」
抽屉重放。**本端点是显式的记录写入**（前端在一轮交换结束后 POST 一批）——不是生成端点；
五个生成端点保持只读、逐字节不变（守不变量 #3）。`ai_messages` 是侧记录，assemble()/agent
永不读它（守 #1/#6）。

- POST /projects/{id}/ai-messages   一批 append（201；项目不存在 → 404）。
- GET  /projects/{id}/ai-messages    列出（newest-first；`chapter_no` 过滤含项目级 NULL；分页）。

提交边界：`AiMessageRepo.append` 只 flush，POST 端点写后 `commit()`（仿模板/规则写侧）。
GET 只读不 commit。
"""

from __future__ import annotations

import uuid
from typing import Annotated

from fastapi import APIRouter, Depends, Query, Request
from sqlalchemy.ext.asyncio import AsyncSession
from ww_core.domain import AiMessageRepo, AiTurnRow, ProjectRepo
from ww_core.domain.ai_message_repo import AiMessageView as AiMessageRepoView
from ww_db import get_session
from ww_shared import AppError, ErrorCode

from ww_api.logging_config import get_logger
from ww_api.pagination import PageDep
from ww_api.schemas.ai_messages import (
    AiKind,
    AiMessageAppendRequest,
    AiMessageListResponse,
    AiMessageView,
)
from ww_api.services.credentials import STUB_OWNER_ID
from ww_api.services.project_deps import get_ai_message_repo, get_project_repo

log = get_logger("ww.api.ai_messages")

router = APIRouter(prefix="/projects", tags=["ai-messages"])

AiMessageRepoDep = Annotated[AiMessageRepo, Depends(get_ai_message_repo)]
ProjectRepoDep = Annotated[ProjectRepo, Depends(get_project_repo)]
SessionDep = Annotated[AsyncSession, Depends(get_session)]


def _to_response_view(v: AiMessageRepoView) -> AiMessageView:
    """repo 视图 → API 视图（同字段镜像；避免路由碰 repo 视图类型泄漏）。"""
    return AiMessageView(
        id=v.id,
        project_id=v.project_id,
        chapter_no=v.chapter_no,
        thread_id=v.thread_id,
        seq=v.seq,
        kind=v.kind,
        tool_key=v.tool_key,
        role=v.role,
        content=v.content,
        meta=v.meta,
        created_at=v.created_at,
    )


@router.post("/{project_id}/ai-messages", status_code=201)
async def append_ai_messages(
    project_id: uuid.UUID,
    body: AiMessageAppendRequest,
    request: Request,
    project_repo: ProjectRepoDep,
    repo: AiMessageRepoDep,
    session: SessionDep,
) -> AiMessageListResponse:
    """一批往复 bubble append（201）。项目不存在 → 404；非法 kind/role/空/超上限 → 422。"""
    request_id = getattr(request.state, "request_id", None)
    project = await project_repo.get(STUB_OWNER_ID, project_id)
    if project is None:
        raise AppError(ErrorCode.NOT_FOUND, f"project not found: {project_id}")
    views = await repo.append(
        project_id,
        thread_id=body.thread_id,
        chapter_no=body.chapter_no,
        kind=body.kind,
        tool_key=body.tool_key,
        rows=[AiTurnRow(role=m.role, content=m.content, meta=m.meta) for m in body.messages],
    )
    await session.commit()
    log.info(
        "ai_messages_appended",
        project_id=str(project_id),
        request_id=request_id,
        thread_id=str(body.thread_id),
        kind=body.kind,
        count=len(views),
    )
    return AiMessageListResponse(messages=[_to_response_view(v) for v in views])


@router.get("/{project_id}/ai-messages")
async def list_ai_messages(
    project_id: uuid.UUID,
    project_repo: ProjectRepoDep,
    repo: AiMessageRepoDep,
    page: PageDep,
    chapter_no: Annotated[int | None, Query(ge=1)] = None,
    kind: AiKind | None = None,
) -> AiMessageListResponse:
    """列出 AI 对话（newest-first）。`chapter_no` → 本章 ∪ 项目级(NULL)；缺省 → 仅项目级。"""
    project = await project_repo.get(STUB_OWNER_ID, project_id)
    if project is None:
        raise AppError(ErrorCode.NOT_FOUND, f"project not found: {project_id}")
    views = await repo.list_for_chapter(
        project_id, chapter_no, kind=kind, limit=page.limit, offset=page.offset
    )
    return AiMessageListResponse(messages=[_to_response_view(v) for v in views])
