# ==============================================
# Breakpilot Drive - Game API Core Routes
# ==============================================
# Core game endpoints: learning level, difficulty, quiz questions.
# Session/stats/leaderboard routes are in game_session_routes.py.
# Extracted from game_api.py for file-size compliance.

from fastapi import APIRouter, HTTPException, Query, Depends, Request
from typing import List, Optional, Dict, Any
from datetime import datetime
import random
import uuid
import os
import logging

from .game_models import (
    LearningLevel,
    GameDifficulty,
    QuizQuestion,
    QuizAnswer,
    GameSession,
    SessionResponse,
    DIFFICULTY_MAPPING,
    SAMPLE_QUESTIONS,
)

logger = logging.getLogger(__name__)

# Feature flags
USE_DATABASE = os.getenv("GAME_USE_DATABASE", "true").lower() == "true"
REQUIRE_AUTH = os.getenv("GAME_REQUIRE_AUTH", "false").lower() == "true"

router = APIRouter(prefix="/api/game", tags=["Breakpilot Drive"])


# ==============================================
# Auth Dependency (Optional)
# ==============================================

async def get_optional_current_user(request: Request) -> Optional[Dict[str, Any]]:
    """
    Optional auth dependency for Game API.

    If GAME_REQUIRE_AUTH=true: Requires valid JWT token
    If GAME_REQUIRE_AUTH=false: Returns None (anonymous access)

    In development mode without auth, returns demo user.
    """
    if not REQUIRE_AUTH:
        return None

    try:
        from auth import get_current_user
        return await get_current_user(request)
    except ImportError:
        logger.warning("Auth module not available")
        return None
    except HTTPException:
        raise  # Re-raise auth errors
    except Exception as e:
        logger.error(f"Auth error: {e}")
        raise HTTPException(status_code=401, detail="Authentication failed")


def get_user_id_from_auth(
    user: Optional[Dict[str, Any]],
    requested_user_id: str
) -> str:
    """
    Get the effective user ID, respecting auth when enabled.

    If auth is enabled and user is authenticated:
    - Returns user's own ID if requested_user_id matches
    - For parents: allows access to child IDs from token
    - For teachers: allows access to student IDs (future)

    If auth is disabled: Returns requested_user_id as-is
    """
    if not REQUIRE_AUTH or user is None:
        return requested_user_id

    user_id = user.get("user_id", "")

    # Same user - always allowed
    if requested_user_id == user_id:
        return user_id

    # Check for parent accessing child data
    children_ids = user.get("raw_claims", {}).get("children_ids", [])
    if requested_user_id in children_ids:
        return requested_user_id

    # Check for teacher accessing student data (future)
    realm_roles = user.get("realm_roles", [])
    if "lehrer" in realm_roles or "teacher" in realm_roles:
        # Teachers can access any student in their class (implement class check later)
        return requested_user_id

    # Admin bypass
    if "admin" in realm_roles:
        return requested_user_id

    # Not authorized
    raise HTTPException(
        status_code=403,
        detail="Not authorized to access this user's data"
    )


# In-Memory Session Storage (Fallback wenn DB nicht verfuegbar)
_sessions: dict[str, GameSession] = {}
_user_levels: dict[str, LearningLevel] = {}

# Database integration
_game_db = None

async def get_game_database():
    """Get game database instance with lazy initialization."""
    global _game_db
    if not USE_DATABASE:
        return None
    if _game_db is None:
        try:
            from game.database import get_game_db
            _game_db = await get_game_db()
            logger.info("Game database initialized")
        except Exception as e:
            logger.warning(f"Game database not available, using in-memory: {e}")
    return _game_db


# ==============================================
# API Endpunkte
# ==============================================

@router.get("/learning-level/{user_id}", response_model=LearningLevel)
async def get_learning_level(
    user_id: str,
    user: Optional[Dict[str, Any]] = Depends(get_optional_current_user)
) -> LearningLevel:
    """
    Holt das aktuelle Lernniveau eines Benutzers aus Breakpilot.

    - Wird beim Spielstart aufgerufen um Schwierigkeit anzupassen
    - Gibt Level 1-5 zurueck (1=Anfaenger, 5=Fortgeschritten)
    - Cached Werte fuer schnellen Zugriff
    - Speichert in PostgreSQL wenn verfuegbar
    - Bei GAME_REQUIRE_AUTH=true: Nur eigene oder Kind-Daten
    """
    # Verify access rights
    user_id = get_user_id_from_auth(user, user_id)

    # Try database first
    db = await get_game_database()
    if db:
        state = await db.get_learning_state(user_id)
        if state:
            return LearningLevel(
                user_id=user_id,
                overall_level=state.overall_level,
                math_level=state.math_level,
                german_level=state.german_level,
                english_level=state.english_level,
                last_updated=state.updated_at or datetime.now()
            )

        # Create new state in database
        new_state = await db.create_or_update_learning_state(
            student_id=user_id,
            overall_level=3,
            math_level=3.0,
            german_level=3.0,
            english_level=3.0
        )
        if new_state:
            return LearningLevel(
                user_id=user_id,
                overall_level=new_state.overall_level,
                math_level=new_state.math_level,
                german_level=new_state.german_level,
                english_level=new_state.english_level,
                last_updated=new_state.updated_at or datetime.now()
            )

    # Fallback to in-memory
    if user_id in _user_levels:
        return _user_levels[user_id]

    # Standard-Level fuer neue Benutzer
    default_level = LearningLevel(
        user_id=user_id,
        overall_level=3,  # Mittleres Level als Default
        math_level=3.0,
        german_level=3.0,
        english_level=3.0,
        last_updated=datetime.now()
    )
    _user_levels[user_id] = default_level
    return default_level


