import json
from openai import AsyncOpenAI

from app.core.config import settings
from app.schemas import ChallengeGenerated


class GPTService:
    """Service for generating challenges using OpenAI GPT"""

    def __init__(self):
        self.client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)

    async def generate_challenges(
        self,
        games: list[dict]
    ) -> dict[int, list[ChallengeGenerated]]:
        """
        Generate challenges for multiple games in one API call.

        Args:
            games: List of dicts with keys: id, title, genre

        Returns:
            Dict mapping game_id to list of generated challenges
        """
        if not games:
            return {}

        games_text = "\n".join([
            f"- {g['title']}" + (f" (жанр: {g['genre']})" if g.get('genre') else "")
            for g in games
        ])

        prompt = f"""Ты — эксперт по видеоиграм. Сгенерируй по 6 КОНКРЕТНЫХ челленджей для каждой из следующих игр:

{games_text}

ВАЖНО:
- ВСЕ ТЕКСТЫ (title, description, proof_hint) ОБЯЗАТЕЛЬНО ПИШИ НА РУССКОМ ЯЗЫКЕ!
- Используй интернет для поиска актуальной информации об играх
- Челленджи должны быть СПЕЦИФИЧНЫМИ для каждой игры!
- Используй РЕАЛЬНЫЕ названия локаций, боссов, персонажей, миссий, уровней из игры
- Основывайся на том, какие челленджи РЕАЛЬНО делают игроки в этой игре
- НЕ генерируй абстрактные челленджи типа "пройди уровень" или "убей 10 врагов"

Требования по сложности ДЛЯ КАЖДОЙ ИГРЫ:
- 2 лёгких (15-30 мин): простые задачи
- 2 средних (1-2 часа): требуют навыка
- 2 сложных (3-12 часов): серьёзный челлендж

Формат ответа — JSON с объектом где ключи это ТОЧНЫЕ названия игр, как они указаны в запросе:
{{
  "Название игры 1": {{
    "challenges": [
      {{"title": "...", "description": "...", "type": "completion|no_death|speedrun|collection|achievement|challenge_run", "difficulty": "easy|medium|hard", "points": 50, "estimated_time": 30, "proof_type": "screenshot|video|steam", "proof_hint": "..."}}
    ]
  }},
  "Название игры 2": {{
    "challenges": [...]
  }}
}}

points: easy=20-40, medium=45-75, hard=90-150
Ответь ТОЛЬКО JSON. ОПИСАНИЕ И НАЗВАНИЕ ЧЕЛЛЕНДЖА ТОЛЬКО НА РУССКОМ ЯЗЫКЕ!"""

        response = await self.client.chat.completions.create(
            model="gpt-5",
            messages=[{"role": "user", "content": prompt}],
            response_format={"type": "json_object"},
        )

        content = response.choices[0].message.content
        data = json.loads(content)

        # Map game titles to IDs (case-insensitive, strip whitespace)
        title_to_id = {g['title'].lower().strip(): g['id'] for g in games}

        # Also keep original titles for logging
        id_to_title = {g['id']: g['title'] for g in games}

        print(f"[GPT] Requested games: {[g['title'] for g in games]}")
        print(f"[GPT] Response keys: {list(data.keys())}")

        result = {}
        for game_title, game_data in data.items():
            # Try exact match first, then case-insensitive
            game_id = title_to_id.get(game_title.lower().strip())

            if not game_id:
                # Try partial match if exact match fails
                for stored_title, gid in title_to_id.items():
                    if stored_title in game_title.lower() or game_title.lower() in stored_title:
                        game_id = gid
                        break

            if not game_id:
                print(f"[GPT] Could not match game: '{game_title}'")
                continue

            challenges = []
            for ch in game_data.get("challenges", []):
                challenges.append(self._parse_challenge(ch))

            result[game_id] = challenges
            print(f"[GPT] Generated {len(challenges)} challenges for '{id_to_title.get(game_id)}'")

        return result

    def _parse_challenge(self, ch: dict) -> ChallengeGenerated:
        """Parse and validate a single challenge from GPT response"""
        ch_type = ch.get("type", "completion")
        if ch_type not in ["completion", "no_death", "speedrun", "collection", "achievement", "challenge_run"]:
            ch_type = "completion"

        difficulty = ch.get("difficulty", "medium")
        if difficulty not in ["easy", "medium", "hard"]:
            difficulty = "medium"

        proof_type = ch.get("proof_type", "screenshot")
        if proof_type not in ["screenshot", "video", "steam"]:
            proof_type = "screenshot"

        points = ch.get("points", 30)
        if not isinstance(points, int) or points < 1:
            points = 30
        if difficulty == "easy":
            points = max(20, min(40, points))
        elif difficulty == "medium":
            points = max(45, min(75, points))
        elif difficulty == "hard":
            points = max(90, min(150, points))

        return ChallengeGenerated(
            title=ch.get("title", "Unnamed Challenge")[:100],
            description=ch.get("description", "Complete the challenge"),
            type=ch_type,
            difficulty=difficulty,
            points=points,
            estimated_time=ch.get("estimated_time"),
            proof_type=proof_type,
            proof_hint=ch.get("proof_hint"),
        )


gpt_service = GPTService()
