"""板子配置(boards/*.json)+ 发牌。加对局 = 加一个 board 文件,引擎零改动。"""

from __future__ import annotations

import json
import random
from dataclasses import dataclass, field
from pathlib import Path

from genesis.werewolf.roles import Role


@dataclass(frozen=True)
class Board:
    id: str
    name: str
    seats: int
    roster: dict[str, int]          # role_id -> 数量
    sheriff: bool
    win: str                        # kill_side(屠边) | kill_all(屠城)
    night_order: tuple[str, ...]    # 参与夜间的角色 id,按结算先后(可空 → 由 role.night_order 推导)
    options: dict = field(default_factory=dict)

    def __post_init__(self):
        total = sum(self.roster.values())
        if total != self.seats:
            raise ValueError(f"板子 {self.id} 角色总数 {total} ≠ 座位数 {self.seats}")


def load_board(path: str | Path) -> Board:
    d = json.loads(Path(path).read_text(encoding="utf-8"))
    return Board(
        id=d["id"], name=d.get("name", d["id"]), seats=int(d["seats"]),
        roster=dict(d["roster"]), sheriff=bool(d.get("sheriff", False)),
        win=d.get("win", "kill_side"), night_order=tuple(d.get("night_order") or []),
        options=dict(d.get("options") or {}))


def deal(board: Board, rng: random.Random) -> dict[int, str]:
    """发牌:把 roster 里的角色随机分配到 1..seats 号座位 → {seat: role_id}。
    用传入的 rng(可种子)保证可复现 —— 测试与存档续局都需要确定性。"""
    pool: list[str] = []
    for role_id, n in board.roster.items():
        pool += [role_id] * n
    rng.shuffle(pool)
    return {seat: role_id for seat, role_id in enumerate(pool, start=1)}


def resolve_night_order(board: Board, roles: dict[str, Role]) -> list[str]:
    """夜间结算顺序:优先板子显式 night_order,否则按各 role.night_order 升序(0 不参与)。"""
    if board.night_order:
        return [rid for rid in board.night_order if roles.get(rid) and roles[rid].acts_at_night()]
    actors = [rid for rid, r in roles.items() if r.acts_at_night() and rid in board.roster]
    return sorted(actors, key=lambda rid: roles[rid].night_order)
