import os
import hmac
import hashlib
import time
from typing import List, Dict, Any, Tuple
from collections import Counter

class SecureBlindBoxRNG:
    """使用 HMAC-SHA256 的加密安全随机数生成器"""
    
    def __init__(self):
        self.server_seed = os.urandom(32)
        self.server_seed_hash = hashlib.sha256(self.server_seed).hexdigest()
        self.nonce = 0
    
    def _generate_random_bytes(self, context: str) -> bytes:
        self.nonce += 1
        message = f"{context}|nonce:{self.nonce}".encode()
        return hmac.new(self.server_seed, message, hashlib.sha256).digest()
    
    def secure_randint(self, max_value: int, context: str = "rand") -> int:
        if max_value <= 0:
            return 0
        rand_bytes = self._generate_random_bytes(context)
        return int.from_bytes(rand_bytes[:8], 'big') % max_value
    
    def secure_shuffle(self, items: List) -> List:
        items = items[:]
        n = len(items)
        for i in range(n - 1, 0, -1):
            j = self.secure_randint(i + 1, f"shuffle:{i}")
            items[i], items[j] = items[j], items[i]
        return items


class MatchingGame:
    """对对碰游戏 - 可视化版本"""
    
    def __init__(self):
        self.rng = SecureBlindBoxRNG()
        
        # 11种卡牌，每种9张
        self.card_types = ['🍎', '🍊', '🍋', '🍇', '🍓', '🍒', '🥝', '🍑', '🍌', '🍉', '🫐']
        self.card_list = [card for card in self.card_types for _ in range(9)]
        
        # 安全洗牌
        self.card_list = self.rng.secure_shuffle(self.card_list)
        
        self.hand = self.card_list[:9]
        self.deck = self.card_list[9:]
        self.total_pairs = 0
        self.round = 0
    
    def display_hand(self):
        """显示当前手牌"""
        print(f"\n{'='*50}")
        print(f"  第 {self.round} 轮 | 手牌: {len(self.hand)}张 | 牌堆: {len(self.deck)}张")
        print(f"{'='*50}")
        print(f"  手牌: {' '.join(self.hand)}")
        
        # 统计每种牌的数量
        counter = Counter(self.hand)
        pairs_info = []
        for card, count in counter.items():
            if count >= 2:
                pairs_info.append(f"{card}×{count}")
        
        if pairs_info:
            print(f"  可配对: {', '.join(pairs_info)}")
        else:
            print(f"  可配对: 无")
    
    def find_and_remove_pairs(self) -> Tuple[int, List[str]]:
        """找出并移除配对的牌"""
        counter = Counter(self.hand)
        pairs_found = 0
        pairs_detail = []
        remaining = []
        
        for card, count in counter.items():
            pairs = count // 2
            if pairs > 0:
                pairs_found += pairs
                pairs_detail.append(f"{card}×{pairs*2}")
            
            # 剩余的单张
            if count % 2 == 1:
                remaining.append(card)
        
        return pairs_found, remaining, pairs_detail
    
    def play_round(self, is_first: bool = False):
        """执行一轮游戏"""
        self.round += 1
        
        # 第一轮：如果有🍎，额外抽牌
        if is_first:
            apple_count = self.hand.count('🍎')
            if apple_count > 0:
                print(f"\n  🎁 发现 {apple_count} 张🍎，额外抽取 {apple_count} 张牌！")
                extra = self.deck[:apple_count]
                self.hand.extend(extra)
                self.deck = self.deck[apple_count:]
                print(f"  抽到: {' '.join(extra)}")
        
        self.display_hand()
        
        # 配对
        pairs, remaining, pairs_detail = self.find_and_remove_pairs()
        
        if pairs > 0:
            print(f"\n  ✨ 配对成功: {', '.join(pairs_detail)}")
            print(f"  本轮配对: {pairs} 对")
            self.total_pairs += pairs
            
            # 抽取新牌
            draw_count = min(pairs, len(self.deck))
            if draw_count > 0:
                new_cards = self.deck[:draw_count]
                self.deck = self.deck[draw_count:]
                remaining.extend(new_cards)
                print(f"  从牌堆抽取: {' '.join(new_cards)}")
            
            self.hand = remaining
            return True
        else:
            print(f"\n  ❌ 无法配对，游戏结束")
            self.hand = remaining
            return False
    
    def play(self):
        """完整游戏流程"""
        print("\n" + "🎮" * 20)
        print("        欢迎来到 对对碰 游戏！")
        print("🎮" * 20)
        print(f"\n游戏规则:")
        print(f"  1. 初始手牌 9 张")
        print(f"  2. 相同的牌可以配对消除")
        print(f"  3. 每配对一次，从牌堆抽取相应数量的新牌")
        print(f"  4. 直到无法配对为止")
        print(f"\n种子哈希: {self.rng.server_seed_hash[:16]}...")
        
        # 第一轮
        can_continue = self.play_round(is_first=True)
        
        # 后续轮次
        while can_continue:
            input("\n  按回车继续...")
            can_continue = self.play_round(is_first=False)
        
        # 游戏结束
        print(f"\n{'='*50}")
        print(f"  🏆 游戏结束！")
        print(f"  总配对数: {self.total_pairs} 对")
        print(f"  剩余手牌: {len(self.hand)} 张 {' '.join(self.hand)}")
        print(f"  剩余牌堆: {len(self.deck)} 张")
        print(f"{'='*50}")
        
        return {
            "total_pairs": self.total_pairs,
            "remaining_hand": self.hand,
            "remaining_deck_count": len(self.deck),
            "seed_hash": self.rng.server_seed_hash
        }


if __name__ == "__main__":
    game = MatchingGame()
    result = game.play()
