"""Card database service for importing and querying card data."""
import httpx
from typing import List, Dict, Optional
from dataclasses import dataclass
from enum import Enum


class CardType(str, Enum):
    """Card types from Magic: The Gathering."""
    CREATURES = "Creature"
    INSTANT = "Instant"
    SORCERY = "Sorcery"
    ENCHANTMENT = "Enchantment"
    ARTIFACT = "Artifact"
    PLANE = "Plane"
    PLANESWALKER = "Planeswalker"
    LAND = "Land"
    BATTLE = "Battle"


class CardColor(str, Enum):
    """Card colors."""
    WHITE = "W"
    BLUE = "U"
    BLACK = "B"
    RED = "R"
    GREEN = "G"
    COLORLESS = "C"
    MULTICOLOR = "M"
    SHARD = "S"
    WIDGET = "X"


class CardRarity(str, Enum):
    """Card rarities."""
    COMMON = "common"
    UNCOMMON = "uncommon"
    RARE = "rare"
    MYTHIC = "mythic"
    SPECIAL = "special"


@dataclass
class CardData:
    """Card information from card database."""
    id: int
    name: str
    types: List[CardType]
    colors: List[CardColor]
    rarity: CardRarity
    set_code: str
    collector_number: str
    flavor_text: Optional[str] = None
    rules_text: Optional[str] = None
    power: Optional[str] = None
    toughness: Optional[str] = None
    artist: Optional[str] = None
    image_url: Optional[str] = None
    provider_id: Optional[str] = None
    
    def __str__(self) -> str:
        return f"{self.name} ({self.set_code}-{self.collector_number})"


class CardDatabase:
    """Card database service for importing and querying card data."""
    
    def __init__(self):
        self.cards: Dict[int, CardData] = {}
        self._next_id = 1
    
    async def import_from_mtjson(self, url: str = "https://mtjson.xyz/api/5.0.0/") -> List[CardData]:
        """Import card data from MTJSON API."""
        async with httpx.AsyncClient() as client:
            response = await client.get(url)
            response.raise_for_status()
            data = response.json()
            
            imported_cards = []
            for card_data in data:
                card = self._parse_mtjson_card(card_data)
                self.cards[self._next_id] = card
                imported_cards.append(card)
                self._next_id += 1
            
            return imported_cards
    
    def _parse_mtjson_card(self, data: dict) -> CardData:
        """Parse MTJSON card data into CardData."""
        card_id = self._next_id
        
        # Extract types
        types = []
        if "types" in data:
            for type_str in data["types"]:
                try:
                    types.append(CardType(type_str))
                except ValueError:
                    pass
        
        # Extract colors
        colors = []
        if "colors" in data:
            for color_str in data["colors"]:
                try:
                    colors.append(CardColor(color_str))
                except ValueError:
                    pass
        
        # Extract rarity
        rarity = CardRarity.COMMON
        if "rarity" in data:
            try:
                rarity = CardRarity(data["rarity"].lower())
            except ValueError:
                pass
        
        # Extract set and collector number
        set_code = ""
        collector_number = ""
        if "set" in data:
            set_code = data["set"]
        if "collectorNumber" in data:
            collector_number = data["collectorNumber"]
        
        # Extract image URL
        image_url = None
        if "imageUris" in data and "normal" in data["imageUris"]:
            image_url = data["imageUris"]["normal"]
        
        return CardData(
            id=card_id,
            name=data.get("name", ""),
            types=types,
            colors=colors,
            rarity=rarity,
            set_code=set_code,
            collector_number=collector_number,
            flavor_text=data.get("flavorText"),
            rules_text=data.get("rulesText"),
            power=data.get("power"),
            toughness=data.get("toughness"),
            artist=data.get("artist"),
            image_url=image_url,
            provider_id=data.get("multiverseId"),
        )
    
    def get_card_by_id(self, card_id: int) -> Optional[CardData]:
        """Get card by ID."""
        return self.cards.get(card_id)
    
    def get_card_by_name(self, name: str) -> List[CardData]:
        """Get cards by name (case-insensitive)."""
        name_lower = name.lower()
        return [card for card in self.cards.values() if card.name.lower() == name_lower]
    
    def search_cards(
        self,
        query: str = "",
        card_type: Optional[CardType] = None,
        color: Optional[CardColor] = None,
        rarity: Optional[CardRarity] = None,
        set_code: Optional[str] = None,
        limit: int = 50,
    ) -> List[CardData]:
        """Search cards with filters."""
        results = list(self.cards.values())
        
        # Filter by query
        if query:
            query_lower = query.lower()
            results = [card for card in results if query_lower in card.name.lower()]
        
        # Filter by type
        if card_type:
            results = [card for card in results if card_type in card.types]
        
        # Filter by color
        if color:
            results = [card for card in results if color in card.colors]
        
        # Filter by rarity
        if rarity:
            results = [card for card in results if card.rarity == rarity]
        
        # Filter by set
        if set_code:
            results = [card for card in results if card.set_code == set_code.upper()]
        
        return results[:limit]
    
    def get_random_card(self) -> Optional[CardData]:
        """Get a random card from the database."""
        import random
        if not self.cards:
            return None
        return random.choice(list(self.cards.values()))
    
    def get_card_count(self) -> int:
        """Get total number of cards in database."""
        return len(self.cards)


# Singleton instance
card_database = CardDatabase()


async def import_cards() -> List[CardData]:
    """Import cards from MTJSON."""
    return await card_database.import_from_mtjson()


def search_cards(**kwargs) -> List[CardData]:
    """Search cards with filters."""
    return card_database.search_cards(**kwargs)


def get_card_by_name(name: str) -> List[CardData]:
    """Get cards by name."""
    return card_database.get_card_by_name(name)


def get_card_by_id(card_id: int) -> Optional[CardData]:
    """Get card by ID."""
    return card_database.get_card_by_id(card_id)
