"""Tests for kill and death tracking in combat."""

import time

import pytest

from mudlib.combat.engine import (
    process_combat,
    start_encounter,
)
from mudlib.combat.moves import CombatMove
from mudlib.entity import Mob
from mudlib.player import accumulate_play_time


@pytest.fixture
def punch_move():
    """Create a basic punch move for testing."""
    return CombatMove(
        name="punch right",
        move_type="attack",
        stamina_cost=5.0,
        timing_window_ms=800,
        damage_pct=0.15,
        countered_by=[],
        resolve_hit="{attacker} hits {defender}!",
        resolve_miss="{defender} dodges!",
        announce="{attacker} punches!",
    )


@pytest.mark.asyncio
async def test_player_kills_mob_increments_stats(player, test_zone, punch_move):
    """Player kills mob -> kills incremented, mob_kills tracked."""
    # Create a goblin mob
    goblin = Mob(name="goblin", x=0, y=0)
    goblin.location = test_zone
    test_zone._contents.append(goblin)

    # Start encounter
    encounter = start_encounter(player, goblin)

    # Execute attack
    encounter.attack(punch_move)

    # Advance past telegraph (0.3s) + window (0.8s)
    encounter.tick(time.monotonic() + 0.31)  # -> WINDOW
    encounter.tick(time.monotonic() + 1.2)  # -> RESOLVE

    # Set defender to very low pl so damage kills them
    goblin.pl = 1.0

    # Process combat (this will resolve and end encounter)
    await process_combat()

    # Verify stats
    assert player.kills == 1
    assert player.mob_kills["goblin"] == 1


@pytest.mark.asyncio
async def test_player_killed_by_mob_increments_deaths(player, test_zone, punch_move):
    """Player killed by mob -> deaths incremented."""
    # Create a goblin mob
    goblin = Mob(name="goblin", x=0, y=0)
    goblin.location = test_zone
    test_zone._contents.append(goblin)

    # Start encounter with mob as attacker
    encounter = start_encounter(goblin, player)

    # Execute attack
    encounter.attack(punch_move)

    # Advance to RESOLVE
    encounter.tick(time.monotonic() + 0.31)
    encounter.tick(time.monotonic() + 1.2)

    # Set player to low pl so they die
    player.pl = 1.0

    # Process combat
    await process_combat()

    # Verify deaths incremented
    assert player.deaths == 1


@pytest.mark.asyncio
async def test_multiple_kills_accumulate(player, test_zone, punch_move):
    """After killing 3 goblins, player.kills == 3, player.mob_kills["goblin"] == 3."""
    for _ in range(3):
        # Create goblin
        goblin = Mob(name="goblin", x=0, y=0)
        goblin.location = test_zone
        test_zone._contents.append(goblin)

        # Create and resolve encounter
        encounter = start_encounter(player, goblin)
        encounter.attack(punch_move)
        encounter.tick(time.monotonic() + 0.31)
        encounter.tick(time.monotonic() + 1.2)
        goblin.pl = 1.0

        await process_combat()

    # Verify accumulated kills
    assert player.kills == 3
    assert player.mob_kills["goblin"] == 3


def test_session_time_tracking(player):
    """Session time tracking accumulates correctly."""
    # Set session start to a known time
    start_time = time.monotonic()
    player.session_start = start_time

    # Simulate 5 seconds passing
    time.sleep(0.01)  # Small real delay to ensure monotonic() advances
    player.session_start = start_time  # Reset for predictable test

    # Mock time to be 5 seconds later
    import unittest.mock

    with unittest.mock.patch("time.monotonic", return_value=start_time + 5.0):
        accumulate_play_time(player)

    # Should have accumulated 5 seconds
    assert player.play_time_seconds == 5.0

    # Session start should be reset to current time
    with unittest.mock.patch("time.monotonic", return_value=start_time + 5.0):
        assert player.session_start == start_time + 5.0


def test_accumulate_play_time_multiple_sessions(player):
    """Multiple accumulation calls should add up correctly."""
    start_time = time.monotonic()
    player.session_start = start_time

    import unittest.mock

    # First accumulation: 3 seconds
    with unittest.mock.patch("time.monotonic", return_value=start_time + 3.0):
        accumulate_play_time(player)

    assert player.play_time_seconds == 3.0

    # Second accumulation: 2 more seconds (from reset point)
    with unittest.mock.patch("time.monotonic", return_value=start_time + 5.0):
        accumulate_play_time(player)

    # Should have 3 + 2 = 5 total
    assert player.play_time_seconds == 5.0
