package taurus.util;

import java.util.*;

public class ZhuanZhuanSuanFaTest {
    private static final int HONG_ZHONG = 412;

    // 权重配置
    private static final int WEIGHT_COMPLETED_MELD = 70;   // 已完成的面子权重
    private static final int WEIGHT_PAIR = 60;            // 对子权重
    private static final int WEIGHT_POTENTIAL_TRIPLET = 50;
    private static final int WEIGHT_POTENTIAL_PAIR = 40;
    private static final int WEIGHT_CLOSE_ADJACENT = 60;  // 相邻牌权重
    private static final int WEIGHT_FAR_ADJACENT = 25;    // 远邻牌权重
    private static final int WEIGHT_MIDDLE_RANK = 25;     // 中张牌权重
    private static final int PENALTY_EDGE_RANK = 15;      // 边张惩罚
    private static final int PENALTY_ISOLATED = 40;       // 孤张惩罚

    public String outCardSuanFa(List<Integer> cardInhand, int card) {
        List<Integer> handCards = new ArrayList<>(cardInhand);
        handCards.sort(Integer::compareTo);
        System.out.println("排序后机器人手牌" + handCards);

        // 分析手牌结构
        HandAnalysis analysis = analyzeHand(handCards);

        System.out.println("机器人 zhuanZhuanCount 转转数量  "  + analysis.zhuanZhaunCount);
        System.out.println(" 按花色分组的计数  "  + analysis.cardCounts);
        System.out.println("机器人 已完成的刻子、顺子  "  + analysis.completedMelds);
        System.out.println("机器人 对子  "  + analysis.pairs);
        System.out.println("机器人 孤张牌  "  + analysis.isolatedCards);
        System.out.println("机器人 每张牌的有用程度  "  + analysis.cardUsefulness);
        System.out.println("机器人 按花色分组的手牌"  + analysis.cardsBySuit);
        System.out.println("机器人 向听数  "  + analysis.shantenCount);

        // 计算每张牌的出牌优先级
        Map<Integer, Integer> discardPriority = calculateDiscardPriority(handCards, analysis);

        // 选择要打出的牌
        int cardToDiscard = selectCardToDiscard(handCards, discardPriority);
        System.out.println("最终打出牌  "  + cardToDiscard);

        return String.valueOf(cardToDiscard);
    }

    private static class HandAnalysis {
        int zhuanZhaunCount = 0;
        Map<Integer, Integer> cardCounts = new HashMap<>(); // 按花色分组的计数
        List<List<Integer>> completedMelds = new ArrayList<>();  // 已完成的刻子/顺子
        List<Integer> pairs = new ArrayList<>(); //对子
        List<Integer> isolatedCards = new ArrayList<>(); //  孤张牌
        Map<Integer, Integer> cardUsefulness = new HashMap<>();  // 每张牌的有用程度
        Map<Integer, List<Integer>> cardsBySuit = new HashMap<>(); // 按花色分组的手牌

        // 新增字段
        int pairCount = 0; // 对子数量
        int meldCount = 0; // 面子数量
        int shantenCount = Integer.MAX_VALUE; // 向听数
        boolean isTingPai = false; // 是否听牌
        Set<Integer> tingCards = new HashSet<>(); // 可听的牌组
        boolean hasLongQiDuiPotential = false; // 七对潜力
        Set<Integer> usedInMelds = new HashSet<>(); // 已用于面子的牌
        Set<Integer> usedInPairs = new HashSet<>(); // 已用于对子的牌
    }

    private HandAnalysis analyzeHand(List<Integer> handCards) {
        HandAnalysis analysis = new HandAnalysis();

        // 分离红中和普通牌，并按花色分组
        for (int card : handCards) {
            if (card == HONG_ZHONG) {
                analysis.zhuanZhaunCount++;
            } else {
                int suit = card / 100;
                analysis.cardCounts.put(card, analysis.cardCounts.getOrDefault(card, 0) + 1);

                // 按花色分组
                analysis.cardsBySuit.computeIfAbsent(suit, k -> new ArrayList<>()).add(card);
            }
        }

        analyzeCardPatterns(analysis);

        // 计算向听数
        calculateShantenCount(analysis);

        // 检查七对潜力
        checkLongQiDuiPotential(analysis);

        // 检查是否听牌
        checkTingPai(analysis);

        return analysis;
    }

