"""整章重写节点单测：纯构造 + 转发网关 Delta（注入 mock 网关，无图运行时、无 DB）。

守不变量 ②（只声明 tier=writer）/#9（rewrite 教条 + stable_core 进缓存前缀，草稿/意见进
断点后 input，不入缓存前缀）。asyncio_mode=auto。
"""

from __future__ import annotations

import uuid
from collections.abc import AsyncIterator

from ww_core.orchestrator import (
    build_rewrite_input,
    build_rewrite_request,
    stream_chapter_rewrite,
)
from ww_llm_gateway.types import Delta, LlmRequest


class _FakeGateway:
    """记录收到的请求并按给定文本吐 Delta。"""

    def __init__(self, texts: list[str]) -> None:
        self._texts = texts
        self.last_req: LlmRequest | None = None

    async def stream(self, req: LlmRequest) -> AsyncIterator[Delta]:
        self.last_req = req
        for text in self._texts:
            yield Delta(text=text)


def test_build_rewrite_input_orders_volatile_draft_feedback() -> None:
    out = build_rewrite_input(volatile="近况X", prior_draft="草稿Y", feedback="意见Z")
    assert "【当前整章草稿】" in out
    assert "【作者意见】" in out
    # 顺序：近况 → 草稿 → 意见。
    assert out.index("近况X") < out.index("草稿Y") < out.index("意见Z")


def test_build_rewrite_input_omits_empty_volatile() -> None:
    out = build_rewrite_input(volatile="   ", prior_draft="D", feedback="F")
    assert out.startswith("【当前整章草稿】")
    assert "D" in out and "F" in out


def test_build_rewrite_request_declares_writer_tier_and_streams() -> None:
    req = build_rewrite_request(
        stable_core="SC",
        volatile="V",
        prior_draft="DRAFT",
        feedback="FEEDBACK",
        user_id=uuid.uuid4(),
        project_id=uuid.uuid4(),
    )
    assert req.tier == "writer"  # 不变量 ②
    assert req.stream is True


def test_rewrite_cached_prefix_excludes_draft_and_feedback() -> None:
    """不变量 #9：草稿/意见是逐轮易变，绝不进 system 缓存前缀，只进断点后 input。"""
    req = build_rewrite_request(
        stable_core="STABLE_CORE",
        volatile="V",
        prior_draft="THE_DRAFT_BODY",
        feedback="THE_FEEDBACK",
        user_id=uuid.uuid4(),
        project_id=uuid.uuid4(),
    )
    cached_prefix = "".join(block.text for block in req.system)
    assert all(block.cache for block in req.system)
    assert "STABLE_CORE" in cached_prefix
    assert "THE_DRAFT_BODY" not in cached_prefix
    assert "THE_FEEDBACK" not in cached_prefix
    assert "THE_DRAFT_BODY" in req.input
    assert "THE_FEEDBACK" in req.input


async def test_stream_chapter_rewrite_forwards_gateway_deltas() -> None:
    gateway = _FakeGateway(["新版一", "新版二"])
    out = [
        delta.text
        async for delta in stream_chapter_rewrite(
            gateway,
            stable_core="SC",
            volatile="V",
            prior_draft="D",
            feedback="F",
            user_id=uuid.uuid4(),
            project_id=uuid.uuid4(),
        )
    ]
    assert out == ["新版一", "新版二"]
    assert gateway.last_req is not None
    assert gateway.last_req.tier == "writer"
