"""
Unit tests for End-of-Season Migration Pipeline (Luân Hồi Chuyển Sinh).
Verifies that when a big update / season ends:
1. Expiring league transitions through FREEZING -> MIGRATING -> ARCHIVED.
2. All active listings on Universal Consignment Vault are canceled and returned.
3. All seasonal stashes are transferred to Standard as 'Remove-Only' tabs.
4. All characters are reassigned to Standard realm.
5. Hall of Fame leaderboard snapshot is preserved.
6. The new season starts completely fresh (clean slate: level 1, 0 items).
"""

import pytest
import sys
import os

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../server")))

from world.season_league_manager import (
    LeagueType,
    LeagueStatus,
    SeasonLeagueManager,
    SeasonStashItem,
)
from world.season_migration_pipeline import (
    SeasonMigrationPipeline,
    MigrationReport,
)
from trade.consignment_vault import UniversalConsignmentVault
from world.primal_stones_crafting import GearItem, ItemRarity


@pytest.fixture
def setup_season_environment():
    league_manager = SeasonLeagueManager()
    vault = UniversalConsignmentVault()
    pipeline = SeasonMigrationPipeline(league_manager=league_manager, vault=vault)

    # 1. Create Season 1
    s1 = league_manager.create_league(
        league_id="season_01_minh_nguyet",
        display_name="Mùa 1: Minh Nguyệt Trảm Thiên",
        league_type=LeagueType.CHALLENGE,
        status=LeagueStatus.ACTIVE,
        version_requirement="v1.0.0"
    )

    # 2. Create player in Season 1
    char_player1 = league_manager.create_character(
        account_id="acc_player1",
        character_name="KiemTonMua1",
        martial_class="ThienVuong",
        league_id="season_01_minh_nguyet"
    )
    char_player1.level = 85

    # 3. Add items to Season 1 Stash
    s1_stashes = league_manager.get_account_stashes("acc_player1", "season_01_minh_nguyet")
    s1_tab = s1_stashes[0]
    s1_item = SeasonStashItem(
        item_uuid="item_ancient_blade",
        item_name="Cổ Kiếm Trảm Yêu",
        stack_count=1,
        item_level=80,
        rarity="CUC_PHAM"
    )
    s1_tab.deposit_item(s1_item)

    # 4. List an item in Consignment Vault for Season 1
    listed_gear = GearItem(
        item_uuid="gear_vault_ring",
        item_name="Hỗn Nguyên Giới Chỉ",
        item_level=75,
        rarity=ItemRarity.LINH_PHAM
    )
    listing_id = vault.list_item_for_sale(
        seller_id="acc_player1",
        item=listed_gear,
        price_currency="ThienMenh",
        price_amount=10
    )

    return league_manager, vault, pipeline, char_player1, listing_id


def test_end_of_season_migration_execution(setup_season_environment):
    league_manager, vault, pipeline, char_player1, listing_id = setup_season_environment

    # Schedule & execute end-of-season migration for Season 1 into Standard
    report: MigrationReport = pipeline.execute_season_migration(
        expiring_league_id="season_01_minh_nguyet",
        next_season_id="season_02_hon_don",
        next_season_name="Mùa 2: Hỗn Độn Sơ Khai",
        next_season_version="v1.1.0"
    )

    # 1. Check Migration Report Metrics
    assert report.success is True
    assert report.characters_migrated == 1
    assert report.vault_listings_canceled == 1
    assert report.remove_only_tabs_created >= 1

    # 2. Check League Statuses
    old_league = league_manager.get_league("season_01_minh_nguyet")
    assert old_league.status == LeagueStatus.ARCHIVED

    new_league = league_manager.get_league("season_02_hon_don")
    assert new_league is not None
    assert new_league.status == LeagueStatus.ACTIVE

    # 3. Check Character is now in Standard
    updated_char = league_manager.get_character(char_player1.character_id)
    assert updated_char.league_id == "standard"
    assert updated_char.level == 85  # Level preserved in Standard!

    # 4. Check Vault Listing was Canceled and Refunded
    listing = vault.listings.get(listing_id)
    assert listing is not None
    assert listing.is_sold is True or listing_id not in [l.listing_id for l in vault.listings.values() if not l.is_sold]

    # 5. Check Standard Stash contains Remove-Only Tab with items
    std_stashes = league_manager.get_account_stashes("acc_player1", "standard")
    remove_only_tabs = [t for t in std_stashes if t.is_remove_only]
    assert len(remove_only_tabs) >= 1

    migrated_tab = remove_only_tabs[0]
    assert "item_ancient_blade" in migrated_tab.items
    assert migrated_tab.is_remove_only is True

    # Withdrawing from migrated tab succeeds
    withdrawn = migrated_tab.withdraw_item("item_ancient_blade")
    assert withdrawn.item_name == "Cổ Kiếm Trảm Yêu"

    # Depositing into migrated tab is blocked
    with pytest.raises(ValueError, match="Cannot deposit into Remove-Only stash tab"):
        migrated_tab.deposit_item(SeasonStashItem(item_uuid="junk", item_name="Rác"))


def test_new_season_clean_slate_isolation(setup_season_environment):
    league_manager, vault, pipeline, char_player1, listing_id = setup_season_environment

    # Run migration to start Season 2
    pipeline.execute_season_migration(
        expiring_league_id="season_01_minh_nguyet",
        next_season_id="season_02_hon_don",
        next_season_name="Mùa 2: Hỗn Độn Sơ Khai",
        next_season_version="v1.1.0"
    )

    # In Season 2, create a new character for the same account
    s2_char = league_manager.create_character(
        account_id="acc_player1",
        character_name="KiemTonMua2",
        martial_class="ThienVuong",
        league_id="season_02_hon_don"
    )

    # Level starts fresh at 1
    assert s2_char.level == 1
    assert s2_char.league_id == "season_02_hon_don"

    # Season 2 stash is clean, has NO items from Season 1
    s2_stashes = league_manager.get_account_stashes("acc_player1", "season_02_hon_don")
    assert len(s2_stashes) == 1
    assert s2_stashes[0].is_remove_only is False
    assert s2_stashes[0].is_empty() is True
    assert "item_ancient_blade" not in s2_stashes[0].items
