"""
Server-Authoritative Gateway Synchronization Helper for FreeExile.
Coordinates zone monster streaming from WildernessEncounterEngine and
quest state synchronization from QuestEngine over WebSocket connections.
Zero-Trust Server Authority: Server is the sole source of truth for stats and progress.
"""

from __future__ import annotations

import time
from typing import Any, Dict, List, Optional

try:
    from server.world.monster_types import MonsterGenus, MonsterRank
    from server.world.quest_catalog import register_canonical_quests_and_milestones
    from server.world.quest_engine import QuestEngine
    from server.world.wilderness_encounter_engine import WildernessEncounterEngine
except ImportError:
    from world.monster_types import MonsterGenus, MonsterRank
    from world.quest_catalog import register_canonical_quests_and_milestones
    from world.quest_engine import QuestEngine
    from world.wilderness_encounter_engine import WildernessEncounterEngine


class GatewaySyncHelper:
    """Manages authoritative zone monster distribution and quest progression for WS clients."""

    def __init__(
        self,
        encounter_engine: Optional[WildernessEncounterEngine] = None,
        quest_engine: Optional[QuestEngine] = None,
    ) -> None:
        self.encounter_engine = encounter_engine or WildernessEncounterEngine()
        if quest_engine is not None:
            self.quest_engine = quest_engine
        else:
            self.quest_engine = QuestEngine()
            register_canonical_quests_and_milestones(self.quest_engine)

    def generate_zone_monsters_payload(
        self, zone_id: str, seed: int = 1000
    ) -> Dict[str, Any]:
        """Generates authoritative monster states for the requested zone."""
        packs = self.encounter_engine.generate_zone_encounter_packs(
            zone_id=zone_id, seed=seed
        )
        monsters: List[Dict[str, Any]] = []

        for pack in packs:
            # 1. Rare Pack Leader
            leader = pack.leader
            genus_name = (
                leader.genus.name
                if hasattr(leader.genus, "name")
                else str(leader.genus)
            )
            rank_name = (
                leader.rank.name if hasattr(leader.rank, "name") else str(leader.rank)
            )
            monsters.append(
                {
                    "id": f"srv_{pack.pack_id}_lead",
                    "name": leader.name,
                    "genus": genus_name,
                    "wx": round(pack.center_x, 2),
                    "wy": round(pack.center_y, 2),
                    "max_hp": leader.max_hp,
                    "hp": leader.max_hp,
                    "attack_dmg": leader.base_damage,
                    "rank": rank_name,
                    "level": leader.level,
                    "is_boss": (leader.rank == MonsterRank.BOSS),
                }
            )

            # 2. Minions from runtime states
            states = self.encounter_engine.procedural_engine.create_pack_runtime_states(
                pack
            )
            for idx, st in enumerate(states):
                if st.is_pack_leader:
                    continue
                minion = st.monster
                m_genus = (
                    minion.genus.name
                    if hasattr(minion.genus, "name")
                    else str(minion.genus)
                )
                monsters.append(
                    {
                        "id": f"srv_{pack.pack_id}_m{idx}",
                        "name": minion.name,
                        "genus": m_genus,
                        "wx": round(st.current_x, 2),
                        "wy": round(st.current_y, 2),
                        "max_hp": minion.max_hp,
                        "hp": minion.max_hp,
                        "attack_dmg": minion.base_damage,
                        "rank": "COMMON",
                        "level": minion.level,
                        "is_boss": False,
                    }
                )

        return {
            "type": "zone_monsters_sync",
            "zone_id": zone_id,
            "monsters": monsters,
            "authoritative": True,
            "timestamp": time.time() * 1000,
        }

    def get_player_quests_payload(self, player_id: str) -> Dict[str, Any]:
        """Returns authoritative active quest progress for a player."""
        self.quest_engine.initialize_player(player_id, 1)
        player_dict = self.quest_engine._player_quests.get(player_id, {})
        if not player_dict:
            self.quest_engine.accept_quest(
                player_id, "quest_norm_01_thuc_tinh_tang_kiem", 1
            )
            player_dict = self.quest_engine._player_quests.get(player_id, {})

        all_quests = list(player_dict.values())
        quest_list: List[Dict[str, Any]] = []
        for q in all_quests:
            q_def = self.quest_engine.get_quest_definition(q.quest_id)
            objs = []
            for o in q.objectives.values():
                objs.append(
                    {
                        "id": o.objective_id,
                        "desc": o.description,
                        "current": o.current_count,
                        "required": o.target_count,
                        "is_completed": o.is_completed,
                    }
                )
            status_val = (
                q.status.value if hasattr(q.status, "value") else str(q.status)
            )
            quest_list.append(
                {
                    "quest_id": q.quest_id,
                    "title": q_def.title if q_def else q.quest_id,
                    "description": q_def.description if q_def else "",
                    "status": status_val,
                    "objectives": objs,
                }
            )

        return {
            "type": "quest_sync",
            "player_id": player_id,
            "quests": quest_list,
            "authoritative": True,
            "timestamp": time.time() * 1000,
        }

    def process_kill_event(
        self, player_id: str, monster_id: str
    ) -> Dict[str, Any]:
        """Authoritatively processes monster kill and returns updated quest state."""
        updated_quest_ids = self.quest_engine.record_kill(player_id, monster_id)
        quest_data = self.get_player_quests_payload(player_id)
        return {
            "type": "quest_progress_update",
            "player_id": player_id,
            "updated_quest_ids": updated_quest_ids,
            "quests": quest_data["quests"],
            "timestamp": time.time() * 1000,
        }
