"""
Card interaction router for MTG card interaction database.

Provides endpoints for searching card synergies, counters, evolutions,
and getting recommendations based on card interactions.
"""
from typing import Optional, List, Dict, Any
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import text

from app.core.database import mtg_get_db
from app.core.redis_client import cache_get, cache_set

router = APIRouter(prefix="/interactions", tags=["Card Interactions"])


@router.get("/synergies/{card_id}")
async def get_card_synergies(
    card_id: int,
    synergy_type: Optional[str] = Query(None, description="Filter by synergy type (archetype, mechanic, mana, combo)"),
    min_strength: int = Query(1, ge=1, le=5, description="Minimum synergy strength"),
    limit: int = Query(100, ge=1, le=500, description="Maximum results"),
    offset: int = Query(0, ge=0, description="Number of results to skip"),
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Get synergies for a specific card.
    
    Synergies are positive interactions where cards work well together.
    """
    cache_key = f"synergies:{card_id}:{synergy_type}:{min_strength}:{limit}:{offset}"
    
    try:
        cached = await cache_get(cache_key)
        if cached:
            return {"cached": True, "results": cached}
        
        # Build query
        conditions = ["card_a_id = :card_id OR card_b_id = :card_id"]
        params = {"card_id": card_id}
        
        if synergy_type:
            conditions.append("synergy_type = :synergy_type")
            params["synergy_type"] = synergy_type
        
        if min_strength:
            conditions.append("strength >= :min_strength")
            params["min_strength"] = min_strength
        
        where_clause = " AND ".join(conditions)
        
        query = f"""
            SELECT id, card_a_id, card_b_id, synergy_type, strength, notes, confidence
            FROM mtg_card_synergies
            WHERE {where_clause}
            ORDER BY strength DESC, confidence DESC
            LIMIT :limit OFFSET :offset
        """
        params["limit"] = limit
        params["offset"] = offset
        
        # Execute query
        result = await db.execute(text(query), params)
        rows = result.fetchall()
        
        synergies = []
        for row in rows:
            synergies.append({
                "id": row[0],
                "card_a_id": row[1],
                "card_b_id": row[2],
                "synergy_type": row[3],
                "strength": row[4],
                "notes": row[5],
                "confidence": row[6],
            })
        
        # Get count for pagination
        count_query = f"""
            SELECT COUNT(*)
            FROM mtg_card_synergies
            WHERE {where_clause}
        """
        count_result = await db.execute(text(count_query), params)
        total = count_result.scalar()
        
        # Cache for 10 minutes
        await cache_set(cache_key, {"synergies": synergies, "total": total}, ttl=600)
        
        return {
            "cached": False,
            "results": synergies,
            "pagination": {
                "total": total,
                "limit": limit,
                "offset": offset,
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error fetching synergies: {str(e)}")


@router.get("/counters/{card_id}")
async def get_card_counters(
    card_id: int,
    counter_type: Optional[str] = Query(None, description="Filter by counter type (color, stats, spell, keyword)"),
    min_strength: int = Query(1, ge=1, le=5, description="Minimum counter strength"),
    limit: int = Query(100, ge=1, le=500, description="Maximum results"),
    offset: int = Query(0, ge=0, description="Number of results to skip"),
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Get counters for a specific card.
    
    Counters are negative interactions where one card is disadvantaged by another.
    """
    cache_key = f"counters:{card_id}:{counter_type}:{min_strength}:{limit}:{offset}"
    
    cached = await cache_get(cache_key)
    if cached:
        return {"cached": True, "results": cached}
    
    conditions = ["card_a_id = :card_id OR card_b_id = :card_id"]
    params = {"card_id": card_id}
    
    if counter_type:
        conditions.append("counter_type = :counter_type")
        params["counter_type"] = counter_type
    
    if min_strength:
        conditions.append("strength >= :min_strength")
        params["min_strength"] = min_strength
    
    where_clause = " AND ".join(conditions)
    
    query = f"""
        SELECT id, card_a_id, card_b_id, counter_type, strength, notes, confidence
        FROM mtg_card_counters
        WHERE {where_clause}
        ORDER BY strength DESC, confidence DESC
        LIMIT :limit OFFSET :offset
    """
    params["limit"] = limit
    params["offset"] = offset
    
    result = await db.execute(text(query), params)
    rows = result.fetchall()
    
    counters = []
    for row in rows:
        counters.append({
            "id": row[0],
            "card_a_id": row[1],
            "card_b_id": row[2],
            "counter_type": row[3],
            "strength": row[4],
            "notes": row[5],
            "confidence": row[6],
        })
    
    count_query = f"""
        SELECT COUNT(*)
        FROM mtg_card_counters
        WHERE {where_clause}
    """
    count_result = await db.execute(text(count_query), params)
    total = count_result.scalar()
    
    await cache_set(cache_key, {"counters": counters, "total": total}, ttl=600)
    
    return {
        "cached": False,
        "results": counters,
        "pagination": {
            "total": total,
            "limit": limit,
            "offset": offset,
        }
    }


@router.get("/evolutions/{card_id}")
async def get_card_evolutions(
    card_id: int,
    evolution_type: Optional[str] = Query(None, description="Filter by evolution type (reprint, transform, double_sided)"),
    min_strength: int = Query(1, ge=1, le=5, description="Minimum strength"),
    limit: int = Query(100, ge=1, le=500, description="Maximum results"),
    offset: int = Query(0, ge=0, description="Number of results to skip"),
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Get evolutions for a specific card.
    
    Evolutions track when a card has been reprinted, transformed, or evolved.
    """
    cache_key = f"evolutions:{card_id}:{evolution_type}:{min_strength}:{limit}:{offset}"
    
    cached = await cache_get(cache_key)
    if cached:
        return {"cached": True, "results": cached}
    
    conditions = ["card_id = :card_id"]
    params = {"card_id": card_id}
    
    if evolution_type:
        conditions.append("evolution_type = :evolution_type")
        params["evolution_type"] = evolution_type
    
    if min_strength:
        conditions.append("strength >= :min_strength")
        params["min_strength"] = min_strength
    
    where_clause = " AND ".join(conditions)
    
    query = f"""
        SELECT id, card_id, evolved_card_id, evolution_type, strength, notes, confidence
        FROM mtg_card_evolution
        WHERE {where_clause}
        ORDER BY strength DESC, confidence DESC
        LIMIT :limit OFFSET :offset
    """
    params["limit"] = limit
    params["offset"] = offset
    
    result = await db.execute(text(query), params)
    rows = result.fetchall()
    
    evolutions = []
    for row in rows:
        evolutions.append({
            "id": row[0],
            "card_id": row[1],
            "evolved_card_id": row[2],
            "evolution_type": row[3],
            "strength": row[4],
            "notes": row[5],
            "confidence": row[6],
        })
    
    count_query = f"""
        SELECT COUNT(*)
        FROM mtg_card_evolution
        WHERE {where_clause}
    """
    count_result = await db.execute(text(count_query), params)
    total = count_result.scalar()
    
    await cache_set(cache_key, {"evolutions": evolutions, "total": total}, ttl=600)
    
    return {
        "cached": False,
        "results": evolutions,
        "pagination": {
            "total": total,
            "limit": limit,
            "offset": offset,
        }
    }


@router.get("/recommend/{card_id}")
async def get_card_recommendations(
    card_id: int,
    recommendation_type: str = Query("synergy", description="Type of recommendation (synergy, counter, evolution)"),
    limit: int = Query(10, ge=1, le=100, description="Maximum results"),
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Get interaction recommendations for a card.
    
    Provides cards that work well together or counter a specific card.
    """
    cache_key = f"recommend:{card_id}:{recommendation_type}:{limit}"
    
    cached = await cache_get(cache_key)
    if cached:
        return {"cached": True, "results": cached}
    
    if recommendation_type == "synergy":
        # Get cards that synergize with this card
        query = """
            SELECT 
                CASE WHEN card_a_id = :card_id THEN card_b_id ELSE card_a_id END as recommended_card_id,
                strength,
                synergy_type,
                confidence
            FROM mtg_card_synergies
            WHERE card_a_id = :card_id OR card_b_id = :card_id
            ORDER BY strength DESC, confidence DESC
            LIMIT :limit
        """
    elif recommendation_type == "counter":
        # Get cards that counter this card
        query = """
            SELECT 
                CASE WHEN card_a_id = :card_id THEN card_b_id ELSE card_a_id END as recommended_card_id,
                strength,
                counter_type,
                confidence
            FROM mtg_card_counters
            WHERE card_a_id = :card_id OR card_b_id = :card_id
            ORDER BY strength DESC, confidence DESC
            LIMIT :limit
        """
    elif recommendation_type == "evolution":
        # Get evolutions of this card
        query = """
            SELECT evolved_card_id as recommended_card_id,
                   strength,
                   evolution_type,
                   confidence
            FROM mtg_card_evolution
            WHERE card_id = :card_id
            ORDER BY strength DESC, confidence DESC
            LIMIT :limit
        """
    else:
        raise HTTPException(status_code=400, detail=f"Invalid recommendation type: {recommendation_type}")
    
    params = {"card_id": card_id, "limit": limit}
    
    result = await db.execute(text(query), params)
    rows = result.fetchall()
    
    recommendations = []
    for row in rows:
        recommendations.append({
            "recommended_card_id": row[0],
            "strength": row[1],
            "type": recommendation_type,
            "subtype": row[2],
            "confidence": row[3],
        })
    
    await cache_set(cache_key, recommendations, ttl=900)
    
    return {
        "cached": False,
        "results": recommendations,
    }


@router.get("/search/synergies")
async def search_synergies(
    card_a_id: Optional[int] = Query(None, description="Card A ID"),
    card_b_id: Optional[int] = Query(None, description="Card B ID"),
    synergy_type: Optional[str] = Query(None, description="Filter by synergy type"),
    min_strength: int = Query(1, ge=1, le=5, description="Minimum strength"),
    min_confidence: float = Query(0.0, ge=0.0, le=1.0, description="Minimum confidence"),
    limit: int = Query(100, ge=1, le=1000, description="Maximum results"),
    offset: int = Query(0, ge=0, description="Number of results to skip"),
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Search synergies with multiple filters.
    """
    cache_key = f"search_synergies:{card_a_id}:{card_b_id}:{synergy_type}:{min_strength}:{min_confidence}:{limit}:{offset}"
    
    cached = await cache_get(cache_key)
    if cached:
        return {"cached": True, "results": cached}
    
    conditions = []
    params = {}
    
    if card_a_id:
        conditions.append("card_a_id = :card_a_id")
        params["card_a_id"] = card_a_id
    
    if card_b_id:
        conditions.append("card_b_id = :card_b_id")
        params["card_b_id"] = card_b_id
    
    if synergy_type:
        conditions.append("synergy_type = :synergy_type")
        params["synergy_type"] = synergy_type
    
    if min_strength:
        conditions.append("strength >= :min_strength")
        params["min_strength"] = min_strength
    
    if min_confidence:
        conditions.append("confidence >= :min_confidence")
        params["min_confidence"] = min_confidence
    
    where_clause = " AND ".join(conditions) if conditions else "TRUE"
    
    query = f"""
        SELECT id, card_a_id, card_b_id, synergy_type, strength, notes, confidence
        FROM mtg_card_synergies
        WHERE {where_clause}
        ORDER BY strength DESC, confidence DESC
        LIMIT :limit OFFSET :offset
    """
    params["limit"] = limit
    params["offset"] = offset
    
    result = await db.execute(text(query), params)
    rows = result.fetchall()
    
    synergies = []
    for row in rows:
        synergies.append({
            "id": row[0],
            "card_a_id": row[1],
            "card_b_id": row[2],
            "synergy_type": row[3],
            "strength": row[4],
            "notes": row[5],
            "confidence": row[6],
        })
    
    count_query = f"""
        SELECT COUNT(*)
        FROM mtg_card_synergies
        WHERE {where_clause}
    """
    count_result = await db.execute(text(count_query), params)
    total = count_result.scalar()
    
    await cache_set(cache_key, {"synergies": synergies, "total": total}, ttl=600)
    
    return {
        "cached": False,
        "results": synergies,
        "pagination": {
            "total": total,
            "limit": limit,
            "offset": offset,
        }
    }


@router.get("/search/counters")
async def search_counters(
    card_a_id: Optional[int] = Query(None, description="Card A ID"),
    card_b_id: Optional[int] = Query(None, description="Card B ID"),
    counter_type: Optional[str] = Query(None, description="Filter by counter type"),
    min_strength: int = Query(1, ge=1, le=5, description="Minimum strength"),
    min_confidence: float = Query(0.0, ge=0.0, le=1.0, description="Minimum confidence"),
    limit: int = Query(100, ge=1, le=1000, description="Maximum results"),
    offset: int = Query(0, ge=0, description="Number of results to skip"),
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Search counters with multiple filters.
    """
    cache_key = f"search_counters:{card_a_id}:{card_b_id}:{counter_type}:{min_strength}:{min_confidence}:{limit}:{offset}"
    
    cached = await cache_get(cache_key)
    if cached:
        return {"cached": True, "results": cached}
    
    conditions = []
    params = {}
    
    if card_a_id:
        conditions.append("card_a_id = :card_a_id")
        params["card_a_id"] = card_a_id
    
    if card_b_id:
        conditions.append("card_b_id = :card_b_id")
        params["card_b_id"] = card_b_id
    
    if counter_type:
        conditions.append("counter_type = :counter_type")
        params["counter_type"] = counter_type
    
    if min_strength:
        conditions.append("strength >= :min_strength")
        params["min_strength"] = min_strength
    
    if min_confidence:
        conditions.append("confidence >= :min_confidence")
        params["min_confidence"] = min_confidence
    
    where_clause = " AND ".join(conditions) if conditions else "TRUE"
    
    query = f"""
        SELECT id, card_a_id, card_b_id, counter_type, strength, notes, confidence
        FROM mtg_card_counters
        WHERE {where_clause}
        ORDER BY strength DESC, confidence DESC
        LIMIT :limit OFFSET :offset
    """
    params["limit"] = limit
    params["offset"] = offset
    
    result = await db.execute(text(query), params)
    rows = result.fetchall()
    
    counters = []
    for row in rows:
        counters.append({
            "id": row[0],
            "card_a_id": row[1],
            "card_b_id": row[2],
            "counter_type": row[3],
            "strength": row[4],
            "notes": row[5],
            "confidence": row[6],
        })
    
    count_query = f"""
        SELECT COUNT(*)
        FROM mtg_card_counters
        WHERE {where_clause}
    """
    count_result = await db.execute(text(count_query), params)
    total = count_result.scalar()
    
    await cache_set(cache_key, {"counters": counters, "total": total}, ttl=600)
    
    return {
        "cached": False,
        "results": counters,
        "pagination": {
            "total": total,
            "limit": limit,
            "offset": offset,
        }
    }


@router.get("/search/evolutions")
async def search_evolutions(
    card_id: Optional[int] = Query(None, description="Card ID"),
    evolved_card_id: Optional[int] = Query(None, description="Evolved Card ID"),
    evolution_type: Optional[str] = Query(None, description="Filter by evolution type"),
    min_strength: int = Query(1, ge=1, le=5, description="Minimum strength"),
    min_confidence: float = Query(0.0, ge=0.0, le=1.0, description="Minimum confidence"),
    limit: int = Query(100, ge=1, le=1000, description="Maximum results"),
    offset: int = Query(0, ge=0, description="Number of results to skip"),
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Search evolutions with multiple filters.
    """
    cache_key = f"search_evolutions:{card_id}:{evolved_card_id}:{evolution_type}:{min_strength}:{min_confidence}:{limit}:{offset}"
    
    cached = await cache_get(cache_key)
    if cached:
        return {"cached": True, "results": cached}
    
    conditions = []
    params = {}
    
    if card_id:
        conditions.append("card_id = :card_id")
        params["card_id"] = card_id
    
    if evolved_card_id:
        conditions.append("evolved_card_id = :evolved_card_id")
        params["evolved_card_id"] = evolved_card_id
    
    if evolution_type:
        conditions.append("evolution_type = :evolution_type")
        params["evolution_type"] = evolution_type
    
    if min_strength:
        conditions.append("strength >= :min_strength")
        params["min_strength"] = min_strength
    
    if min_confidence:
        conditions.append("confidence >= :min_confidence")
        params["min_confidence"] = min_confidence
    
    where_clause = " AND ".join(conditions) if conditions else "TRUE"
    
    query = f"""
        SELECT id, card_id, evolved_card_id, evolution_type, strength, notes, confidence
        FROM mtg_card_evolution
        WHERE {where_clause}
        ORDER BY strength DESC, confidence DESC
        LIMIT :limit OFFSET :offset
    """
    params["limit"] = limit
    params["offset"] = offset
    
    result = await db.execute(text(query), params)
    rows = result.fetchall()
    
    evolutions = []
    for row in rows:
        evolutions.append({
            "id": row[0],
            "card_id": row[1],
            "evolved_card_id": row[2],
            "evolution_type": row[3],
            "strength": row[4],
            "notes": row[5],
            "confidence": row[6],
        })
    
    count_query = f"""
        SELECT COUNT(*)
        FROM mtg_card_evolution
        WHERE {where_clause}
    """
    count_result = await db.execute(text(count_query), params)
    total = count_result.scalar()
    
    await cache_set(cache_key, {"evolutions": evolutions, "total": total}, ttl=600)
    
    return {
        "cached": False,
        "results": evolutions,
        "pagination": {
            "total": total,
            "limit": limit,
            "offset": offset,
        }
    }


@router.get("/stats/{card_id}")
async def get_card_interaction_stats(
    card_id: int,
    db: AsyncSession = Depends(mtg_get_db),
):
    """
    Get aggregated interaction statistics for a card.
    """
    cache_key = f"interaction_stats:{card_id}"
    
    cached = await cache_get(cache_key)
    if cached:
        return {"cached": True, "results": cached}
    
    query = """
        SELECT 
            card_id,
            total_synergies,
            total_counters,
            total_evolutions,
            total_synergy_strength,
            avg_synergy_strength
        FROM mtg_card_interaction_stats
        WHERE card_id = :card_id
    """
    params = {"card_id": card_id}
    
    result = await db.execute(text(query), params)
    row = result.fetchone()
    
    if not row:
        return {
            "cached": False,
            "results": {
                "card_id": card_id,
                "total_synergies": 0,
                "total_counters": 0,
                "total_evolutions": 0,
                "total_synergy_strength": 0,
                "avg_synergy_strength": 0,
            }
        }
    
    stats = {
        "card_id": row[0],
        "total_synergies": row[1],
        "total_counters": row[2],
        "total_evolutions": row[3],
        "total_synergy_strength": row[4],
        "avg_synergy_strength": row[5],
    }
    
    await cache_set(cache_key, stats, ttl=1800)
    
    return {
        "cached": False,
        "results": stats,
    }
