import re
import string
from pydantic import BaseModel
from typing import Optional
from enum import IntEnum

__all__ = [
    "Rarity",
    "SkinMetadatum",
    "StickerMetadatum",
    "ItemMetadatum",
    "SkinContainerEntry",
    "ItemContainerEntry",
    "ContainerEntry",
    "GenericContainer",
    "SkinCase",
    "SouvenirPackage",
    "StickerCapsule",
    "Container",
    "PhaseGroup",
    "remove_skin_name_formatting",
]


class Rarity(IntEnum):
    Common = 0
    Uncommon = 1
    Rare = 2
    Mythical = 3
    Legendary = 4
    Ancient = 5
    Contraband = 6

    def get_name_for_skin(self) -> str:
        """
        Get the rarity string if the item is a skin
        """
        return [
            "Consumer Grade",
            "Industrial Grade",
            "Mil-Spec",
            "Restricted",
            "Classified",
            "Covert",
            "Contraband",
        ][self.value]

    def get_name_for_regular_item(self) -> str:
        """
        Get the rarity string if the item is a regular item
        """
        return [
            "Base Grade",
            "Industrial Grade",
            "High Grade",
            "Remarkable",
            "Exotic",
            "Extraordinary",
            "Contraband",
        ][self.value]


class SkinMetadatum(BaseModel):
    formatted_name: str
    rarity: Rarity
    price: int
    image_url: str
    description: Optional[str]
    min_float: float
    max_float: float


class StickerMetadatum(BaseModel):
    formatted_name: str
    rarity: Rarity
    price: int
    image_url: str


type ItemMetadatum = SkinMetadatum | StickerMetadatum


class PhaseGroup(IntEnum):
    DOPPLER = 0
    GAMMA_DOPPLER = 1

    def get_phases(self) -> list[str]:
        return [
            [
                "Phase 1",
                "Phase 2",
                "Phase 3",
                "Phase 4",
                "Sapphire",
                "Ruby",
                "Black Pearl",
            ],
            ["Phase 1", "Phase 2", "Phase 3", "Phase 4", "Emerald"],
        ][self.value]


class SkinContainerEntry(BaseModel):
    unformatted_name: str
    min_float: float
    max_float: float
    phase_group: Optional[PhaseGroup]
    image_url: str


class ItemContainerEntry(BaseModel):
    unformatted_name: str
    image_url: str


type ContainerEntry = SkinContainerEntry | ItemContainerEntry


class GenericContainer[T: ContainerEntry](BaseModel):
    formatted_name: str
    price: int
    image_url: str
    requires_key: bool
    contains: dict[Rarity, list[T]]
    contains_rare: list[T]


class SkinCase(GenericContainer[SkinContainerEntry]):
    pass


class SouvenirPackage(GenericContainer[SkinContainerEntry]):
    pass


class StickerCapsule(GenericContainer[ItemContainerEntry]):
    pass


type Container = SkinCase | SouvenirPackage | StickerCapsule

_SPECIAL_CHARS_REGEX = re.compile(r"[™★♥\s]")


def remove_skin_name_formatting(skin_name: str) -> str:
    """
    Removes formatting from skin names:
    - Converts to lowercase
    - Removes punctuation, whitespace and special characters
    """
    skin_name = _SPECIAL_CHARS_REGEX.sub("", skin_name.lower())
    return skin_name.translate(str.maketrans("", "", string.punctuation))