@router.get("/difficulty/{level}", response_model=GameDifficulty)
async def get_game_difficulty(level: int) -> GameDifficulty:
    """
    Gibt Spielparameter basierend auf Lernniveau zurueck.

    Level 1-5 werden auf Spielgeschwindigkeit, Hindernisfrequenz,
    Fragen-Schwierigkeit etc. gemappt.
    """
    if level < 1 or level > 5:
        raise HTTPException(status_code=400, detail="Level muss zwischen 1 und 5 sein")

    return DIFFICULTY_MAPPING[level]


@router.get("/quiz/questions", response_model=List[QuizQuestion])
async def get_quiz_questions(
    difficulty: int = Query(3, ge=1, le=5, description="Schwierigkeitsgrad 1-5"),
    count: int = Query(10, ge=1, le=50, description="Anzahl der Fragen"),
    subject: Optional[str] = Query(None, description="Fach: math, german, english, oder None fuer gemischt"),
    mode: Optional[str] = Query(None, description="Quiz-Modus: quick (waehrend Fahrt), pause (Spiel pausiert), oder None fuer beide")
) -> List[QuizQuestion]:
    """
    Holt Quiz-Fragen fuer das Spiel.

    - Filtert nach Schwierigkeitsgrad (+/- 1 Level)
    - Optional nach Fach filterbar
    - Optional nach Modus: "quick" (visuelle Fragen waehrend Fahrt) oder "pause" (Denkaufgaben)
    - Gibt zufaellige Auswahl zurueck
    """
    # Fragen nach Schwierigkeit filtern (+/- 1 Level Toleranz)
    filtered = [
        q for q in SAMPLE_QUESTIONS
        if abs(q.difficulty - difficulty) <= 1
        and (subject is None or q.subject == subject)
        and (mode is None or q.quiz_mode == mode)
    ]

    if not filtered:
        # Fallback: Alle Fragen wenn keine passenden gefunden
        filtered = [q for q in SAMPLE_QUESTIONS if mode is None or q.quiz_mode == mode]

    # Zufaellige Auswahl
    selected = random.sample(filtered, min(count, len(filtered)))
    return selected


@router.get("/quiz/visual-triggers")
async def get_visual_triggers() -> List[dict]:
    """
    Gibt alle verfuegbaren visuellen Trigger zurueck.

    Unity verwendet diese Liste um zu wissen, welche Objekte
    im Spiel Quiz-Fragen ausloesen koennen.
    """
    triggers = {}
    for q in SAMPLE_QUESTIONS:
        if q.visual_trigger and q.quiz_mode == "quick":
            if q.visual_trigger not in triggers:
                triggers[q.visual_trigger] = {
                    "trigger": q.visual_trigger,
                    "question_count": 0,
                    "difficulties": set(),
                    "subjects": set()
                }
            triggers[q.visual_trigger]["question_count"] += 1
            triggers[q.visual_trigger]["difficulties"].add(q.difficulty)
            triggers[q.visual_trigger]["subjects"].add(q.subject)

    # Sets zu Listen konvertieren fuer JSON
    return [
        {
            "trigger": t["trigger"],
            "question_count": t["question_count"],
            "difficulties": list(t["difficulties"]),
            "subjects": list(t["subjects"])
        }
        for t in triggers.values()
    ]


@router.post("/quiz/answer")
async def submit_quiz_answer(answer: QuizAnswer) -> dict:
    """
    Verarbeitet eine Quiz-Antwort (fuer Echtzeit-Feedback).

    In der finalen Version: Speichert in Session, updated Analytics.
    """
    return {
        "question_id": answer.question_id,
        "was_correct": answer.was_correct,
        "points": 500 if answer.was_correct else -100,
        "message": "Richtig! Weiter so!" if answer.was_correct else "Nicht ganz, versuch es nochmal!"
    }


