# 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/>.

"""Raw card definition models using SQLAlchemy polymorphism.

Defines the base card types and specialized card categories (Character, Action, Location)
used in the trading card game. Uses single-table inheritance for polymorphic relationships.
"""

from typing import List

from sqlalchemy.orm import relationship
from sqlalchemy import Enum as SQEnum, Identity
from sqlalchemy import JSON, Column, ForeignKey, Integer, String

from discord_shared_db.base import Base
from discord_shared_db.card_game.card_modifiers import RawCardModifier
from discord_shared_db.card_game.tcg_enum import ActionCardType, ManaType, Rarity

class RawCard(Base):
    """Base raw card definition model (polymorphic base).
    
    Represents the base definition of a card in the TCG. Uses single-table
    inheritance to support multiple card types.
    
    Attributes:
        id: Unique card definition identifier.
        name: Card name.
        collect_number: Card's collection number.
        rarity: Card rarity level.
        image_path: Path to card artwork image.
        flavor_text: Flavor/lore text on the card.
        amount_pulled: Total number of times this card has been pulled.
        card_type: Discriminator for polymorphic type (character, action, location).
    """
    __tablename__ = "raw_cards"

    id = Column(String, primary_key=True)
    name = Column(String, nullable=False)
    collect_number = Column(Integer, nullable=False)
    rarity = Column(SQEnum(Rarity), nullable=False)
    image_path = Column(String, nullable=False)
    flavor_text = Column(String)

    amount_pulled = Column(Integer, default=0)
    card_type = Column(String, nullable=False)

    allowed_modifiers = relationship(
        "CardModifier",
        secondary=RawCardModifier.__table__,
        lazy="selectin",
    )

    __mapper_args__ = {
        "polymorphic_on": card_type,
        "polymorphic_identity": "base",
    }

class RawMove(Base):
    """Character card move definition model.
    
    Defines a move/ability that can be performed by character cards.
    
    Attributes:
        id: Unique move identifier.
        card_id: Reference to the character card.
        name: Name of the move.
        mana_cost: JSON mapping of mana types to quantities required.
        effect_text: Human-readable description of the move effect.
        effect_code: Code-based definition of the move effect.
        card: Relationship to the RawCharacterCard object.
    """
    __tablename__ = "raw_moves"

    id = Column(Integer, Identity(start=1), primary_key=True,)
    card_id = Column(String, ForeignKey("raw_cards.id"), nullable=False)

    name = Column(String, nullable=False)
    mana_cost = Column(JSON, nullable=False)
    effect_text = Column(String, nullable=False)
    effect_code = Column(String, nullable=False)

    card = relationship("RawCharacterCard", back_populates="moves")

 
class RawCharacterCard(RawCard):
    """Character card definition model.
    
    Specializes RawCard for character cards that have moves and mana.
    
    Attributes:
        id: Reference to parent RawCard.
        total_energy: Total energy pool for the character.
        mana_type: Type of mana the character uses.
        moves: Moves/abilities this character can perform.
    """
    __tablename__ = "raw_character_cards"

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

    total_energy = Column(Integer, nullable=False)
    mana_type = Column(SQEnum(ManaType), nullable=False)

    moves = relationship(
        "RawMove",
        back_populates="card",
        cascade="all, delete-orphan",
    )

    __mapper_args__ = {
        "polymorphic_identity": "character",
    }

class RawActionCard(RawCard):
    """Action card definition model.
    
    Specializes RawCard for action cards with effects and mana costs.
    
    Attributes:
        id: Reference to parent RawCard.
        action_card_type: Type of action (instant, equipment).
        mana_cost: JSON mapping of mana types to quantities required.
        effect_text: Human-readable description of card effect.
        effect_code: Code-based definition of card effect.
    """
    __tablename__ = "raw_action_cards"

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

    action_card_type = Column(SQEnum(ActionCardType), nullable=False)
    mana_cost = Column(JSON)
    effect_text = Column(String)
    effect_code = Column(String)

    __mapper_args__ = {
        "polymorphic_identity": "action",
    }


class RawLocationCard(RawCard):
    """Location card definition model.
    
    Specializes RawCard for location cards that provide environmental effects.
    
    Attributes:
        id: Reference to parent RawCard.
        mana_cost: JSON mapping of mana types to quantities required.
        effect_text: Human-readable description of location effect.
        effect_code: Code-based definition of location effect.
    """
    __tablename__ = "raw_location_cards"

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

    mana_cost = Column(JSON)
    effect_text = Column(String)
    effect_code = Column(String)

    __mapper_args__ = {
        "polymorphic_identity": "location",
    }
    

class RawManaCard(RawCard):
    """Mana card definition model.
    
    Represents cards that generate mana resources.
    """
    __tablename__ = "raw_mana_cards"

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

    mana_amount = Column(Integer, nullable=False)

    mana_provided = Column(JSON, default=list, nullable=False)

    __mapper_args__ = {
        "polymorphic_identity": "mana",
    }
