"""Game record types and typed helpers for shogi."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Literal, Optional, TypedDict

from rshogi._rshogi import (
    GameRecord,
    GameRecordMetadata,
    GameResult,
    GameResultInfo,
    MoveEngineInfo,
    MoveRecord,
    SpecialMoveRecord,
    TimeControl,
    read_pack,
    read_pack_file,
    write_pack,
    write_pack_file,
)

StrictMode = Literal["strict", "permissive"]
EngineExtraValue = str | int | float | bool


class TimeControlDict(TypedDict, total=False):
    base_seconds: int
    byoyomi_seconds: int
    increment_seconds: int


class MoveEngineInfoDict(TypedDict, total=False):
    eval: int | None
    depth: int | None
    nodes: int | None
    seldepth: int | None
    extras: dict[str, EngineExtraValue]


class MoveRecordDict(TypedDict, total=False):
    move: MoveRecord | int | str
    time_ms: int | None
    comment: str | None
    engine_info: MoveEngineInfo | MoveEngineInfoDict | None


class GameResultInfoDict(TypedDict, total=False):
    result: GameResult | int | str
    ply_count: int
    reason: str | None
    end_time_ms: int | None
    end_comment: str | None


class GameRecordMetadataDict(TypedDict, total=False):
    event: str | None
    site: str | None
    black_player: str | None
    white_player: str | None
    game_name: str | None
    game_type: str | None
    time_control: TimeControl | TimeControlDict | str | None
    black_time_control: TimeControl | TimeControlDict | str | None
    white_time_control: TimeControl | TimeControlDict | str | None
    max_moves: int | None
    impasse_rule: str | None
    start_date: str | None
    end_date: str | None
    updated_date: str | None
    comment: str | None
    attributes: dict[str, str]


class GameRecordDict(TypedDict, total=False):
    version: int
    init_position_sfen: str
    moves: list[MoveRecordDict]
    metadata: GameRecordMetadata | GameRecordMetadataDict
    result: GameResultInfoDict | GameResult | int | str


@dataclass(slots=True)
class GameRecordMetadataBuilder:
    event: Optional[str] = None
    site: Optional[str] = None
    black_player: Optional[str] = None
    white_player: Optional[str] = None
    game_name: Optional[str] = None
    game_type: Optional[str] = None
    time_control: Optional[TimeControl] = None
    black_time_control: Optional[TimeControl] = None
    white_time_control: Optional[TimeControl] = None
    max_moves: Optional[int] = None
    impasse_rule: Optional[str] = None
    start_date: Optional[str] = None
    end_date: Optional[str] = None
    updated_date: Optional[str] = None
    comment: Optional[str] = None
    attributes: dict[str, str] = field(default_factory=dict)

    def build(self) -> GameRecordMetadata:
        return GameRecordMetadata(
            event=self.event,
            site=self.site,
            black_player=self.black_player,
            white_player=self.white_player,
            game_name=self.game_name,
            game_type=self.game_type,
            time_control=self.time_control,
            black_time_control=self.black_time_control,
            white_time_control=self.white_time_control,
            max_moves=self.max_moves,
            impasse_rule=self.impasse_rule,
            start_date=self.start_date,
            end_date=self.end_date,
            updated_date=self.updated_date,
            comment=self.comment,
            attributes=dict(self.attributes),
        )


@dataclass(slots=True)
class GameRecordBuilder:
    init_position_sfen: str
    moves: list[MoveRecord] = field(default_factory=list)
    metadata: Optional[GameRecordMetadata | GameRecordMetadataBuilder] = None
    terminal: Optional[SpecialMoveRecord] = None

    def build(self) -> GameRecord:
        metadata = self.metadata.build() if isinstance(self.metadata, GameRecordMetadataBuilder) else self.metadata
        return GameRecord.from_main_line(
            self.init_position_sfen,
            list(self.moves),
            self.terminal,
            metadata,
        )


__all__ = [
    "EngineExtraValue",
    "GameRecord",
    "GameRecordBuilder",
    "GameRecordDict",
    "GameRecordMetadata",
    "GameRecordMetadataBuilder",
    "GameRecordMetadataDict",
    "GameResult",
    "GameResultInfo",
    "GameResultInfoDict",
    "MoveEngineInfo",
    "MoveEngineInfoDict",
    "MoveRecord",
    "MoveRecordDict",
    "SpecialMoveRecord",
    "StrictMode",
    "TimeControl",
    "TimeControlDict",
    "read_pack",
    "read_pack_file",
    "write_pack",
    "write_pack_file",
]
