from typing import List, Literal, Optional

from pydantic import BaseModel


class Oper(BaseModel):
    name: str
    skill: Optional[int] = 1
    skill_usage: Optional[int] = 0
    skill_times: Optional[int] = 1

    def __eq__(self, other):
        if isinstance(other, Oper):
            return self.name == other.name
        return False

    def __hash__(self):
        return hash(self.name)


class Group(BaseModel):
    name: str
    opers: List[Oper]

    def __eq__(self, other):
        if isinstance(other, Group):
            return sorted(self.opers, key=lambda x: x.name) == sorted(
                other.opers, key=lambda x: x.name
            )
        return False

    def __hash__(self):
        return hash(frozenset(self.opers))


class Action(BaseModel):
    type: Literal[
        "BulletTime",
        "Deploy",
        "SpeedUp",
        "Skill",
        "SkillUsage",
        "SkillDaemon",
        "Retreat",
        "Output",
        "MoveCamera",
        "调配干员",
        "CheckIfStartOver",
        "GetDrops",
    ] = "Deploy"
    name: Optional[str] = None
    costs: Optional[int] = None
    location: Optional[List[int]] = None
    direction: Optional[str] = None
    cost_changes: Optional[int] = None
    pre_delay: Optional[int] = None
    post_delay: Optional[int] = None
    cooling: Optional[int] = None
    kills: Optional[int] = None
    skill_usage: Optional[int] = None
    skill_times: Optional[int] = None
    distance: Optional[List[float]] = None


class ToolMen(BaseModel):
    PIONEER: int = 0
    WARRIOR: int = 0
    TANK: int = 0
    SNIPER: int = 0
    CASTER: int = 0
    MEDIC: int = 0
    SUPPORT: int = 0
    SPECIAL: int = 0


class Strategy(BaseModel):
    core: Optional[str] = None
    tool_men: ToolMen
    location: List[int]
    direction: str


class Stage(BaseModel):
    stage_name: str
    strategies: List[Strategy]
    draw_as_possible: bool = True
    actions: List[Action]
    retry_times: int = 3


class WorkModel(BaseModel):
    actions: List[Action]
    groups: List[Group] = []
    opers: List[Oper] = []

    class Config:
        extra = "ignore"


class SSSModel(BaseModel):
    stage_name: str
    buff: Optional[str] = None
    equipment: Optional[List[str]] = None
    strategy: Optional[str] = None
    opers: List[Oper] = []
    groups: List[Group] = []
    tool_men: ToolMen
    drops: List[str] = []
    blacklist: List[str] = []
    stages: List[Stage] = []

    class Config:
        extra = "ignore"
