"""Deck model for Mantimon TCG.

This module defines the Deck model for player deck configurations.
Decks store card lists as JSONB for flexibility and can be validated
against campaign rules or used freely in freeplay mode.

Example:
    deck = Deck(
        user_id=user.id,
        name="Electric Storm",
        cards={"pikachu_base_001": 2, "raichu_base_001": 1, ...},
        energy_cards={"lightning": 10, "colorless": 4}
    )
"""

from typing import TYPE_CHECKING
from uuid import UUID

from sqlalchemy import Boolean, ForeignKey, Index, String, Text, text
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.db.base import Base

if TYPE_CHECKING:
    from app.db.models.user import User


class Deck(Base):
    """Player deck configuration.

    Stores a deck's card composition and validation state.
    Cards are stored as JSONB mapping card_definition_id -> quantity.

    Attributes:
        id: Unique identifier (UUID).
        user_id: Foreign key to the owning user.
        name: Display name for the deck.
        cards: JSONB mapping card IDs to quantities.
        energy_cards: JSONB mapping energy types to quantities.
        is_valid: Whether deck passes validation rules.
        validation_errors: JSONB list of validation error messages.
        is_starter: Whether this is a pre-built starter deck.
        starter_type: Type of starter deck (grass, fire, water, etc.).
        created_at: Record creation timestamp.
        updated_at: Record update timestamp.

    Relationships:
        user: The user who owns this deck.

    Notes:
        - Campaign mode requires deck ownership validation
        - Freeplay mode unlocks all cards (validation skipped)
        - Free users limited to 5 decks, premium unlimited
    """

    __tablename__ = "decks"

    # Ownership
    user_id: Mapped[UUID] = mapped_column(
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
        doc="Foreign key to owning user",
    )

    # Deck identity
    name: Mapped[str] = mapped_column(
        String(100),
        nullable=False,
        doc="Display name for the deck",
    )

    # Card composition (JSONB for flexibility)
    # Format: {"card_definition_id": quantity, ...}
    cards: Mapped[dict] = mapped_column(
        JSONB,
        default=dict,
        nullable=False,
        doc="Mapping of card IDs to quantities",
    )

    # Energy cards tracked separately for easier UI display
    # Format: {"lightning": 10, "fire": 5, ...}
    energy_cards: Mapped[dict] = mapped_column(
        JSONB,
        default=dict,
        nullable=False,
        doc="Mapping of energy types to quantities",
    )

    # Validation state
    is_valid: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        nullable=False,
        doc="Whether deck passes validation rules",
    )
    validation_errors: Mapped[list | None] = mapped_column(
        JSONB,
        nullable=True,
        doc="List of validation error messages",
    )

    # Starter deck flags
    is_starter: Mapped[bool] = mapped_column(
        Boolean,
        default=False,
        nullable=False,
        doc="Whether this is a pre-built starter deck",
    )
    starter_type: Mapped[str | None] = mapped_column(
        String(20),
        nullable=True,
        doc="Type of starter deck (grass, fire, water, etc.)",
    )

    # Optional notes/description
    description: Mapped[str | None] = mapped_column(
        Text,
        nullable=True,
        doc="Optional deck description or notes",
    )

    # Relationship
    user: Mapped["User"] = relationship(
        "User",
        back_populates="decks",
    )

    # Indexes
    __table_args__ = (
        Index("ix_decks_user_name", "user_id", "name"),
        # Partial unique index: only one starter deck per user
        Index(
            "ix_decks_user_starter_unique",
            "user_id",
            unique=True,
            postgresql_where=text("is_starter = true"),
        ),
    )

    @property
    def total_cards(self) -> int:
        """Get total number of cards in deck (excluding energy).

        Returns:
            Sum of all card quantities.
        """
        return sum(self.cards.values()) if self.cards else 0

    @property
    def total_energy(self) -> int:
        """Get total number of energy cards.

        Returns:
            Sum of all energy card quantities.
        """
        return sum(self.energy_cards.values()) if self.energy_cards else 0

    @property
    def deck_size(self) -> int:
        """Get total deck size (cards + energy).

        Returns:
            Total cards in deck.
        """
        return self.total_cards + self.total_energy

    def __repr__(self) -> str:
        return f"<Deck(id={self.id!r}, name={self.name!r}, size={self.deck_size})>"
