# This file is part of discord-shared-db
#
# Copyright (C) 2026 CouchComfy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

"""Card pack definition and slot probability models.

Manages the configuration and probabilities for card pack definitions,
including pack slots, rarity weights, and card types available per slot.
"""

from sqlalchemy.orm import relationship
from sqlalchemy import BigInteger, Column, Float, ForeignKey, Identity, Integer, String

from discord_shared_db.base import Base

class RawPack(Base):
    """Card pack definition model.
    
    Represents a booster pack template that can be purchased or opened
    by players. Defines the pack's cost, card count, and slot structure.
    
    Attributes:
        id: Unique pack identifier.
        name: Human-readable name of the pack.
        cost: Purchasing cost in in-game currency.
        total_cards: Total number of cards in each pack instance.
        slots: List of pack slots defining card pull positions and probabilities.
    """
    __tablename__ = "raw_packs"

    id = Column(String, primary_key=True)
    name = Column(String, nullable=False)
    cost = Column(Integer, nullable=False)
    total_cards = Column(Integer, nullable=False)

    slots = relationship("RawPackSlot", back_populates="pack")

class RawPackSlot(Base):
    """Pack slot definition model.
    
    Represents a single card slot position within a pack. Each slot can
    have multiple possible card types and rarity distributions.
    
    Attributes:
        id: Unique slot identifier.
        pack_id: Reference to the pack this slot belongs to.
        slot_index: Position index of this slot within the pack (0-based).
        pack: Relationship to the RawPack object.
        probabilities: Rarity weight probabilities for this slot.
        allowed_types: Card types that can appear in this slot.
    """
    __tablename__ = "raw_pack_slots"

    id = Column(BigInteger, Identity(start=1), primary_key=True)
    pack_id = Column(String, ForeignKey("raw_packs.id"), nullable=False)
    slot_index = Column(Integer, nullable=False)

    pack = relationship("RawPack", back_populates="slots")
    probabilities = relationship(
        "RawPackSlotRarity", 
        back_populates="slot",
        cascade="all, delete-orphan",
    )
    allowed_types = relationship(
        "RawPackSlotType",
        back_populates="slot",
        cascade="all, delete-orphan",
    )

class RawPackSlotType(Base):
    """Pack slot card type restriction model.
    
    Defines which card types are allowed to appear in a specific pack slot.
    
    Attributes:
        id: Unique record identifier.
        slot_id: Reference to the pack slot.
        card_type: The card type allowed (e.g., 'character', 'action', 'location').
        slot: Relationship to the RawPackSlot object.
    """
    __tablename__ = "raw_pack_slot_types"

    id = Column(BigInteger, Identity(start=1), primary_key=True)
    slot_id = Column(Integer, ForeignKey("raw_pack_slots.id"), nullable=False)

    card_type = Column(String, nullable=False) 

    slot = relationship("RawPackSlot", back_populates="allowed_types")


class RawPackSlotRarity(Base):
    """Pack slot rarity probability model.
    
    Defines the probability weight for each rarity level within a pack slot.
    Weights are used to determine the likelihood of pulling cards of
    specific rarities.
    
    Attributes:
        id: Unique record identifier.
        slot_id: Reference to the pack slot.
        rarity: Rarity level (e.g., 'common', 'uncommon', 'rare').
        weight: Probability weight for this rarity (normalized or raw).
        slot: Relationship to the RawPackSlot object.
    """
    __tablename__ = "raw_pack_slot_rarities"

    id = Column(BigInteger, Identity(start=1), primary_key=True)
    slot_id = Column(Integer, ForeignKey("raw_pack_slots.id"), nullable=False)

    rarity = Column(String, nullable=False)  # "common", "uncommon", "rare"
    weight = Column(Float, nullable=False)   # normalized or raw weight

    slot = relationship("RawPackSlot", back_populates="probabilities")


class RawPackCard(Base):
    """Pack card pool association model.
    
    Represents the relationship between a pack and a card, indicating
    that the card is available to be pulled from the pack.
    
    Attributes:
        pack_id: Reference to the pack (primary key).
        card_id: Reference to the card (primary key).
    """
    __tablename__ = "raw_pack_cards"

    pack_id = Column(String, ForeignKey("raw_packs.id"), primary_key=True)
    card_id = Column(String, ForeignKey("raw_cards.id"), primary_key=True)