from enum import Enum, auto

__all__ = [
    "Suit",
    "Rank",
    "Street",
    "HandType",
    "PlayerStateType",
    "GameStateType",
    "ActionType",
    "GameStage",
    "GameEventType",
]


class Suit(Enum):
    """
    Card suit enumeration.

    Represents the four suits in a standard deck of playing cards.

    Attributes
    ----------
    HEARTS : str
        Hearts suit, represented by 'H'.
    SPADES : str
        Spades suit, represented by 'S'.
    CLUBS : str
        Clubs suit, represented by 'C'.
    DIAMONDS : str
        Diamonds suit, represented by 'D'.
    """

    HEARTS = "H"
    SPADES = "S"
    CLUBS = "C"
    DIAMONDS = "D"


class Rank(Enum):
    """
    Card rank enumeration.

    Represents the ranks of cards in a standard deck, with numeric values
    for comparison purposes. Ace is high (14).

    Attributes
    ----------
    TWO : int
        Rank value 2.
    THREE : int
        Rank value 3.
    FOUR : int
        Rank value 4.
    FIVE : int
        Rank value 5.
    SIX : int
        Rank value 6.
    SEVEN : int
        Rank value 7.
    EIGHT : int
        Rank value 8.
    NINE : int
        Rank value 9.
    TEN : int
        Rank value 10.
    JACK : int
        Rank value 11.
    QUEEN : int
        Rank value 12.
    KING : int
        Rank value 13.
    ACE : int
        Rank value 14 (high ace).
    """

    TWO = 2
    THREE = 3
    FOUR = 4
    FIVE = 5
    SIX = 6
    SEVEN = 7
    EIGHT = 8
    NINE = 9
    TEN = 10
    JACK = 11
    QUEEN = 12
    KING = 13
    ACE = 14


class Street(Enum):
    """
    Betting round enumeration for Texas Hold'em.

    Represents the different stages of a poker hand, ordered by when they occur.

    Attributes
    ----------
    PRE_FLOP : int
        First betting round, before any community cards are dealt (value 0).
    FLOP : int
        Second betting round, after three community cards are dealt (value 1).
    TURN : int
        Third betting round, after the fourth community card is dealt (value 2).
    RIVER : int
        Fourth betting round, after the fifth community card is dealt (value 3).
    """

    PRE_FLOP = 0
    FLOP = 1
    TURN = 2
    RIVER = 3


class HandType(Enum):
    """
    Poker hand type enumeration.

    Represents the different types of poker hands, from weakest to strongest.

    Attributes
    ----------
    HIGH_CARD : str
        Highest card wins, no pairs or better.
    PAIR : str
        Two cards of the same rank.
    TWO_PAIR : str
        Two different pairs.
    THREE_OF_A_KIND : str
        Three cards of the same rank.
    STRAIGHT : str
        Five cards in sequence, not all the same suit.
    FLUSH : str
        Five cards of the same suit, not in sequence.
    FULL_HOUSE : str
        Three of a kind plus a pair.
    FOUR_OF_A_KIND : str
        Four cards of the same rank.
    STRAIGHT_FLUSH : str
        Five cards in sequence, all of the same suit.
    ROYAL_FLUSH : str
        Ace, King, Queen, Jack, Ten, all of the same suit (best hand).
    """

    HIGH_CARD = 0
    PAIR = 1
    TWO_PAIR = 2
    THREE_OF_A_KIND = 3
    STRAIGHT = 4
    FLUSH = 5
    FULL_HOUSE = 6
    FOUR_OF_A_KIND = 7
    STRAIGHT_FLUSH = 8
    ROYAL_FLUSH = 9

    def __lt__(self, other):
        if self.__class__ is other.__class__:
            return self.value < other.value
        return NotImplemented

    def __le__(self, other):
        if self.__class__ is other.__class__:
            return self.value <= other.value
        return NotImplemented

    def __gt__(self, other):
        if self.__class__ is other.__class__:
            return self.value > other.value
        return NotImplemented

    def __ge__(self, other):
        if self.__class__ is other.__class__:
            return self.value >= other.value
        return NotImplemented


class PlayerStateType(Enum):
    """
    Player state enumeration.

    Represents the current state of a player during a poker hand.

    Attributes
    ----------
    ACTIVE : str
        Player is actively participating in the current hand and can take actions.
    FOLDED : str
        Player has folded and is no longer competing for the pot.
    ALL_IN : str
        Player has bet all their chips and cannot take further actions, but remains
        in the hand competing for pots they contributed to.
    ELIMINATED : str
        Player has lost all their chips and is out of the game.
    """

    ACTIVE = auto()
    FOLDED = auto()
    ALL_IN = auto()
    ELIMINATED = auto()


