"""P1-4：`SqlChapterRepo.max_version` 用行锁消除 read-then-insert 的 TOCTOU 竞态。

并发验收同一章时，两请求若都读到同一 max(version) 再各自 +1 插入，会撞
`(project_id, chapter_no, version)` 唯一约束抛 500。修法：`max_version` 的 SELECT 加
`with_for_update()` 锁住该章现有行——后到者阻塞到前者提交后才读到更新后的 max。

真正的双事务阻塞行为需真实 PG（由 tests/ 下 E2E 覆盖）；此处以**不连库**的方式断言
编译出的 SQL 确实带 `FOR UPDATE`（行锁已正确接线），保持单测确定性、不联网。
"""

from __future__ import annotations

import uuid
from typing import Any

import pytest
from sqlalchemy.dialects import postgresql
from ww_core.domain.chapter_repo import SqlChapterRepo

PROJECT = uuid.UUID("00000000-0000-0000-0000-000000000001")


class _CapturingResult:
    def scalars(self) -> _CapturingResult:
        return self

    def __iter__(self) -> Any:
        return iter([])


class _CapturingSession:
    """fake session：捕获 execute 的 statement，返回空结果（不连库）。"""

    def __init__(self) -> None:
        self.statements: list[Any] = []

    async def execute(self, statement: Any) -> _CapturingResult:
        self.statements.append(statement)
        return _CapturingResult()


@pytest.mark.asyncio
async def test_max_version_query_uses_for_update_row_lock() -> None:
    session = _CapturingSession()
    repo = SqlChapterRepo(session)  # type: ignore[arg-type]  # fake 同形（仅用 execute）

    result = await repo.max_version(PROJECT, 1)

    # 无现有行 → 0（read-then-insert 的基线）。
    assert result == 0
    # 断言编译出的 SQL 带 FOR UPDATE（行锁），即 with_for_update() 已正确接线（P1-4）。
    assert len(session.statements) == 1
    compiled = str(
        session.statements[0].compile(dialect=postgresql.dialect())  # type: ignore[no-untyped-call]
    ).upper()
    assert "FOR UPDATE" in compiled
