"""Card search service with filters."""
from typing import List, Dict, Any, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, or_, and_
from sqlalchemy.orm import selectinload

from app.models.mtg_models import MtgCard, MtgSet
from app.models.mirror_models import MtgCardMirror


class CardSearchService:
    """Card search service with filters."""

    @staticmethod
    async def search_cards(
        db: AsyncSession,
        query: str,
        card_type: Optional[str] = None,
        set_code: Optional[str] = None,
        color: Optional[str] = None,
        limit: int = 100,
        offset: int = 0,
    ) -> Dict[str, Any]:
        """
        Search cards with filters.
        
        Args:
            db: Database session
            query: Search query (name, type, mana cost)
            card_type: Filter by card type
            set_code: Filter by set code
            color: Filter by card color
            limit: Maximum results
            offset: Number of results to skip
            
        Returns:
            Dictionary with search results and metadata
        """
        # Build conditions
        conditions = [
            or_(
                MtgCard.name.ilike(f"%{query}%"),
                MtgCard.type_line.ilike(f"%{query}%"),
                MtgCard.mana_cost.ilike(f"%{query}%"),
            )
        ]

        if card_type:
            conditions.append(MtgCard.type_line.ilike(f"%{card_type}%"))

        if set_code:
            conditions.append(MtgCard.set_code == set_code)

        if color:
            # Parse color string (e.g., "WU" for white-blue)
            colors = [c.strip() for c in color.upper().split(",")]
            for c in colors:
                if c in ["W", "U", "B", "R", "G"]:
                    conditions.append(MtgCard.colors.ilike(f"%{c}%"))

        # Count total results
        count_stmt = select(MtgCard).where(*conditions)
        total_result = await db.execute(count_stmt)
        total = len(total_result.scalars().all())

        # Fetch results with pagination
        stmt = select(MtgCard).where(*conditions).offset(offset).limit(limit)
        result = await db.execute(stmt)
        cards = result.scalars().all()

        # Format results
        card_list = []
        for card in cards:
            card_data = {
                "id": card.id,
                "name": card.name,
                "mana_cost": card.mana_cost,
                "type_line": card.type_line,
                "oracle_text": card.oracle_text,
                "power": card.power,
                "toughness": card.toughness,
                "rarity": card.rarity,
                "layout": card.layout,
                "colors": card.colors,
                "set_code": card.set_code,
                "set_name": card.set_name,
            }
            card_list.append(card_data)

        return {
            "cards": card_list,
            "total": total,
            "page": offset // limit + 1,
            "page_size": limit,
            "total_pages": (total + limit - 1) // limit,
        }

    @staticmethod
    async def get_card_by_id(db: AsyncSession, card_id: int) -> Optional[Dict[str, Any]]:
        """
        Get a card by its ID.
        
        Args:
            db: Database session
            card_id: Card ID
            
        Returns:
            Card data dictionary or None
        """
        stmt = select(MtgCard).where(MtgCard.id == card_id)
        result = await db.execute(stmt)
        card = result.scalar_one_or_none()

        if not card:
            return None

        return {
            "id": card.id,
            "name": card.name,
            "mana_cost": card.mana_cost,
            "type_line": card.type_line,
            "oracle_text": card.oracle_text,
            "power": card.power,
            "toughness": card.toughness,
            "rarity": card.rarity,
            "layout": card.layout,
            "colors": card.colors,
            "set_code": card.set_code,
            "set_name": card.set_name,
            "identifiers": card.identifiers,
            "images": card.images,
        }

    @staticmethod
    async def get_sets(db: AsyncSession) -> List[Dict[str, Any]]:
        """
        Get all available sets.
        
        Args:
            db: Database session
            
        Returns:
            List of set data dictionaries
        """
        stmt = select(MtgSet).order_by(MtgSet.name)
        result = await db.execute(stmt)
        sets = result.scalars().all()

        return [
            {
                "id": s.id,
                "name": s.name,
                "code": s.code,
                "release_date": s.release_date,
                "card_count": s.card_count,
            }
            for s in sets
        ]

    @staticmethod
    async def get_card_types(db: AsyncSession) -> List[str]:
        """
        Get all unique card types.
        
        Args:
            db: Database session
            
        Returns:
            List of unique card types
        """
        stmt = select(MtgCard.type_line).distinct()
        result = await db.execute(stmt)
        types = result.scalars().all()
        return list(types)

    @staticmethod
    async def get_card_rarities(db: AsyncSession) -> List[str]:
        """
        Get all unique card rarities.
        
        Args:
            db: Database session
            
        Returns:
            List of unique rarities
        """
        stmt = select(MtgCard.rarity).distinct()
        result = await db.execute(stmt)
        rarities = result.scalars().all()
        return list(rarities)
