"""世界观实体**写侧** Repository（C3 扩 / ARCH §5.4 worldbuilder writes=world_entities）。

读侧（`list_for_project`，供 assemble 注入）已在
`ww_core.memory.sql_repositories.SqlWorldEntityRepo` + `domain.repositories.WorldEntityRepo`/
`WorldEntityView` 提供（C5 稳定，不动）。本模块加**写**能力，命名加 `Write` 前缀避歧义。

**schema → DB 列形变（T5.1 gotcha）**：`ww_agents.WorldEntityCard.rules` 是 `list[str]`，
而 `world_entities.rules` 列是 JSONB **dict**——入库时包成 `{"rules": [...]}`。
`type`/`name` 是 Text 列直落。

**提交边界**：`create` 只 `flush()` 不 `commit()`——提交交端点事务。
"""

from __future__ import annotations

import uuid
from typing import Any, Protocol

from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from ww_db.models import WorldEntity


class WorldEntityWriteView(BaseModel):
    """世界观实体写入后的只读快照（snake_case，frozen）。"""

    model_config = {"frozen": True}

    id: uuid.UUID
    type: str
    name: str


def _rules_to_jsonb(rules: list[str]) -> dict[str, Any]:
    """`list[str]` → JSONB dict（DB 列形）。"""
    return {"rules": list(rules)}


class WorldEntityWriteRepo(Protocol):
    """世界观实体写侧接口（按 project_id 隔离；只 flush 不 commit）。"""

    async def create(
        self,
        project_id: uuid.UUID,
        *,
        type: str,
        name: str,
        rules: list[str],
    ) -> WorldEntityWriteView: ...


class SqlWorldEntityWriteRepo:
    """SQLAlchemy 实现：插一行 `world_entities`（rules list→dict；只 flush 不 commit）。"""

    def __init__(self, session: AsyncSession) -> None:
        self._s = session

    async def create(
        self,
        project_id: uuid.UUID,
        *,
        type: str,
        name: str,
        rules: list[str],
    ) -> WorldEntityWriteView:
        row = WorldEntity(
            project_id=project_id,
            type=type,
            name=name,
            rules=_rules_to_jsonb(rules),
        )
        self._s.add(row)
        await self._s.flush()
        await self._s.refresh(row)
        return WorldEntityWriteView(id=row.id, type=row.type, name=row.name)
