"""大纲生成的注入上下文组装（确定性序列化文本；ARCH §5.4 outliner reads / §6.2）。

把 projects 设定 + 已登记伏笔 + 人物 + 世界观确定性序列化成纯文本喂给 outliner——
**无时间戳/无 UUID**（缓存前缀稳定，不变量 #9），逐项排序保证同输入同输出（可单测）。
outliner 据此排出分章节拍 + 伏笔回收窗口（关联本章与伏笔，§6.2）。

注：reads=["projects","foreshadow","characters","world_entities"]（C6 outliner_spec），
本组装恰好覆盖这四源，不读 digest/outline（排大纲是从设定生成、非续写既有章）。
"""

from __future__ import annotations

from collections.abc import Sequence

from ww_core.domain import ForeshadowLedgerView, ProjectView
from ww_core.domain.repositories import CharacterView, WorldEntityView


def _project_block(project: ProjectView) -> str:
    lines = [f"标题：{project.title}"]
    if project.genre:
        lines.append(f"类型：{project.genre}")
    if project.logline:
        lines.append(f"一句话简介：{project.logline}")
    if project.premise:
        lines.append(f"前提：{project.premise}")
    if project.theme:
        lines.append(f"主题：{project.theme}")
    if project.selling_points:
        lines.append("卖点：" + "、".join(project.selling_points))
    if project.structure:
        lines.append(f"结构：{project.structure}")
    return "【作品设定】\n" + "\n".join(lines)


def _foreshadow_block(foreshadow: Sequence[ForeshadowLedgerView]) -> str:
    if not foreshadow:
        return "【已登记伏笔】\n（无）"
    rows = sorted(foreshadow, key=lambda f: f.code)
    lines = []
    for f in rows:
        window = ""
        if f.expected_close_from is not None or f.expected_close_to is not None:
            lo = f.expected_close_from if f.expected_close_from is not None else "?"
            hi = f.expected_close_to if f.expected_close_to is not None else "?"
            window = f"（回收窗口 {lo}-{hi}）"
        plant = f"埋设第{f.planted_at}章 " if f.planted_at is not None else ""
        lines.append(f"- [{f.code}] {f.title} {plant}{window}".rstrip())
    return "【已登记伏笔】\n" + "\n".join(lines)


def _characters_block(characters: Sequence[CharacterView]) -> str:
    if not characters:
        return "【人物】\n（无）"
    rows = sorted(characters, key=lambda c: c.name)
    lines = []
    for c in rows:
        role = f"（{c.role}）" if c.role else ""
        motive = f" 动机：{c.motive}" if c.motive else ""
        lines.append(f"- {c.name}{role}{motive}".rstrip())
    return "【人物】\n" + "\n".join(lines)


def _world_block(entities: Sequence[WorldEntityView]) -> str:
    if not entities:
        return "【世界观】\n（无）"
    rows = sorted(entities, key=lambda e: (e.type, e.name))
    lines = [f"- [{e.type}] {e.name}" for e in rows]
    return "【世界观】\n" + "\n".join(lines)


def build_outline_context(
    *,
    project: ProjectView,
    foreshadow: Sequence[ForeshadowLedgerView],
    characters: Sequence[CharacterView],
    world_entities: Sequence[WorldEntityView],
) -> str:
    """组装 outliner 注入上下文（确定性文本，纯函数）。"""
    return "\n\n".join(
        [
            _project_block(project),
            _foreshadow_block(foreshadow),
            _characters_block(characters),
            _world_block(world_entities),
        ]
    )
