"""整章再沟通 / 重写节点（ARCH §5.2 writer 行的工具变体）。

把当前整章草稿 + 作者意见流式重写成新一版。与 write 节点的关系（不变量纪律）：
- rewrite 是**独立工具，不是写图节点**：吃「当前草稿 + 作者意见」，不参与
  `章=f(outline, state, fingerprint)` 纯函数写章（不变量 #7），也不写库
  （HITL：新版停前端/草稿，接受才落，不变量 #3）。
- 与 write 一样：节点逻辑无 LLM 非确定性（藏在网关后），`build_rewrite_request` 是纯函数、
  `stream_chapter_rewrite` 注入 mock 网关即可单测。
- 不变量 ②：只传 `tier="writer"`，绝不传具体 model。
- 不变量 #9：rewrite 教条 + `stable_core` 进 `system` 缓存断点前（cache=True）；易变的
  `volatile` + 当前草稿 + 作者意见进 `input`（断点后，绝不进缓存前缀）。
"""

from __future__ import annotations

import uuid
from collections.abc import AsyncIterator
from typing import Protocol

from ww_agents import load_prompt
from ww_llm_gateway.types import Block, Delta, LlmRequest, Scope

# 整章重写教条（品类无关内核）：import 期读盘 → 缺失即 fail-fast（崩 import）。
# 字节稳定的稳定内容，作为最前的 cache=True system 块（跨调用前缀复用，不变量 #9）。
_REWRITE_DOCTRINE = load_prompt("rewrite")


class GatewayStream(Protocol):
    """rewrite 节点对网关的最小依赖——只需 `stream`（注入真网关或 mock）。"""

    def stream(self, req: LlmRequest) -> AsyncIterator[Delta]: ...


def build_rewrite_input(*, volatile: str, prior_draft: str, feedback: str) -> str:
    """组重写输入（断点后 volatile 段）：近况 + 当前整章草稿 + 作者意见。

    三段都进 `input`（不进缓存前缀）：草稿/意见逐轮变，是最易变的部分。
    """
    parts: list[str] = []
    if volatile.strip():
        parts.append(volatile)
    parts.append(f"【当前整章草稿】\n{prior_draft}")
    parts.append(f"【作者意见】\n{feedback}")
    return "\n\n".join(parts)


def build_rewrite_request(
    *,
    stable_core: str,
    volatile: str,
    prior_draft: str,
    feedback: str,
    user_id: uuid.UUID,
    project_id: uuid.UUID,
) -> LlmRequest:
    """据组装上下文 + 当前草稿 + 作者意见构造重写请求（纯函数）。

    `system` = [rewrite 教条(cache), stable_core(cache)]；`input` = 近况 + 草稿 + 意见（断点后）。
    """
    return LlmRequest(
        tier="writer",
        system=[
            Block(text=_REWRITE_DOCTRINE, cache=True),
            Block(text=stable_core, cache=True),
        ],
        input=build_rewrite_input(volatile=volatile, prior_draft=prior_draft, feedback=feedback),
        stream=True,
        scope=Scope(user_id=user_id, project_id=project_id),
    )


async def stream_chapter_rewrite(
    gateway: GatewayStream,
    *,
    stable_core: str,
    volatile: str,
    prior_draft: str,
    feedback: str,
    user_id: uuid.UUID,
    project_id: uuid.UUID,
) -> AsyncIterator[Delta]:
    """流式重写本章增量——构造请求 → 转发网关 `Delta`。

    本身不累积/不落库；瞬时失败已在网关重试，此处异常向上抛给 SSE 归一层（发 `error` 事件）。
    """
    req = build_rewrite_request(
        stable_core=stable_core,
        volatile=volatile,
        prior_draft=prior_draft,
        feedback=feedback,
        user_id=user_id,
        project_id=project_id,
    )
    async for delta in gateway.stream(req):
        yield delta
