"""Card loader for populating card details from the registry.

This module provides utilities to load card details from the CardDetailsRegistry
into Card objects, supporting both individual cards and full decks.

Usage:
    from tarot.card.loader import load_card_details, load_deck_details
    from tarot.card.details import CardDetailsRegistry

    # Load single card
    loader = CardDetailsRegistry()
    card = my_deck.minor.swords(11)
    load_card_details(card, loader)

    # Load entire deck
    load_deck_details(my_deck, loader)
"""

from typing import TYPE_CHECKING, List, Optional

if TYPE_CHECKING:
    from tarot.card.card import Card
    from tarot.card.details import CardDetailsRegistry
    from tarot.deck import Deck


def load_card_details(card: "Card", registry: Optional["CardDetailsRegistry"] = None) -> bool:
    """
    Load details for a single card from the registry.

    Args:
        card: The Card object to populate with details
        registry: Optional CardDetailsRegistry. If not provided, creates a new one.

    Returns:
        True if details were found and loaded, False otherwise

    Example:
        >>> from tarot import Deck
        >>> deck = Deck()
        >>> card = deck.major[0]  # The Fool
        >>> load_card_details(card)
        True
        >>> print(card.keywords)
        ['new beginnings', 'innocence', 'faith', ...]
    """
    if registry is None:
        from tarot.card.details import CardDetailsRegistry

        registry = CardDetailsRegistry()

    return registry.load_into_card(card)


def load_deck_details(
    deck: "Deck", registry: Optional["CardDetailsRegistry"] = None, verbose: bool = False
) -> int:
    """
    Load details for all cards in a deck.

    Args:
        deck: The Deck object containing cards to populate
        registry: Optional CardDetailsRegistry. If not provided, creates a new one.
        verbose: If True, prints information about each card loaded

    Returns:
        Number of cards successfully loaded with details

    Example:
        >>> from tarot import Deck
        >>> deck = Deck()
        >>> count = load_deck_details(deck, verbose=True)
        >>> print(f"Loaded details for {count} cards")
    """
    if registry is None:
        from tarot.card.details import CardDetailsRegistry

        registry = CardDetailsRegistry()

    loaded_count = 0
    failed_cards = []

    # Load all cards from the deck
    for card in deck.cards:
        if load_card_details(card, registry):
            loaded_count += 1
            if verbose:
                print(f"✓ Loaded: {card.name}")
        else:
            failed_cards.append(card.name)
            if verbose:
                print(f"✗ Failed: {card.name}")

    if verbose and failed_cards:
        print(f"\n{len(failed_cards)} cards failed to load:")
        for name in failed_cards:
            print(f"  - {name}")

    return loaded_count


def get_cards_by_suit(deck: "Deck", suit_name: str) -> List["Card"]:
    """
    Get all cards from a specific suit in the deck.

    Args:
        deck: The Deck object
        suit_name: The suit name ("Cups", "Pentacles", "Swords", "Wands")

    Returns:
        List of Card objects from that suit

    Example:
        >>> from tarot import Deck
        >>> from tarot.card.loader import get_cards_by_suit
        >>> deck = Deck()
        >>> swords = get_cards_by_suit(deck, "Swords")
        >>> print(len(swords))  # Should be 14
        14
    """
    if hasattr(deck, "suit") and callable(deck.suit):
        # Deck has a suit method, use it
        return deck.suit(suit_name)

    # Fallback: filter cards manually
    return [
        card
        for card in deck.cards
        if hasattr(card, "suit") and card.suit and card.suit.name == suit_name
    ]


def filter_cards_by_keywords(cards: List["Card"], keyword: str) -> List["Card"]:
    """
    Filter a list of cards by keyword.

    Args:
        cards: List of Card objects to filter
        keyword: The keyword to search for (case-insensitive)

    Returns:
        List of cards that have the keyword

    Example:
        >>> from tarot import Deck
        >>> deck = Deck()
        >>> all_cards = list(deck.major.cards()) + list(deck.minor.cups.cards())
        >>> love_cards = filter_cards_by_keywords(all_cards, "love")
    """
    keyword_lower = keyword.lower()
    return [
        card
        for card in cards
        if hasattr(card, "keywords")
        and card.keywords
        and any(keyword_lower in kw.lower() for kw in card.keywords)
    ]


def print_card_details(card: "Card", include_reversed: bool = False) -> None:
    """
    Pretty print card details to console.

    Args:
        card: The Card object to print
        include_reversed: If True, also print reversed keywords and interpretation

    Example:
        >>> from tarot import Deck
        >>> deck = Deck()
        >>> card = deck.major[0]  # The Fool
        >>> print_card_details(card)
    """
    print(f"\n{'=' * 60}")
    print(f"  {card.name}")
    print(f"{'=' * 60}")

    # Define attributes to print with their formatting
    attributes = {
        "explanation": ("Explanation", False),
        "interpretation": ("Interpretation", False),
        "guidance": ("Guidance", False),
    }

    # Add reversed attributes only if requested
    if include_reversed:
        attributes["reversed_interpretation"] = ("Reversed Interpretation", False)

    # List attributes (joined with commas)
    list_attributes = {
        "keywords": "Keywords",
        "reversed_keywords": ("Reversed Keywords", include_reversed),
    }

    # Numeric attributes
    numeric_attributes = {
        "numerology": "Numerology",
    }

    # Print text attributes
    for attr_name, (display_name, _) in attributes.items():
        if hasattr(card, attr_name):
            value = getattr(card, attr_name)
            if value:
                if attr_name == "explanation" and isinstance(value, dict):
                    print(f"\n{display_name}:")
                    if "summary" in value:
                        print(f"Summary: {value['summary']}")
                    if "waite" in value:
                        print(f"Waite: {value['waite']}")
                    # Print other keys if any
                    for k, v in value.items():
                        if k not in ["summary", "waite"]:
                            print(f"{k.capitalize()}: {v}")
                else:
                    print(f"\n{display_name}:\n{value}")

    # Print list attributes
    for attr_name, display_info in list_attributes.items():
        if isinstance(display_info, tuple):
            display_name, should_show = display_info
            if not should_show:
                continue
        else:
            display_name = display_info

        if hasattr(card, attr_name):
            value = getattr(card, attr_name)
            if value:
                print(f"\n{display_name}: {', '.join(value)}")

    # Print numeric attributes
    for attr_name, display_name in numeric_attributes.items():
        if hasattr(card, attr_name):
            value = getattr(card, attr_name)
            if value is not None:
                print(f"\n{display_name}: {value}")

    print(f"\n{'=' * 60}\n")


def get_card_info(
    card_name: str, registry: Optional["CardDetailsRegistry"] = None
) -> Optional[dict]:
    """
    Get card information by card name.

    Args:
        card_name: The name of the card (e.g., "Princess of Swords")
        registry: Optional CardDetailsRegistry. If not provided, creates a new one.

    Returns:
        Dictionary containing card details, or None if not found

    Example:
        >>> from tarot.card.loader import get_card_info
        >>> info = get_card_info("Princess of Swords")
        >>> if info:
        ...     print(info['explanation'])
    """
    if registry is None:
        from tarot.card.details import CardDetailsRegistry

        registry = CardDetailsRegistry()

    return registry.get(card_name)
