package robot.mj.handler;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TObject;
import com.taurus.core.plugin.redis.Redis;
import com.taurus.core.util.ICallback;
import redis.clients.jedis.Jedis;
import taurus.client.MessageResponse;
import taurus.client.TaurusClient;
import taurus.util.CardObj;
import taurus.util.CardUtil;
import taurus.util.test_smart;

import java.util.*;

public class HuNanPaoDeKuai {

    public int seat = 0;

    //座位号 剩余牌数量
    private final Map<Integer, List<Integer>> seatRemainHistory = new HashMap<>();
    
    // 跑的快玩家手牌
    private final List<CardObj> paoDekuaiCardInhand = new ArrayList<>();

    // 会话标识
    public String session = "";
    // 访问令牌
    public String token = "";

    //跑的快别人出的牌
    private  ITObject card_list = TObject.newInstance();

    public int guangboseat = 0;

    public int remain = 0;

    public Map<Integer, List<Integer>> getSeatRemainHistory() {
        return seatRemainHistory;
    }

    public List<CardObj> getPaoDekuaiCardInhand() {
        return paoDekuaiCardInhand;
    }

    public ITObject getCard_list() {
        return card_list;
    }

    public void setCard_list(ITObject cardList) {
        this.card_list = cardList;
    }

    private static final Gson gson = new Gson();


    /**
     * 将当前实例状态序列化为JSON字符串并保存到Redis
     * @param connecId 连接ID
     */
    public void saveToRedis(String connecId) {
        Jedis jedis = Redis.use("group1_db2").getJedis();
        try {
            Map<String, String> stateMap = new HashMap<>();

            stateMap.put("seatRemainHistory", gson.toJson(seatRemainHistory));
            stateMap.put("paoDekuaiCardInhand", gson.toJson(paoDekuaiCardInhand));
            stateMap.put("card_list", gson.toJson(card_list));

            stateMap.put("seat", String.valueOf(seat));
            stateMap.put("guangboseat", String.valueOf(guangboseat));
            stateMap.put("remain", String.valueOf(remain));


            stateMap.put("session", session);
            stateMap.put("token", token);

            String redisKey = "{pdk}:" + connecId;
            jedis.hmset(redisKey, stateMap);
            //1小时过期时间
            jedis.expire(redisKey, 3600);

            System.out.println("保存HuNanPaoDeKuai状态到Redis: " + connecId);
        } catch (Exception e) {
            System.err.println("保存HuNanPaoDeKuai状态到Redis失败: " + e.getMessage());
        } finally {
            jedis.close();
        }
    }

    /**
     * 从Redis恢复实例状态
     * @param connecId 连接ID
     * @return 是否成功恢复
     */
    public boolean restoreFromRedis(String connecId) {
        Jedis jedis = Redis.use("group1_db2").getJedis();
        try {
            String redisKey = "{pdk}:" + connecId;
            Map<String, String> stateMap = jedis.hgetAll(redisKey);

            if (stateMap == null || stateMap.isEmpty()) {
                System.out.println("Redis中没有找到HuNanPaoDeKuai状态数据: " + connecId);
                return false;
            }

            //反序列化集合
            if (stateMap.containsKey("seatRemainHistory")) {
                seatRemainHistory.clear();
                Map<Integer, List<Integer>> remainHistory = gson.fromJson(stateMap.get("seatRemainHistory"),
                        new TypeToken<Map<Integer, List<Integer>>>(){}.getType());
                if (remainHistory != null) seatRemainHistory.putAll(remainHistory);
            }

            if (stateMap.containsKey("paoDekuaiCardInhand")) {
                paoDekuaiCardInhand.clear();
                List<CardObj> handCards = gson.fromJson(stateMap.get("paoDekuaiCardInhand"),
                        new TypeToken<List<CardObj>>(){}.getType());
                if (handCards != null) paoDekuaiCardInhand.addAll(handCards);
            }

            if (stateMap.containsKey("card_list")) {
                String cardListJson = stateMap.get("card_list");
                if (cardListJson != null && !cardListJson.isEmpty()) {
                    card_list = TObject.newInstance();
                }
            }

            session = stateMap.getOrDefault("session", "");
            token = stateMap.getOrDefault("token", "");
            
            // 恢复关键状态字段
            if (stateMap.containsKey("seat")) {
                try {
                    seat = Integer.parseInt(stateMap.get("seat"));
                } catch (NumberFormatException e) {
                    seat = 0;
                }
            } else {
                seat = 0;
            }
            
            if (stateMap.containsKey("guangboseat")) {
                try {
                    guangboseat = Integer.parseInt(stateMap.get("guangboseat"));
                } catch (NumberFormatException e) {
                    guangboseat = 0;
                }
            } else {
                guangboseat = 0;
            }
            
            if (stateMap.containsKey("remain")) {
                try {
                    remain = Integer.parseInt(stateMap.get("remain"));
                } catch (NumberFormatException e) {
                    remain = 0;
                }
            }

            System.out.println("从Redis恢复HuNanPaoDeKuai状态成功: " + connecId + ", 手牌数量: " + paoDekuaiCardInhand.size());
            return true;
        } catch (Exception e) {
            System.err.println("从Redis恢复HuNanPaoDeKuai状态失败: " + e.getMessage());
            return false;
        } finally {
            jedis.close();
        }
    }

