from __future__ import annotations

import datetime as dt
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field


class ActionSchema(BaseModel):
    type: str
    payload: Dict[str, Any] = Field(default_factory=dict)


class ActionLogSchema(BaseModel):
    idx: int
    ts: dt.datetime
    actor: str
    action: ActionSchema
    applied: bool = True
    meta: Dict[str, Any] = Field(default_factory=dict)


class TradeOfferSchema(BaseModel):
    id: str
    from_player: str
    to_player: Optional[str] = None
    offer: Dict[str, int]
    request: Dict[str, int]
    status: str
    created_at: dt.datetime


class GameSlotSchema(BaseModel):
    slot_id: int
    name: Optional[str] = None
    user_id: Optional[int] = None
    is_ai: bool = False
    ai_kind: Optional[str] = None
    ai_model: Optional[str] = None
    ready: bool = False
    color: Optional[str] = None


class GameSummarySchema(BaseModel):
    id: str
    name: str
    status: str
    max_players: int
    created_by: str
    created_at: dt.datetime
    players: List[GameSlotSchema]


class GameStateSchema(BaseModel):
    id: str
    name: str
    status: str
    max_players: int
    created_by: str
    created_at: dt.datetime
    players: List[GameSlotSchema]
    game: Optional[Dict[str, Any]] = None
    board: Optional[Dict[str, Any]] = None
    legal_actions: List[ActionSchema] = Field(default_factory=list)
    pending_trades: List[TradeOfferSchema] = Field(default_factory=list)
    history: List[ActionLogSchema] = Field(default_factory=list)


class CreateGameRequest(BaseModel):
    name: str
    max_players: int
    created_by: Optional[str] = None


class JoinGameRequest(BaseModel):
    username: str
    user_id: int


class AddAIRequest(BaseModel):
    ai_type: str
    model_name: Optional[str] = None


class TradeOfferRequest(BaseModel):
    from_player: str
    to_player: Optional[str] = None
    offer: Dict[str, int]
    request: Dict[str, int]


class TradeRespondRequest(BaseModel):
    player: str
    accept: bool


class ActionRequest(BaseModel):
    actor: str
    action: ActionSchema


class AIRequest(BaseModel):
    observation: Dict[str, Any]
    legal_actions: List[ActionSchema]
    agent: Dict[str, Any]
    debug: bool = False


class AIResponse(BaseModel):
    action: ActionSchema
    debug: Dict[str, Any] = Field(default_factory=dict)


class ReplayMeta(BaseModel):
    id: str
    created_at: dt.datetime
    players: List[str]
    winner: Optional[str] = None
    total_actions: int


class ReplayDetail(ReplayMeta):
    seed: int
    actions: List[ActionLogSchema]


class ReplayArchive(BaseModel):
    version: int = 1
    id: str
    created_at: dt.datetime
    seed: int
    players: List[str]
    winner: Optional[str] = None
    slots: List[GameSlotSchema]
    actions: List[ActionLogSchema]
