"""
Unit Test Suite for Progressive Map Scaling & Vast Endgame Labyrinth Architecture.
Validates that map dimensions, room counts, and secret chambers strictly scale
proportionally with quest progression from Act I (compact) to Pinnacle Labyrinth (vast).
"""

from __future__ import annotations
import math
import time
import pytest

from server.world.map_progression_scaler import (
    calculate_map_scale_profile,
    get_zone_scaled_dimensions,
    PROGRESSION_PROFILES,
    MapScaleProfile,
)
from server.world.procedural_map_engine import ProceduralMapEngine
from server.world.wilderness_map_generator import WildernessMapGenerator
from server.world.map_data_types import TileType


class TestProgressiveMapScaling:
    """Verifies that map scale grows monotonically from early game to endgame."""

    def test_progressive_dimensions_monotonic_growth(self) -> None:
        stages = [
            ("ACT_I_ONBOARDING", 1, None),
            ("ACT_II_EXPLORATION", 15, None),
            ("ACT_III_SANDSTORM", 35, None),
            ("ACT_IV_V_CRUCIBLE", 55, None),
            ("ENDGAME_WHITE_ATLAS", 72, 3),
            ("ENDGAME_YELLOW_RED_ATLAS", 80, 10),
            ("ENDGAME_PINNACLE_LABYRINTH", 90, 16),
        ]
        prev_area = 0
        prev_rooms = 0
        for stage_name, lvl, tier in stages:
            prof = calculate_map_scale_profile(level=lvl, map_tier=tier)
            area = prof.grid_width * prof.grid_height
            assert area > prev_area, f"Area for {stage_name} ({area}) must exceed {prev_area}"
            assert prof.max_rooms > prev_rooms, f"Max rooms for {stage_name} must exceed {prev_rooms}"
            prev_area = area
            prev_rooms = prof.max_rooms

    def test_act1_is_compact_and_onboarding_focused(self) -> None:
        prof = calculate_map_scale_profile(level=1, act_id="ACT_I_HUNGER")
        assert prof.grid_width == 60
        assert prof.grid_height == 45
        assert prof.total_tiles == 2700
        assert prof.is_labyrinth is False
        assert prof.secret_chambers == 0
        assert prof.pillar_totems == 0
        assert prof.boss_distance_min <= 40.0

    def test_endgame_tier16_is_vast_labyrinth(self) -> None:
        prof = calculate_map_scale_profile(level=90, map_tier=16)
        assert prof.grid_width == 240
        assert prof.grid_height == 180
        assert prof.total_tiles == 43200
        assert prof.is_labyrinth is True
        assert prof.secret_chambers >= 5
        assert prof.pillar_totems >= 4
        assert prof.max_rooms >= 35
        assert prof.boss_distance_min >= 200.0

    def test_secret_chambers_and_totems_scale_with_tier(self) -> None:
        act1 = calculate_map_scale_profile(level=5)
        act3 = calculate_map_scale_profile(level=30)
        t5 = calculate_map_scale_profile(level=73, map_tier=5)
        t16 = calculate_map_scale_profile(level=85, map_tier=16)

        assert act1.secret_chambers == 0
        assert act3.secret_chambers == 2
        assert t5.secret_chambers == 3
        assert t16.secret_chambers == 6

        assert act1.pillar_totems == 0
        assert act3.pillar_totems == 2
        assert t16.pillar_totems == 4


class TestVastLabyrinthProceduralSynthesis:
    """Verifies that ProceduralMapEngine synthesizes high-complexity mazes at endgame scale."""

    def test_procedural_map_engine_for_progression_act1(self) -> None:
        engine = ProceduralMapEngine.for_progression(level=5, act_id="ACT_I_HUNGER")
        assert engine.width == 60
        assert engine.height == 45
        grid = engine.generate_map(seed=42)
        assert grid.width == 60
        assert grid.height == 45
        assert len(grid.rooms) >= 5
        assert grid.boss_room is not None

    def test_procedural_map_engine_for_progression_pinnacle_labyrinth(self) -> None:
        engine = ProceduralMapEngine.for_progression(level=90, map_tier=16)
        assert engine.width == 240
        assert engine.height == 180
        t0 = time.perf_counter()
        grid = engine.generate_map(seed=1337)
        elapsed_ms = (time.perf_counter() - t0) * 1000.0

        assert grid.width == 240
        assert grid.height == 180
        assert len(grid.rooms) >= 20, f"Expected >= 20 rooms in vast labyrinth, got {len(grid.rooms)}"
        assert grid.boss_room is not None

        # Verify boss distance across vast labyrinth
        dist = math.hypot(
            grid.boss_room.center[0] - grid.spawn_point[0],
            grid.boss_room.center[1] - grid.spawn_point[1],
        )
        assert dist >= 120.0, f"Boss distance in labyrinth must be >= 120 tiles, got {dist:.1f}"
        assert elapsed_ms < 1000.0, f"Synthesis of 240x180 maze took {elapsed_ms:.1f}ms (budget < 1000ms)"


class TestWildernessProgressionScaling:
    """Verifies that WildernessMapGenerator scales dimensions and encounter clusters."""

    def test_wilderness_for_zone_scales_with_map_tier(self) -> None:
        gen_early = WildernessMapGenerator.for_zone("zone_tang_kiem_nhai", seed=10, player_level=1)
        assert gen_early.width == 60
        assert gen_early.height == 45

        gen_endgame = WildernessMapGenerator.for_zone("zone_boundless_celestial_palace", seed=10, player_level=90, map_tier=16)
        assert gen_endgame.width == 240
        assert gen_endgame.height == 180

        grid = gen_endgame.generate(seed=777)
        assert grid.width == 240
        assert grid.height == 180
        assert len(grid.encounter_zones) >= 4, "High tier wilderness must have >= 4 encounter clusters"

        # Verify safe spawn and sealed boss gate
        assert grid.tiles[grid.spawn_point[1]][grid.spawn_point[0]].walkable is True
        assert grid.tiles[grid.boss_gate[1]][grid.boss_gate[0]].tile_type == TileType.BOSS_GATE
