"""
Unit tests for FreeExile MegaShop Catalog Engine.
Validates product SKUs, categorization (Items, Skins, Chests, Coins, Passes),
transparent loot box drop rates disclosures, account purchase limits, and discounts.
"""

import unittest
import sys
import os

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

from shop.shop_catalog import (
    MegaShopCatalog,
    ProductCategory,
    ShopProduct,
    ChestDropProbability,
)


class TestShopCatalog(unittest.TestCase):
    def setUp(self):
        self.catalog = MegaShopCatalog()

    def test_catalog_contains_all_categories(self):
        """Catalog must contain items across all 5 mandatory product categories."""
        categories = {p.category for p in self.catalog.get_all_products()}
        expected_categories = {
            ProductCategory.COINS,
            ProductCategory.SKINS,
            ProductCategory.ITEMS,
            ProductCategory.CHESTS,
            ProductCategory.PASSES,
        }
        self.assertTrue(expected_categories.issubset(categories))

    def test_loot_box_transparency_guarantee(self):
        """Every Mystery Chest must have full drop rate disclosure summing strictly to 100%."""
        chests = self.catalog.get_products_by_category(ProductCategory.CHESTS)
        self.assertGreater(len(chests), 0, "At least one mystery chest must be available")

        for chest in chests:
            self.assertTrue(chest.chest_drop_rates, f"Chest {chest.product_id} missing drop rates")
            total_probability = sum(drop.drop_chance_percent for drop in chest.chest_drop_rates)
            self.assertAlmostEqual(
                total_probability,
                100.0,
                places=2,
                msg=f"Chest {chest.product_id} drop probabilities must sum to 100.0%, got {total_probability}"
            )
            # Must contain pity counter item or unique tier item
            has_rare_or_unique = any(drop.rarity >= 2 for drop in chest.chest_drop_rates)
            self.assertTrue(has_rare_or_unique, f"Chest {chest.product_id} must have Rare/Unique items")

    def test_skin_products_attributes(self):
        """Skins must have cosmetic keys and valid coin or fiat pricing."""
        skins = self.catalog.get_products_by_category(ProductCategory.SKINS)
        self.assertGreater(len(skins), 0)
        for skin in skins:
            self.assertTrue(skin.coin_price > 0 or skin.base_fiat_usd > 0)
            self.assertTrue(skin.name_i18n_key.startswith("shop.skin."))

    def test_purchase_limits_and_discounts(self):
        """Products with purchase limit and discounts calculate effective prices correctly."""
        product = self.catalog.get_product("coin_starter_pack_once")
        self.assertIsNotNone(product)
        self.assertEqual(product.purchase_limit_per_account, 1)
        self.assertGreater(product.discount_percent, 0)
        self.assertEqual(
            product.calculate_discounted_price(),
            int(product.coin_price * (100 - product.discount_percent) / 100)
        )


    def test_premium_merchant_stash_product(self):
        """Premium merchant stash tab must be registered under ITEMS with coin price 500."""
        product = self.catalog.get_product("item_premium_merchant_stash_tab")
        self.assertIsNotNone(product)
        self.assertEqual(product.category, ProductCategory.ITEMS)
        self.assertEqual(product.coin_price, 500)
        self.assertEqual(product.purchase_limit_per_account, 1)
        self.assertEqual(product.badge_label, "PREMIUM_TRADE")


if __name__ == "__main__":
    unittest.main()