    /**
     * 从Redis清除实例状态
     * @param connecId 连接ID
     */
    public static void removeFromRedis(String connecId) {
        Jedis jedis = Redis.use("group1_db2").getJedis();
        try {
            String redisKey = "{pdk}:" + connecId;
            jedis.del(redisKey);
            System.out.println("从Redis删除HuNanPaoDeKuai状态: " + connecId);
        } catch (Exception e) {
            System.err.println("从Redis删除HuNanPaoDeKuai状态失败: " + e.getMessage());
        } finally {
            jedis.close();
        }
    }

    /**
     * 同步手牌
     * @param handCard
     */
    public void updateHandCard(List<Integer> handCard) {
        System.out.println("updateHandCard同步手牌:"+ handCard);
        paoDekuaiCardInhand.clear();
        System.out.println("updateHandCard同步手牌paoDekuaiCardInhand:"+ paoDekuaiCardInhand);
        for(Integer card : handCard) {
            paoDekuaiCardInhand.add(new CardObj(card));
        }
        System.out.println("updateHandCard同步手牌add:"+ paoDekuaiCardInhand);
    }

    public void ready(TaurusClient client){
        try {
            // 添加1秒延迟
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ITObject params = TObject.newInstance();
        params.putString("session", session + "," + token);

        client.send("1003", params, new ICallback<MessageResponse>() {

            @Override
            public void action(MessageResponse messageResponse) {


            }
        });
    }

    public String piao(TaurusClient client){
        List<Integer> sl = new ArrayList<>();
        sl.add(0);
        sl.add(2);
        sl.add(3);
        sl.add(5);
        int p = new Random().nextInt(3);
        ITObject params = TObject.newInstance();
        params.putInt("id", sl.get(p));
        client.send("1015", params, response -> {
        });
        return null;
    }
    
    /**
     * 出牌方法
     */
    public  String outCard(TaurusClient client) {
        try {

            ITArray itArray = null;
            itArray = test_smart.intelligentPaoDeKuaiOutCard(this, paoDekuaiCardInhand, card_list, seatRemainHistory);

            //无法跟牌且不是下家只剩一张牌的情况 则pass
            if (itArray == null && remain != 1) {
                System.out.println("无法跟牌，选择pass");
                return null;
            }
            
            if (remain == 1 && itArray == null) { //如果玩家的下家只有一张牌，玩家出单张必须是最大的
                CardObj maxSingleCard = CardUtil.findMaxSingleCard(paoDekuaiCardInhand);
                System.out.println("出的最大牌  " + maxSingleCard);
                itArray = CardUtil.toTArray1(maxSingleCard);
            }

            //跑得快出牌
            System.out.println("机器人出牌 " + seat + CardUtil.toList(itArray));
            ITObject params = TObject.newInstance();
            params.putString("session", session + "," + token);
            params.putTArray("card", itArray);
            params.putTArray("all_card", CardUtil.toTArray(paoDekuaiCardInhand));
            CardUtil.removeCard(paoDekuaiCardInhand, CardUtil.toList(itArray)); //删除手牌里打过的牌
            System.out.println("目前机器人剩余手牌：" + paoDekuaiCardInhand.toString());

            int ot = new Random().nextInt(5);
            Thread.sleep(ot * 1000);

            client.send("1013", params, response ->

            {
                System.out.println("出牌成功: " + response.returnCode);
            });
        }catch (Exception e) {
            System.err.println("出牌异常: " + e.getMessage());
            e.printStackTrace();
        }
        System.out.println("=== outCard方法执行结束 ===");
        return null;
    }

    /**
     * 跑得快初始化手牌
     *
     * @param param 消息参数
     * @return
     */
    public  String paoDeKuaiCardInHead(ITObject param, TaurusClient client) {
        ITArray cardList = param.getTArray("cards");
        List<CardObj> cardObjs = new ArrayList<>();
        if (cardList.size() != 0) {
            cardObjs = CardUtil.toList(cardList);
        }
        paoDekuaiCardInhand.addAll(cardObjs);
//        if (paoDekuaiCardInhand.size() > 14) {
//            outCard(client);
//            System.out.println("机器人:" + param.getInt("seat") + "为庄家，需要出牌" + ",牌为：" + paoDekuaiCardInhand.get(0));
//        }
        System.out.println("机器人:" + param.getInt("seat") + "初始化手牌" + ",牌为：" + paoDekuaiCardInhand.toString());
        return null;
    }

    /**
     * 跑的快出牌广播
     *
     * @param param 消息参数
     * @return
     */
    public  String paoDekuaiChupaiGuangBo(ITObject param) {
        //正确获取座位号
        Integer broadcastSeat = param.getInt("seat");//从seat字段获取座位号
        if (broadcastSeat != null) {
            guangboseat = broadcastSeat;
        } else {
            //从player字段获取座位号
            guangboseat = param.getInt("player");
        }
        
        //更新出牌信息
        ITObject cardObj = param.getTObject("card_obj");
        if (cardObj != null) {

            // 创建新的card_list对象，确保包含所有必要字段
            card_list = TObject.newInstance();
            
            // 复制card_obj中的所有字段
            if (cardObj.containsKey("card_list")) {
                card_list.putTArray("card_list", cardObj.getTArray("card_list"));
            }
            
            // 确保必要的字段存在
            if (cardObj.containsKey("min_card")) {
                card_list.putInt("min_card", cardObj.getInt("min_card"));
            }
            if (cardObj.containsKey("type")) {
                card_list.putInt("type", cardObj.getInt("type"));
            }
            if (cardObj.containsKey("len")) {
                card_list.putInt("len", cardObj.getInt("len"));
            }
            
            // 关键修复：根据实际牌数校验和修正type字段
            if (card_list.containsKey("card_list") && card_list.containsKey("type")) {
                int actualLen = card_list.getTArray("card_list").size();
                int reportedType = card_list.getInt("type");
                int reportedLen = card_list.getInt("len");
                

                // 根据实际牌数推断正确类型
                int inferredType = inferCorrectType(actualLen);
                if (inferredType != reportedType) {
                    System.out.println("[警告] 检测到类型不匹配! 报告类型:" + getCardTypeName(reportedType) + ", 推断类型:" + getCardTypeName(inferredType));
                    card_list.putInt("type", inferredType);
                }
                
                // 修正长度字段
                if (reportedLen != actualLen) {
                    card_list.putInt("len", actualLen);
                }
            }
            // 如果len字段缺失或为0，根据实际牌数计算
            else if (card_list.containsKey("card_list")) {
                int actualLen = card_list.getTArray("card_list").size();
                card_list.putInt("len", actualLen);

                // 同时推断类型
                int inferredType = inferCorrectType(actualLen);
                card_list.putInt("type", inferredType);
            }
            
        }
        
        remain = param.getInt("remain"); //剩余牌数量
        saveRemainHistory(guangboseat, remain);
        return null;
    }

    public  void saveRemainHistory(int guangboseat, int remain) {
        if (!seatRemainHistory.containsKey(guangboseat)) {
            seatRemainHistory.put(guangboseat, new ArrayList<>());
        }
        seatRemainHistory.get(guangboseat).add(remain);
    }

    /** 根据牌数推断正确的牌型 */
    private int inferCorrectType(int len) {
        switch (len) {
            case 1: return 1; // 单牌
            case 2: return 2; // 对子
            case 3: return 5; // 三张
            case 4: return 8; // 炸弹
            case 5: return 7; // 三带二
            case 6: return 4; // 连对（2连对=4张，3连对=6张）
            case 8: return 4; // 连对（4连对=8张）
            case 10: return 4; // 连对（5连对=10张）
            case 12: return 10; // 飞机带牌（333444+55+66）
            default:
                // 连对（偶数张牌）
                if (len >= 4 && len % 2 == 0) return 4;
                // 飞机带牌（5的倍数）
                if (len >= 10 && len % 5 == 0) return 10;
                // 顺子（5张及以上连续单牌）
                if (len >= 5) return 3;
                // 默认返回单牌
                return 1;
        }
    }
    
    /** 牌型数字转名称 */
    private String getCardTypeName(int type) {
        switch (type) {
            case 1: return "单牌";
            case 2: return "对子";
            case 3: return "顺子";
            case 4: return "连对";
            case 5: return "三张";
            case 7: return "三带二";
            case 8: return "炸弹";
            case 9: return "飞机";
            case 10: return "飞机带牌";
            case 11: return "四带二";
            case 12: return "四带两对";
            default: return "未知(" + type + ")";
        }
    }


}