"""
Integration test fixtures and configuration.

Provides shared fixtures for integration tests including game engine setup,
player fixtures at different life stages, and mock dependencies.
"""

import pytest
import sys
import os
from pathlib import Path

# Add ws directory to Python path
ws_dir = Path(__file__).parent.parent.parent / 'ws'
if str(ws_dir) not in sys.path:
    sys.path.insert(0, str(ws_dir))

# Set working directory to ws for relative imports
os.chdir(str(ws_dir))

# Set test mode
os.environ['TEST_MODE'] = 'true'
os.environ['DB_NAME'] = 'lifesim_test'

from ws.game_engine import GameEngine
from ws.core.models import playerClass, personClass
from tests.mocks.storage_mock import MockGameStorage
from tests.mocks.output_mock import MockGameOutput
from tests.mocks.services_mock import MockConversationService


@pytest.fixture
def mock_storage():
    """
    Provide a fresh mock storage instance for each test.

    Returns:
        MockGameStorage instance
    """
    storage = MockGameStorage()
    yield storage
    storage.clear()


@pytest.fixture
def mock_output():
    """
    Provide a fresh mock output instance for each test.

    Returns:
        MockGameOutput instance
    """
    output = MockGameOutput()
    yield output
    output.clear()


@pytest.fixture
def mock_conversation_service():
    """
    Provide a fresh mock conversation service for each test.

    Returns:
        MockConversationService instance
    """
    service = MockConversationService()
    yield service
    service.clear()


@pytest.fixture
def game_engine(mock_storage, mock_output, mock_conversation_service):
    """
    Provide a game engine with mock dependencies.

    Args:
        mock_storage: Mock storage fixture
        mock_output: Mock output fixture
        mock_conversation_service: Mock conversation service fixture

    Returns:
        GameEngine instance with mocks
    """
    return GameEngine(
        storage=mock_storage,
        output=mock_output,
        conversation_service=mock_conversation_service
    )


@pytest.fixture
def base_player():
    """
    Create a base player with userID and basic setup.

    Returns:
        playerClass instance with basic initialization
    """
    player = playerClass()
    player.userID = "test_user_001"
    player.status = "active"
    player.controller = "active"
    return player


@pytest.fixture
def newborn_player(base_player):
    """
    Create a player with a newborn character.

    Returns:
        playerClass with character at age 0
    """
    from ws.character.character_manager import characterSetup

    player = base_player
    characterSetup(player, "TestBaby", 0, "Male")
    player.c.ageHours = 0
    player.c.ageDays = 0
    player.c.ageYears = 0
    player.c.energy = 100
    player.c.hunger = 0
    player.c.happiness = 75
    player.hourOfDay = 8
    player.minuteOfHour = 0
    player.dayOfYear = 100
    player.dayOfWeek = 1

    return player


@pytest.fixture
def child_player(base_player):
    """
    Create a player with a child character (age 8).

    Returns:
        playerClass with character at age 8
    """
    from ws.character.character_manager import characterSetup

    player = base_player
    characterSetup(player, "TestChild", 8, "Female")
    player.c.ageHours = 8 * 365 * 24
    player.c.ageDays = 8 * 365
    player.c.ageYears = 8
    player.c.energy = 90
    player.c.hunger = 20
    player.c.happiness = 80
    player.c.occupation = "elementary_school"
    player.hourOfDay = 8
    player.minuteOfHour = 0
    player.dayOfYear = 100
    player.dayOfWeek = 2

    return player


@pytest.fixture
def teen_player(base_player):
    """
    Create a player with a teenager character (age 16).

    Returns:
        playerClass with character at age 16
    """
    from ws.character.character_manager import characterSetup

    player = base_player
    characterSetup(player, "TestTeen", 16, "Male")
    player.c.ageHours = 16 * 365 * 24
    player.c.ageDays = 16 * 365
    player.c.ageYears = 16
    player.c.energy = 85
    player.c.hunger = 30
    player.c.happiness = 70
    player.c.occupation = "high_school"
    player.c.money = 500
    player.hourOfDay = 8
    player.minuteOfHour = 0
    player.dayOfYear = 100
    player.dayOfWeek = 3

    return player


@pytest.fixture
def adult_player(base_player):
    """
    Create a player with an adult character (age 30).

    Returns:
        playerClass with character at age 30
    """
    from ws.character.character_manager import characterSetup

    player = base_player
    characterSetup(player, "TestAdult", 30, "Female")
    player.c.ageHours = 30 * 365 * 24
    player.c.ageDays = 30 * 365
    player.c.ageYears = 30
    player.c.energy = 80
    player.c.hunger = 25
    player.c.happiness = 75
    player.c.occupation = "professional"
    player.c.money = 50000
    player.c.education = "College"
    player.hourOfDay = 9
    player.minuteOfHour = 0
    player.dayOfYear = 100
    player.dayOfWeek = 4

    return player


@pytest.fixture
def elderly_player(base_player):
    """
    Create a player with an elderly character (age 70).

    Returns:
        playerClass with character at age 70
    """
    from ws.character.character_manager import characterSetup

    player = base_player
    characterSetup(player, "TestElder", 70, "Male")
    player.c.ageHours = 70 * 365 * 24
    player.c.ageDays = 70 * 365
    player.c.ageYears = 70
    player.c.energy = 60
    player.c.hunger = 15
    player.c.happiness = 80
    player.c.occupation = "retired"
    player.c.money = 200000
    player.c.education = "College"
    player.hourOfDay = 7
    player.minuteOfHour = 0
    player.dayOfYear = 100
    player.dayOfWeek = 5

    return player


def simulate_time(player, hours: int = 1, minutes: int = 0):
    """
    Helper function to simulate time passage.

    Args:
        player: Player object
        hours: Number of hours to simulate
        minutes: Number of additional minutes to simulate

    Returns:
        Updated player object
    """
    total_minutes = hours * 60 + minutes
    player.minuteOfHour += total_minutes

    while player.minuteOfHour >= 60:
        player.minuteOfHour -= 60
        player.hourOfDay += 1

        if player.hourOfDay >= 24:
            player.hourOfDay = 0
            player.dayOfYear += 1
            player.dayOfWeek += 1

            if player.dayOfWeek > 7:
                player.dayOfWeek = 1

            if player.dayOfYear > 365:
                player.dayOfYear = 1

    return player


def add_test_relationships(player, count: int = 3):
    """
    Helper function to add test relationships to a player.

    Args:
        player: Player object
        count: Number of relationships to add

    Returns:
        Updated player object with relationships
    """
    from ws.character.character_manager import create_character
    from ws.relationships.relationship_manager import updateAffinity

    for i in range(count):
        character = create_character(
            player,
            f"Friend{i}",
            player.c.ageYears,
            player.c.sex
        )
        player.r.append(character)
        updateAffinity(player, player.c, character, 50)

    return player