class GameStage(Enum):
    """
    Game stage enumeration.

    Represents the different states of the game from waiting for players
    to game completion.

    Attributes
    ----------
    WAITING_FOR_PLAYERS : str
        Game is waiting for enough players to join.
    READY : str
        Enough players have joined; game is ready to start.
    STARTED : str
        Game has started; hands will begin dealing.
    DEALING : str
        Dealing hole cards to players and posting blinds.
    PRE_FLOP : str
        First betting round after hole cards are dealt.
    FLOP : str
        Second betting round after three community cards are dealt.
    TURN : str
        Third betting round after the fourth community card is dealt.
    RIVER : str
        Final betting round after the fifth community card is dealt.
    SHOWDOWN : str
        Players reveal hands and the winner is determined.
    HAND_COMPLETE : str
        Hand has ended; preparing for the next hand.
    GAME_OVER : str
        Game has ended (not enough players with chips).
    """

    WAITING_FOR_PLAYERS = auto()
    READY = auto()
    STARTED = auto()
    DEALING = auto()
    PRE_FLOP = auto()
    FLOP = auto()
    TURN = auto()
    RIVER = auto()
    SHOWDOWN = auto()
    HAND_COMPLETE = auto()
    GAME_OVER = auto()


GameStateType = GameStage


class ActionType(Enum):
    """
    Player action enumeration.

    Represents the different types of actions a player can take during a
    betting round.

    Attributes
    ----------
    FOLD : str
        Discard hand and forfeit any chance of winning the pot.
    CHECK : str
        Pass the action without betting (only valid when there's no bet to call).
    CALL : str
        Match the current bet to stay in the hand.
    BET : str
        Be the first to put chips into the pot in a betting round.
    RAISE : str
        Increase the current bet.
    ALL_IN : str
        Bet all remaining chips.
    """

    FOLD = auto()
    CHECK = auto()
    CALL = auto()
    BET = auto()
    RAISE = auto()
    ALL_IN = auto()


class GameEventType(Enum):
    """
    Game event enumeration.

    Represents the different types of events that can occur during a poker game.

    Attributes
    ----------
    GAME_STARTED : str
        Game has started.
    HAND_STARTED : str
        New hand has started.
    HAND_ENDED : str
        Hand has ended.
    GAME_ENDED : str
        Game has ended.
    HOLE_CARDS_DEALT : str
        Hole cards dealt to players.
    FLOP_DEALT : str
        First three community cards dealt.
    TURN_DEALT : str
        Fourth community card dealt.
    RIVER_DEALT : str
        Fifth community card dealt.
    PLAYER_ACTION_TAKEN : str
        Player takes an action.
    BETTING_ROUND_STARTED : str
        Betting round started.

        .. versionadded:: 0.2.0
    BETTING_ROUND_COMPLETED : str
        Betting round completed.
    BLINDS_POSTED : str
        Blind bets posted.
    ANTES_POSTED : str
        Ante bets posted.
    SHOWDOWN_STARTED : str
        Showdown has started.

        .. versionadded:: 0.2.0
    SHOWDOWN_COMPLETED : str
        Showdown has completed.
    PLAYER_JOINED : str
        Player joined the game.
    PLAYER_LEFT : str
        Player left the game.
    POT_WON : str
        Pot has been won by a player.

        .. versionadded:: 0.2.0
    PLAYER_CARDS_REVEALED : str
        Player's cards have been revealed at showdown. This only happens if there are multiple
        winners. If there is a single winner, their cards are not revealed.

        .. versionadded:: 0.2.0
    PLAYER_ELIMINATED : str
        Player has been eliminated from the game.

        .. versionadded:: 0.2.0
    """

    # Game lifecycle events
    GAME_STARTED = auto()
    GAME_ENDED = auto()
    HAND_STARTED = auto()
    HAND_ENDED = auto()
    SHOWDOWN_STARTED = auto()
    SHOWDOWN_COMPLETED = auto()

    # Dealing events
    HOLE_CARDS_DEALT = auto()
    FLOP_DEALT = auto()
    TURN_DEALT = auto()
    RIVER_DEALT = auto()

    # Player related events
    PLAYER_ACTION_TAKEN = auto()
    POT_WON = auto()
    PLAYER_CARDS_REVEALED = auto()
    PLAYER_JOINED = auto()
    PLAYER_LEFT = auto()
    PLAYER_ELIMINATED = auto()

    # Betting events
    BLINDS_POSTED = auto()
    ANTES_POSTED = auto()
    BETTING_ROUND_STARTED = auto()
    BETTING_ROUND_COMPLETED = auto()
