"""规则端点（C3 扩 / PRODUCT_SPEC §7 `POST /projects/:id/rules`；不变量 #3）。

POST /projects/:id/rules：作者显式加规则——审稿发现的问题/亮点随手沉淀为项目规则。
写一行 `rules`（level + content），喂给 assemble 的四级合并（`merge_rules`）。

加规则是**作者显式动作**（不变量 #3：规则入库不经 AI 静默写库）。`level` 合法性由
`RuleCreateRequest` 的 Literal 校验（非法 → FastAPI 422）。

提交边界：`RuleWriteRepo.create` 只 `flush()`，端点写后 `await session.commit()`
（仿 foreshadow/outline 写侧，见 memory/gotchas）。
"""

from __future__ import annotations

import uuid
from typing import Annotated

from fastapi import APIRouter, Depends, Request, Response
from sqlalchemy.ext.asyncio import AsyncSession
from ww_core.domain import RuleWriteRepo
from ww_core.domain.project_repo import ProjectRepo
from ww_db import get_session
from ww_shared import AppError, ErrorCode

from ww_api.logging_config import get_logger
from ww_api.schemas.rules import RuleCreateRequest, RuleView
from ww_api.services.credentials import STUB_OWNER_ID
from ww_api.services.project_deps import get_project_repo, get_rule_write_repo

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

router = APIRouter(prefix="/projects", tags=["rules"])

RuleWriteRepoDep = Annotated[RuleWriteRepo, Depends(get_rule_write_repo)]
ProjectRepoDep = Annotated[ProjectRepo, Depends(get_project_repo)]
SessionDep = Annotated[AsyncSession, Depends(get_session)]


@router.post("/{project_id}/rules", status_code=201)
async def create_rule(
    project_id: uuid.UUID,
    body: RuleCreateRequest,
    request: Request,
    repo: RuleWriteRepoDep,
    project_repo: ProjectRepoDep,
    session: SessionDep,
) -> RuleView:
    """新增一条规则（201）。非法 level / 空 content → FastAPI 422；项目不存在 → 404。

    项目存在性须在 insert 前校验：否则 FK 违例会逃逸成 500（QA H2），而非干净的 404。
    """
    request_id = getattr(request.state, "request_id", None)
    if await project_repo.get(STUB_OWNER_ID, project_id) is None:
        raise AppError(ErrorCode.NOT_FOUND, f"project not found: {project_id}")
    view = await repo.create(project_id, level=body.level, content=body.content)
    await session.commit()
    log.info(
        "rule_created",
        project_id=str(project_id),
        request_id=request_id,
        level=body.level,
    )
    return RuleView(id=view.id, level=view.level, content=view.content)


@router.delete("/{project_id}/rules/{rule_id}", status_code=204)
async def delete_rule(
    project_id: uuid.UUID,
    rule_id: uuid.UUID,
    request: Request,
    repo: RuleWriteRepoDep,
    project_repo: ProjectRepoDep,
    session: SessionDep,
) -> Response:
    """删除一条本作品规则（204）。项目不存在 → 404；规则不存在 / 不属于该项目 → 404。

    删规则是**作者显式动作**（不变量 #3：规则增删不经 AI 静默写库）。repo.delete 只 flush，
    端点提交；删不到行（未知 id / 跨项目）→ 不提交、抛 404。
    """
    request_id = getattr(request.state, "request_id", None)
    if await project_repo.get(STUB_OWNER_ID, project_id) is None:
        raise AppError(ErrorCode.NOT_FOUND, f"project not found: {project_id}")
    deleted = await repo.delete(project_id, rule_id)
    if not deleted:
        raise AppError(ErrorCode.NOT_FOUND, f"rule not found: {rule_id}")
    await session.commit()
    log.info(
        "rule_deleted",
        project_id=str(project_id),
        rule_id=str(rule_id),
        request_id=request_id,
    )
    return Response(status_code=204)