    private void analyzeCardPatterns(HandAnalysis analysis) {
        // 初始化可组成面子的牌集合
        Set<Integer> usedInMelds = new HashSet<>();
        Set<Integer> usedInPairs = new HashSet<>();

        // 对每种花色分别分析
        for (List<Integer> suitCards : new ArrayList<>(analysis.cardsBySuit.values())) {
            List<Integer> cardsCopy = new ArrayList<>(suitCards);
            cardsCopy.sort(Integer::compareTo);

            // 先找刻子
            findTripletsOptimized(cardsCopy, analysis, usedInMelds);
            // 再找顺子
            findSequencesOptimized(cardsCopy, analysis, usedInMelds);
            // 找对子
            findPairsOptimized(cardsCopy, analysis, usedInPairs);
            // 剩余的是孤张
            analysis.isolatedCards.addAll(cardsCopy);
        }

        // 保存已使用的牌信息
        analysis.usedInMelds = usedInMelds;
        analysis.usedInPairs = usedInPairs;

        // 更新面子数量和对子数量
        analysis.meldCount = analysis.completedMelds.size();
        analysis.pairCount = analysis.pairs.size();

        // 分析每张牌的价值
        analyzeCardUsefulness(analysis);
    }

    // 优化的刻子查找方法
    private void findTripletsOptimized(List<Integer> cards, HandAnalysis analysis, Set<Integer> usedInMelds) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int card : cards) {
            countMap.put(card, countMap.getOrDefault(card, 0) + 1);
        }

        // 使用新的列表来记录要移除的牌
        List<Integer> cardsToRemove = new ArrayList<>();

        for (int card : cards) {
            if (countMap.getOrDefault(card, 0) >= 3 && !cardsToRemove.contains(card)) {
                // 找到刻子
                List<Integer> triplet = Arrays.asList(card, card, card);
                analysis.completedMelds.add(triplet);

                // 标记要移除的牌
                cardsToRemove.add(card);
                cardsToRemove.add(card);
                cardsToRemove.add(card);

                // 标记已使用的牌
                usedInMelds.add(card);

                // 更新计数
                countMap.put(card, countMap.get(card) - 3);
            }
        }

        // 一次性移除所有标记的牌
        cards.removeAll(cardsToRemove);
    }

    // 优化的顺子查找方法
    private void findSequencesOptimized(List<Integer> cards, HandAnalysis analysis, Set<Integer> usedInMelds) {
        if (cards.size() < 3) return;

        // 转换为点数并去重排序
        Set<Integer> points = new HashSet<>();
        for (int card : cards) {
            points.add(card % 100); // 获取点数（1-9）
        }

        List<Integer> sortedPoints = new ArrayList<>(points);
        Collections.sort(sortedPoints);

        for (int i = 0; i <= sortedPoints.size() - 3; i++) {
            int p1 = sortedPoints.get(i);
            int p2 = sortedPoints.get(i + 1);
            int p3 = sortedPoints.get(i + 2);

            if (p2 == p1 + 1 && p3 == p2 + 1) {
                // 找到顺子模式，获取对应的牌
                int suit = cards.get(0) / 100; // 所有牌都是同一花色
                int card1 = suit * 100 + p1;
                int card2 = suit * 100 + p2;
                int card3 = suit * 100 + p3;

                if (cards.contains(card1) && cards.contains(card2) && cards.contains(card3)) {
                    // 找到顺子
                    List<Integer> sequence = Arrays.asList(card1, card2, card3);
                    analysis.completedMelds.add(sequence);

                    // 移除这三张牌
                    cards.remove(Integer.valueOf(card1));
                    cards.remove(Integer.valueOf(card2));
                    cards.remove(Integer.valueOf(card3));

                    // 标记已使用的牌
                    usedInMelds.add(card1);
                    usedInMelds.add(card2);
                    usedInMelds.add(card3);

                    // 重新开始查找，因为牌列表改变了
                    findSequencesOptimized(cards, analysis, usedInMelds);
                    return;
                }
            }
        }
    }

    // 优化的对子查找方法
    private void findPairsOptimized(List<Integer> cards, HandAnalysis analysis, Set<Integer> usedInPairs) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int card : cards) {
            countMap.put(card, countMap.getOrDefault(card, 0) + 1);
        }

        // 使用新的列表来记录要移除的牌
        List<Integer> cardsToRemove = new ArrayList<>();

        for (int card : cards) {
            if (countMap.getOrDefault(card, 0) >= 2 && !cardsToRemove.contains(card)) {
                analysis.pairs.add(card);

                // 标记已使用的牌
                usedInPairs.add(card);

                // 标记要移除的牌
                cardsToRemove.add(card);
                cardsToRemove.add(card);

                // 更新计数
                countMap.put(card, countMap.get(card) - 2);
            }
        }

        // 一次性移除所有标记的牌
        cards.removeAll(cardsToRemove);
    }

    // 计算向听数
    private void calculateShantenCount(HandAnalysis analysis) {
        // 简化版向听数计算
        int totalCards = analysis.zhuanZhaunCount;
        for (List<Integer> suitCards : analysis.cardsBySuit.values()) {
            totalCards += suitCards.size();
        }

        // 基础向听数 = 理想牌型的面子数 - 当前面子数
        int idealMelds = (totalCards + analysis.zhuanZhaunCount) / 3;
        analysis.shantenCount = Math.max(0, idealMelds - analysis.meldCount);
    }

    // 检查七对潜力
    private void checkLongQiDuiPotential(HandAnalysis analysis) {
        // 七对需要至少5个对子加上转转
        if (analysis.pairCount >= 5 || analysis.zhuanZhaunCount >= 2) {
            analysis.hasLongQiDuiPotential = true;
        }
    }

    // 检查是否听牌
    private void checkTingPai(HandAnalysis analysis) {
        // 检查基本听牌条件
        int totalCards = analysis.zhuanZhaunCount;
        for (List<Integer> suitCards : analysis.cardsBySuit.values()) {
            totalCards += suitCards.size();
        }

        // 标准麻将听牌条件：一对将牌 + 四面子，或七对子
        boolean standardTing = (totalCards - 2) % 3 == 0 && analysis.shantenCount == 0;
        boolean sevenPairsTing = analysis.hasLongQiDuiPotential && totalCards >= 12;

        analysis.isTingPai = standardTing || sevenPairsTing;

        // 如果听牌，尝试找出听的牌
        if (analysis.isTingPai) {
            findTingCards(analysis);
        }
    }

    // 找出可听的牌
    private void findTingCards(HandAnalysis analysis) {
        // 简化版听牌查找逻辑
        for (int suit = 1; suit <= 3; suit++) { // 遍历万、饼、条
            for (int rank = 1; rank <= 9; rank++) { // 遍历1-9
                int testCard = suit * 100 + rank;
                if (!analysis.cardCounts.containsKey(testCard) || analysis.cardCounts.get(testCard) < 4) {
                    // 模拟加入这张牌
                    analysis.tingCards.add(testCard);
                }
            }
        }
    }

    /**
     * 分析摸牌后是否可听牌，并全面分析手牌结构
     */
    public boolean analyzeDrawCard(List<Integer> currentHand, int drawnCard) {
        // 创建包含摸牌后的手牌
        List<Integer> newHand = new ArrayList<>(currentHand);
        newHand.add(drawnCard);
        newHand.sort(Integer::compareTo);

        System.out.println("摸牌: " + drawnCard + "，摸牌后手牌: " + newHand);

        // 分析新的手牌
        HandAnalysis analysis = analyzeHand(newHand);

        // 输出详细分析结果
        System.out.println("摸牌后分析结果:");
        System.out.println("- 是否听牌: " + analysis.isTingPai);
        if (analysis.isTingPai) {
            System.out.println("- 可听的牌组: " + analysis.tingCards);
        }
        System.out.println("- 转转数量: " + analysis.zhuanZhaunCount);
        System.out.println("- 已完成的面子数: " + analysis.meldCount);
        System.out.println("- 对子数量: " + analysis.pairCount);
        System.out.println("- 孤张牌: " + analysis.isolatedCards);
        System.out.println("- 向听数: " + analysis.shantenCount);

        // 特别分析新摸的牌对牌型的影响
        int newCardCount = 0;
        for (int card : newHand) {
            if (card == drawnCard) newCardCount++;
        }

        System.out.println("- 新摸牌 " + drawnCard + " 的数量: " + newCardCount);

        // 分析新摸牌的潜力
        int drawnCardPotential = calculateCardPotentialScore(drawnCard, analysis);
        System.out.println("- 新摸牌的潜力分数: " + drawnCardPotential);

        // 调用分析打出哪张牌可以听牌的方法
        findDiscardToTing(newHand);

        return analysis.isTingPai;
    }

    /**
     * 分析打出哪张牌可以听牌
     */
    public Map<Integer, Set<Integer>> findDiscardToTing(List<Integer> currentHand) {
        Map<Integer, Set<Integer>> discardToTingMap = new HashMap<>();
        System.out.println("\n开始分析打出哪张牌可以听牌...");

        // 对手牌进行深度复制，避免修改原手牌
        List<Integer> handCopy = new ArrayList<>(currentHand);
        handCopy.sort(Integer::compareTo);

        // 统计每种牌的数量，避免重复分析相同的牌
        Map<Integer, Integer> cardCounts = new HashMap<>();
        for (int card : handCopy) {
            cardCounts.put(card, cardCounts.getOrDefault(card, 0) + 1);
        }

        // 尝试打出每一种不同的牌
        for (Map.Entry<Integer, Integer> entry : cardCounts.entrySet()) {
            int cardToDiscard = entry.getKey();

            // 转转通常不会打出，但仍然分析可能性
            if (cardToDiscard == HONG_ZHONG) {
                System.out.println("- 通常不建议打出转转: " + cardToDiscard);
                continue;
            }

            // 模拟打出这张牌
            List<Integer> tempHand = new ArrayList<>(handCopy);
            tempHand.remove(Integer.valueOf(cardToDiscard));

            // 分析打出这张牌后的手牌是否听牌
            HandAnalysis analysis = analyzeHand(tempHand);

            // 如果听牌，记录这张牌和对应的听牌组
            if (analysis.isTingPai && !analysis.tingCards.isEmpty()) {
                discardToTingMap.put(cardToDiscard, analysis.tingCards);
                System.out.println("- 打出牌: " + cardToDiscard + " 后可以听牌");
                System.out.println("  听的牌组: " + analysis.tingCards);
            }
        }

        // 输出分析结果
        if (discardToTingMap.isEmpty()) {
            System.out.println("- 当前没有可以打出后听牌的牌");
        } else {
            System.out.println("\n可打出后听牌的牌数量: " + discardToTingMap.size());
            System.out.println("建议打出的牌及其对应的听牌组:");
            for (Map.Entry<Integer, Set<Integer>> entry : discardToTingMap.entrySet()) {
                System.out.println("- 牌: " + entry.getKey() + " -> 听牌组: " + entry.getValue());
            }
        }

        return discardToTingMap;
    }

    /**
     * 计算牌的潜力分数
     */
    /**
     * 计算牌的潜力分数（增强版）
     */
    private int calculateCardPotentialScore(int card, HandAnalysis analysis) {
        int score = 0;

        // 如果是转转，潜力很高
        if (card == HONG_ZHONG) {
            return 100;
        }

        int suit = card / 100;
        int rank = card % 100;
        int cardCount = analysis.cardCounts.getOrDefault(card, 0);

        // 1. 刻子潜力评估
        if (cardCount >= 2) {
            score += 30; // 两张相同的牌有刻子潜力
            if (cardCount >= 3) {
                score += 40; // 三张相同的牌刻子已完成
            }
        } else if (cardCount == 1) {
            score += 10; // 单张牌的基础潜力
        }

        // 2. 对子潜力
        if (analysis.pairs.contains(card)) {
            score += 25;
            // 如果已经有多个对子，评估七对潜力
            if (analysis.pairCount >= 5) {
                score += 15; // 七对潜力加分
            }
        }

        // 3. 顺子潜力评估
        // 检查两面搭（如34需要2或5）
        int prevCard = suit * 100 + (rank - 1);
        int nextCard = suit * 100 + (rank + 1);
        boolean hasPrev = analysis.cardCounts.getOrDefault(prevCard, 0) > 0;
        boolean hasNext = analysis.cardCounts.getOrDefault(nextCard, 0) > 0;

        if (hasPrev && hasNext) {
            score += 20; // 两面搭子
        } else if (hasPrev || hasNext) {
            score += 10; // 一面搭子
        }

        // 4. 检查坎搭可能性（如2和4之间需要3）
        if (rank >= 3 && rank <= 7) {
            int prevPrevCard = suit * 100 + (rank - 2);
            int nextNextCard = suit * 100 + (rank + 2);

            if (analysis.cardCounts.getOrDefault(prevPrevCard, 0) > 0) {
                score += 8; // 坎搭潜力
            }
            if (analysis.cardCounts.getOrDefault(nextNextCard, 0) > 0) {
                score += 8; // 坎搭潜力
            }
        }

        // 5. 中间牌额外潜力
        if (rank >= 3 && rank <= 7) {
            score += 5; // 中张牌额外价值
        }
        // 边张减分
        else if (rank == 1 || rank == 9) {
            score -= 5; // 边张减分
        }

        // 6. 检查是否形成复合搭子（如334有两面搭和对子的复合）
        if (cardCount >= 1) {
            // 检查是否有相邻的对子
            if (analysis.cardCounts.getOrDefault(prevCard, 0) >= 2) {
                score += 8; // 相邻对子形成复合搭子
            }
            if (analysis.cardCounts.getOrDefault(nextCard, 0) >= 2) {
                score += 8; // 相邻对子形成复合搭子
            }

            // 检查是否有相邻的单牌形成复合搭子（如334）
            if (analysis.cardCounts.getOrDefault(prevCard, 0) == 1 && cardCount >= 2) {
                score += 5;
            }
            if (analysis.cardCounts.getOrDefault(nextCard, 0) == 1 && cardCount >= 2) {
                score += 5;
            }
        }

        // 7. 转转作为万能牌的影响
        if (analysis.zhuanZhaunCount > 0) {
            // 单张牌+转转可以形成对子
            if (cardCount == 1) {
                score += 10;
            }
            // 两张牌+转转可以形成刻子
            if (cardCount == 2) {
                score += 15;
            }
            // 转转可以填补顺子空缺
            if (rank >= 2 && rank <= 8 && (!hasPrev || !hasNext)) {
                score += 5;
            }
        }

        // 8. 评估该牌对整体牌型的贡献
        if (analysis.shantenCount <= 2 && !analysis.isolatedCards.contains(card)) {
            score += 10; // 对接近听牌的牌型有贡献
        }

        // 9. 孤张牌减分
        if (analysis.isolatedCards.contains(card)) {
            score -= 15; // 孤张牌减分
        }

        return Math.max(0, score); // 确保分数不为负
    }

    /**
     * 处理牌数较少的花色
     */
    private void handleSmallSuit(List<Integer> suitCards, HandAnalysis analysis) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int card : suitCards) {
            countMap.put(card, countMap.getOrDefault(card, 0) + 1);
        }

        // 先找对子
        for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
            if (entry.getValue() >= 2) {
                analysis.pairs.add(entry.getKey());

                // 移除对子
                suitCards.remove(entry.getKey());
                suitCards.remove(entry.getKey());
                break;
            }
        }

        // 剩余的都是孤张
        analysis.isolatedCards.addAll(suitCards);
    }

    /**
     * 分析每张牌的有用程度（优化版）
     */
    private void analyzeCardUsefulnessOptimized(HandAnalysis analysis) {
        // 分析所有普通牌
        for (List<Integer> suitCards : analysis.cardsBySuit.values()) {
            for (int card : suitCards) {
                int usefulness = calculateSingleCardUsefulness(card, suitCards, analysis);
                analysis.cardUsefulness.put(card, usefulness);
            }
        }
    }

    // 重命名为analyzeCardUsefulness以保持向后兼容性
    private void analyzeCardUsefulness(HandAnalysis analysis) {
        analyzeCardUsefulnessOptimized(analysis);
    }

    private int calculateSingleCardUsefulness(int card, List<Integer> sameSuitCards, HandAnalysis analysis) {
        int usefulness = 0;
        int suit = card / 100;
        int rank = card % 100;

        // 1. 检查是否在已完成的牌型中
        for (List<Integer> meld : analysis.completedMelds) {
            if (meld.contains(card)) {
                usefulness += WEIGHT_COMPLETED_MELD;
                break;
            }
        }

        // 2. 检查是否是对子
        if (analysis.pairs.contains(card)) {
            usefulness += WEIGHT_PAIR;
        }

        // 3. 检查刻子潜力
        int sameCardCount = Collections.frequency(sameSuitCards, card);
        if (sameCardCount >= 2) {
            usefulness += WEIGHT_POTENTIAL_TRIPLET;
        } else if (sameCardCount == 1) {
            usefulness += 15;
        }

        // 4. 检查顺子潜力
        usefulness += checkSequencePotential(card, sameSuitCards);

        // 5. 检查相邻牌潜力
        usefulness += checkAdjacentCardPotential(card, sameSuitCards);

        // 6. 中张牌价值更高（3-7）
        if (rank >= 3 && rank <= 7) {
            usefulness += WEIGHT_MIDDLE_RANK;
        }

        // 7. 边张牌价值较低（1,2,8,9）
        if (rank == 1 || rank == 2 || rank == 8 || rank == 9) {
            usefulness -= PENALTY_EDGE_RANK;
        }

        // 8. 孤张牌惩罚
        if (analysis.isolatedCards.contains(card)) {
            usefulness -= PENALTY_ISOLATED;
        }

        return Math.max(usefulness, 1);
    }

    /**
     * 特别处理相邻牌的情况（优化版）
     */
    private int checkAdjacentCardPotential(int card, List<Integer> sameSuitCards) {
        int potential = 0;
        int suit = card / 100;
        int rank = card % 100;

        // 检查前后相邻的牌
        int[] closeAdjacent = {rank - 1, rank + 1}; // 紧邻的牌
        int[] farAdjacent = {rank - 2, rank + 2};   // 隔一张的牌

        // 紧邻的牌价值很高
        for (int adjRank : closeAdjacent) {
            if (adjRank >= 1 && adjRank <= 9) {
                int adjCard = suit * 100 + adjRank;
                if (sameSuitCards.contains(adjCard)) {
                    potential += WEIGHT_CLOSE_ADJACENT;
                }
            }
        }

        // 隔一张的牌也有价值
        for (int adjRank : farAdjacent) {
            if (adjRank >= 1 && adjRank <= 9) {
                int adjCard = suit * 100 + adjRank;
                if (sameSuitCards.contains(adjCard)) {
                    potential += WEIGHT_FAR_ADJACENT;
                }
            }
        }

        return potential;
    }

    /**
     * 检查顺子潜力（严格同花色）
     */
    private int checkSequencePotential(int card, List<Integer> sameSuitCards) {
        int potential = 0;
        int rank = card % 100;

        // 检查可能的顺子组合（必须是同花色）
        int[][] sequencePatterns = {
                {rank - 2, rank - 1}, // 缺前两张
                {rank - 1, rank + 1}, // 缺中间一张
                {rank + 1, rank + 2}  // 缺后两张
        };

        int suit = card / 100;

        for (int[] pattern : sequencePatterns) {
            boolean validPattern = true;
            for (int r : pattern) {
                if (r < 1 || r > 9) {
                    validPattern = false;
                    break;
                }
            }

            if (validPattern) {
                int neededCard1 = suit * 100 + pattern[0];
                int neededCard2 = suit * 100 + pattern[1];

                if (sameSuitCards.contains(neededCard1) && sameSuitCards.contains(neededCard2)) {
                    potential += 30; // 已经有两张配套牌
                } else if (sameSuitCards.contains(neededCard1) || sameSuitCards.contains(neededCard2)) {
                    potential += 15; // 有一张配套牌
                } else {
                    potential += 5;  // 有形成顺子的潜力
                }
            }
        }

        return potential;
    }

    /**
     * 计算每张牌的出牌优先级（增强版）
     */
    private Map<Integer, Integer> calculateDiscardPriority(List<Integer> handCards, HandAnalysis analysis) {
        Map<Integer, Integer> priority = new HashMap<>();

        for (int card : handCards) {
            if (card == HONG_ZHONG) {
                priority.put(card, 1000); // 转转优先级很高（不应该打）
                continue;
            }

            // 听牌时，保护听牌组中的牌
            if (analysis.isTingPai && analysis.tingCards.contains(card)) {
                priority.put(card, 900); // 听牌组中的牌优先级很高
                continue;
            }

            // 获取牌的有用程度
            int usefulness = analysis.cardUsefulness.getOrDefault(card, 0);

            // 计算牌的潜力分数
            int potentialScore = calculateCardPotentialScore(card, analysis);

            // 综合评估优先级：有用程度 + 潜力分数
            int discardPriority = usefulness + potentialScore;

            // 孤张牌更容易被打出（降低优先级数值）
            if (analysis.isolatedCards.contains(card)) {
                discardPriority = Math.max(1, discardPriority - PENALTY_ISOLATED);

                // 特别处理：如果是完全孤立的边张牌（如1或9且没有相邻牌）
                int rank = card % 100;
                int suit = card / 100;
                if ((rank == 1 || rank == 9) &&
                        analysis.cardCounts.getOrDefault(suit * 100 + (rank == 1 ? 2 : 8), 0) == 0) {
                    discardPriority = Math.max(1, discardPriority - 20); // 进一步降低优先级
                }
            }

            // 边张牌（1和9）在不是对子或刻子的情况下优先级降低
            int rank = card % 100;
            if ((rank == 1 || rank == 9) && analysis.cardCounts.getOrDefault(card, 0) < 2) {
                discardPriority = Math.max(1, discardPriority - 10);
            }

            priority.put(card, discardPriority);
        }

        return priority;
    }

    private int selectCardToDiscard(List<Integer> handCards, Map<Integer, Integer> priority) {
        int minPriority = Integer.MAX_VALUE;
        List<Integer> candidateCards = new ArrayList<>();

        // 检查是否有可以打出后听牌的选项
        Map<Integer, Set<Integer>> discardToTingMap = findDiscardToTing(handCards);
        if (!discardToTingMap.isEmpty()) {
            // 如果有多个可打出后听牌的选项，选择其中一个
            Integer bestTingCard = discardToTingMap.keySet().iterator().next();
            System.out.println("发现可以打出后听牌的牌: " + bestTingCard);
            return bestTingCard;
        }

        // 正常选择优先级最低的牌
        for (int card : handCards) {
            int cardPriority = priority.getOrDefault(card, 50);

            // 选择优先级数值最小的牌（最应该打出的）
            if (cardPriority < minPriority) {
                minPriority = cardPriority;
                candidateCards.clear();
                candidateCards.add(card);
            } else if (cardPriority == minPriority) {
                candidateCards.add(card);
            }
        }

        if (!candidateCards.isEmpty()) {
            // 优先打出数量较多的相同牌
            if (candidateCards.size() > 1) {
                int maxCount = 0;
                int selectedCard = candidateCards.get(0);
                Map<Integer, Integer> countMap = new HashMap<>();

                for (int card : handCards) {
                    countMap.put(card, countMap.getOrDefault(card, 0) + 1);
                }

                for (int card : candidateCards) {
                    int count = countMap.getOrDefault(card, 0);
                    if (count > maxCount) {
                        maxCount = count;
                        selectedCard = card;
                    }
                }
                return selectedCard;
            }

            // 如果只有一张候选牌，直接返回
            return candidateCards.get(0);
        }

        return handCards.get(0);
    }

    /**
     * 判断是否应该碰牌
     */
    public boolean shouldPong(int proposedCard, List<Integer> currentHand) {
        System.out.println("判断是否应该碰牌: " + proposedCard);

        // 基础碰牌条件：手中已有两张相同的牌
        int count = 0;
        for (int card : currentHand) {
            if (card == proposedCard) {
                count++;
            }
        }

        if (count < 2) {
            System.out.println("- 手中没有两张相同的牌，无法碰");
            return false;
        }

        // 分析当前手牌状态
        HandAnalysis analysis = analyzeHand(currentHand);

        // 规则1：听牌时不能碰听牌组中的牌
        if (analysis.isTingPai && analysis.tingCards.contains(proposedCard)) {
            System.out.println("- 听牌时不能碰听牌组中的牌");
            return false;
        }

        // 规则2：有5个或更多对子时不能碰已成对子的牌
        int pairCount = countPairs(currentHand);
        if (pairCount >= 5) {
            System.out.println("- 对子数量过多，不建议碰牌");
            return false;
        }

        // 规则3：顺子的情况下不能碰
        if (isInSequence(proposedCard, currentHand)) {
            System.out.println("- 形成顺子的情况下，不建议碰牌");
            return false;
        }

        System.out.println("- 可以碰牌");
        return true;
    }

    /**
     * 计算手牌中的对子数量
     */
    private int countPairs(List<Integer> handCards) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (int card : handCards) {
            countMap.put(card, countMap.getOrDefault(card, 0) + 1);
        }

        int pairCount = 0;
        for (int count : countMap.values()) {
            pairCount += count / 2;
        }

        return pairCount;
    }

    /**
     * 检查牌是否在顺子中
     */
    private boolean isInSequence(int card, List<Integer> handCards) {
        int suit = card / 100;
        int rank = card % 100;

        // 检查是否有形成顺子的可能
        boolean hasPrev = handCards.contains(suit * 100 + (rank - 1));
        boolean hasNext = handCards.contains(suit * 100 + (rank + 1));

        return hasPrev && hasNext;
    }

    /**
     * 判断是否应该杠牌
     */
    public boolean shouldGang(int proposedCard, List<Integer> currentHand, int gangType) {
        System.out.println("判断是否应该杠牌: " + proposedCard + "，杠类型: " + gangType);

        // 计算手牌中该牌的数量
        int count = 0;
        for (int card : currentHand) {
            if (card == proposedCard) {
                count++;
            }
        }

        // 检查基础杠牌条件
        // 类型2: 明杠(从他人处获得)
        // 类型3: 吃杠(从他人处获得)
        // 类型4: 自杠
        // 类型5: 碰后补杠

        boolean hasEnoughCards = false;
        if (gangType == 2 || gangType == 3) {
            // 明杠和吃杠需要手中已有三张
            hasEnoughCards = (count >= 3);
        } else if (gangType == 4 || gangType == 5) {
            // 自杠和补杠需要手中有四张或之前已经碰了
            hasEnoughCards = (count >= 4) || (count >= 1);
        }

        if (!hasEnoughCards) {
            System.out.println("- 手中牌数量不足，无法杠");
            return false;
        }

        // 分析当前手牌状态
        HandAnalysis analysis = analyzeHand(currentHand);

        // 规则1：听牌时优先考虑杠牌，但不杠听牌组中的牌
        if (analysis.isTingPai && analysis.tingCards.contains(proposedCard)) {
            System.out.println("- 听牌时不杠听牌组中的牌");
            return false;
        }

        // 规则2：检查杠后是否会破坏已有搭子
        if (isInSequence(proposedCard, currentHand)) {
            System.out.println("- 杠牌会破坏顺子搭子，不建议杠");
            // 但是如果已经有刻子，杠牌还是可以考虑的
            int tripletCount = 0;
            for (List<Integer> meld : analysis.completedMelds) {
                if (meld.contains(proposedCard) && meld.size() == 3) {
                    tripletCount++;
                }
            }
            if (tripletCount == 0) {
                return false; // 没有刻子，不杠
            }
        }

        // 规则3：转转优先杠牌，增加灵活性
        if (proposedCard == HONG_ZHONG) {
            System.out.println("- 转转优先杠，增加灵活性");
            return true;
        }

        // 规则4：如果牌局前期，有杠就杠增加得分机会
        if (analysis.shantenCount >= 2) {
            System.out.println("- 牌局前期，建议杠牌增加得分机会");
            return true;
        }

        // 规则5：如果牌局后期，即将听牌，谨慎杠牌
        if (analysis.shantenCount == 1) {
            System.out.println("- 牌局后期，谨慎杠牌，优先听牌");
            // 计算杠牌后的手牌是否会变得更差
            List<Integer> tempHand = new ArrayList<>(currentHand);
            tempHand.remove(Integer.valueOf(proposedCard));
            HandAnalysis afterGangAnalysis = analyzeHand(tempHand);

            // 如果杠牌后向听数增加，不杠
            if (afterGangAnalysis.shantenCount > analysis.shantenCount) {
                System.out.println("- 杠牌后向听数增加，不建议杠");
                return false;
            }
        }

        System.out.println("- 可以杠牌");
        return true;
    }
}
