"""
Unit tests for FreeExile MegaShop Orchestrator Service.
Validates end-to-end purchasing workflow, coin credit via 2PC,
cosmetic skin delivery, and mystery chest gacha drops with transparent probabilities.
"""

import unittest
import sys
import os

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

from shop.shop_service import MegaShopService
from shop.shop_catalog import ProductCategory
from shop.payment_gateway_router import PlatformType, PaymentGateway
from shop.receipt_verifier import CryptoChain, CryptoToken


class TestShopService(unittest.TestCase):
    def setUp(self):
        self.shop_service = MegaShopService()
        self.test_account = "player_exile_007"
        self.shop_service.register_player(self.test_account)

    def test_buy_coins_via_apple_iap_on_ios(self):
        """Buying 1000 Gold Cores on iOS via Apple IAP successfully credits player balance."""
        # 1. Initiate order
        order = self.shop_service.create_purchase_order(
            account_id=self.test_account,
            product_id="coin_pack_1000",
            platform=PlatformType.PLATFORM_IOS,
            gateway=PaymentGateway.GATEWAY_APPLE_IAP,
            country_code="US"
        )
        self.assertTrue(order.success)

        # 2. Simulate Apple StoreKit 2 JWS receipt verification
        receipt_jwt = f"valid_mock_storekit_jws_{order.order_id}"
        settle_result = self.shop_service.settle_fiat_order(
            order_id=order.order_id,
            receipt_payload=receipt_jwt
        )
        self.assertTrue(settle_result.success)
        self.assertEqual(settle_result.coins_credited, 1000)

        # Check account balance
        balance = self.shop_service.get_player_coin_balance(self.test_account)
        self.assertEqual(balance, 1000)

    def test_buy_skin_with_in_game_coins(self):
        """Purchasing Azure Dragon Blade Skin with in-game Gold Cores deducts coins and delivers cosmetic."""
        # Grant initial coins
        self.shop_service.credit_player_coins(self.test_account, 2500, reason="test_grant")

        skin_product_id = "skin_azure_dragon_blade"
        result = self.shop_service.purchase_product_with_coins(
            account_id=self.test_account,
            product_id=skin_product_id
        )
        self.assertTrue(result.success)
        self.assertIn(skin_product_id, self.shop_service.get_player_owned_skins(self.test_account))

        # Check remaining balance (2500 - 1800 = 700)
        remaining = self.shop_service.get_player_coin_balance(self.test_account)
        self.assertEqual(remaining, 700)

    def test_open_mystery_chest_delivers_loot(self):
        """Opening a Mystery Chest deducts coins and delivers weighted random loot according to published probabilities."""
        self.shop_service.credit_player_coins(self.test_account, 1000, reason="test_grant")

        chest_product_id = "chest_celestial_fortune"
        result = self.shop_service.purchase_and_open_chest(
            account_id=self.test_account,
            chest_product_id=chest_product_id
        )
        self.assertTrue(result.success)
        self.assertIsNotNone(result.dropped_item)
        self.assertTrue(len(result.dropped_item.item_id) > 0)
        self.assertIn(result.dropped_item.rarity, [0, 1, 2, 3])

        # Verify item added to player inventory
        inventory = self.shop_service.get_player_inventory(self.test_account)
        self.assertTrue(any(item["item_id"] == result.dropped_item.item_id for item in inventory))

    def test_web3_crypto_purchase_with_bonus(self):
        """Web3 Crypto payment on Web portal gives +10% bonus coins."""
        # 1. Create Web3 order
        order = self.shop_service.create_purchase_order(
            account_id=self.test_account,
            product_id="coin_pack_1000",
            platform=PlatformType.PLATFORM_WEB_PC,
            gateway=PaymentGateway.GATEWAY_CRYPTO_WEB3,
            country_code="VN",
            crypto_chain=CryptoChain.CHAIN_ARBITRUM,
            crypto_token=CryptoToken.TOKEN_USDT,
            buyer_wallet="0xAbc987...123"
        )
        self.assertTrue(order.success)
        self.assertIsNotNone(order.web3_details)

        # 2. Register mock tx and settle
        tx_hash = "0xArbitrumTxHash_USDT_Settled_12345"
        self.shop_service.crypto_verifier.mock_register_on_chain_tx(
            tx_hash=tx_hash,
            chain=CryptoChain.CHAIN_ARBITRUM,
            from_address="0xAbc987...123",
            to_address=order.web3_details.merchant_vault_address,
            token=CryptoToken.TOKEN_USDT,
            amount_transferred=order.web3_details.required_token_amount,
            confirmations=20,
            is_confirmed=True
        )

        settle = self.shop_service.settle_crypto_order(
            order_id=order.order_id,
            tx_hash=tx_hash,
            chain=CryptoChain.CHAIN_ARBITRUM
        )
        self.assertTrue(settle.success)
        # Base 1000 + 10% bonus = 1100 coins
        self.assertEqual(settle.coins_credited, 1100)
        self.assertEqual(self.shop_service.get_player_coin_balance(self.test_account), 1100)


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