package robot.mj;

import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TObject;
import com.taurus.core.events.Event;
import com.taurus.core.events.IEventListener;
import com.taurus.core.plugin.redis.Redis;
import com.taurus.core.util.StringUtil;
import robot.mj.business.AccountBusiness;
import robot.mj.handler.HuNanPaoDeKuai;
import robot.mj.info.RobotUser;
import taurus.client.Message;
import taurus.client.MessageResponse;
import taurus.client.TaurusClient;
import taurus.client.SocketCode;
import redis.clients.jedis.Jedis;

import java.util.*;
import java.util.concurrent.*;

import static robot.mj.EXGameController.robotRoomMapping;

/**
 * 机器人连接管理器 - 管理与游戏服务器的连接
 */
public class RobotConnectionManager {

    private static final Map<String, HuNanPaoDeKuai> huNanPaoDeKuaiInstances = new ConcurrentHashMap<>();
    private final EXGameController exGameController;

    private final String host = Config.GAME_SERVER_HOST;
    private final int port = Integer.parseInt(Config.GAME_SERVER_PORT);


    public RobotConnectionManager() {
        exGameController = new EXGameController();
    }

    /**
     * 获取跑得快处理器实例
     */
    private HuNanPaoDeKuai getHuNanPaoDeKuaiInstance(String connecId) {
        HuNanPaoDeKuai existingInstance = huNanPaoDeKuaiInstances.get(connecId);
        if (existingInstance != null) {
            return existingInstance;
        }

        HuNanPaoDeKuai newInstance = new HuNanPaoDeKuai();

        //从Redis恢复状态
        boolean restored = newInstance.restoreFromRedis(connecId);
        if (restored) {
            System.out.println("从Redis恢复HuNanPaoDeKuai实例: " + connecId);
        } else {
            System.out.println("创建新的HuNanPaoDeKuai实例: " + connecId);
        }

        huNanPaoDeKuaiInstances.put(connecId, newInstance);
        System.out.println("当前HuNanPaoDeKuai实例总数: " + huNanPaoDeKuaiInstances.size());
        return newInstance;
    }

    /**
     * 设置会话和令牌
     */
    public void setSessionAndToken(String session, String token, String connecId) {
        HuNanPaoDeKuai instance = getHuNanPaoDeKuaiInstance(connecId);
        instance.session = session;
        instance.token = token;
    }

    /**
     * 连接到跑得快游戏服务器
     */
    public TaurusClient connectToGameServer(String connecId) {
        try {
            //创建Taurus客户端
            TaurusClient client = new TaurusClient(host + ":" + port, "game", TaurusClient.ConnectionProtocol.Tcp);

            //设置事件监听器
            setupEventListeners(client, connecId);

            client.connect();

            return client;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 断开与游戏服务器的连接（主动断开）
     */
    public void disconnectFromGameServer(String connecId) {
        System.out.println("开始主动断开连接: {"+connecId+"}");
        RobotUser robotUser = robotRoomMapping.remove(connecId);

        //清理连接数据
        if (connecId != null) {
            HuNanPaoDeKuai.removeFromRedis(connecId);

            HuNanPaoDeKuai instance = huNanPaoDeKuaiInstances.get(connecId);
            if (instance != null) {
                instance.getPaoDekuaiCardInhand().clear();
                instance.getSeatRemainHistory().clear();
                System.out.println("清空HuNanPaoDeKuai集合数据: " + connecId);
            }

            huNanPaoDeKuaiInstances.remove(connecId);
        }

        if (robotUser != null) {
            TaurusClient client = robotUser.getClient();
            if (client != null) {
                try {
                    if (client.isConnected()) {
                        client.killConnection();
                    }
                    System.out.println("客户端主动断开连接完成: {"+connecId+"}");
                } catch (Exception e) {
                    System.out.println("断开客户端连接时发生异常: " + connecId + ", 错误: " + e.getMessage());
                }
            } else {
                System.out.println("客户端连接不存在: {"+connecId+"}");
            }
        }
    }

    /**
     * 设置事件监听器
     */
    public void setupEventListeners(TaurusClient client, String connecId) {
        //添加消息事件监听器
        IEventListener messageListener = new IEventListener() {
            @Override
            public void handleEvent(Event event) {
                //获取 msg
                Message message = (Message) event.getParameter("msg");

                ITObject param = message.param;
                //回调协议号
                String command = message.command;
                System.out.println("csmj OnEvent msg： " + command);

                //根据玩法ID处理不同的回调
                if (StringUtil.isNotEmpty(command)) {
                    //直接处理协议
                    handleProtocol(command, message, client, connecId);
                }
            }
        };

        //添加连接状态监听器
        IEventListener connectListener = new IEventListener() {
            @Override
            public void handleEvent(Event event) {
                Message message = (Message) event.getParameter("msg");
                SocketCode code = (SocketCode) event.getParameter("code");

            }
        };

        //注册事件监听器
        client.addEventListener(TaurusClient.NetClientEvent.OnEvent, messageListener);
        client.addEventListener(TaurusClient.NetClientEvent.Connect, connectListener);
    }


    /**
     * 机器人断线重连
     */
    public void reconnectToGameServer(MessageResponse response, RobotUser robotUser, TaurusClient client) {
        String connecId = robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId();
        if(client.isConnected()){
            try {
                ITObject obj = response.messageData.param.getTObject("tableInfo");
                ITObject reloadInfo = response.messageData.param.getTObject("reloadInfo");
                if (obj != null) {
                    //处理 seat
                    //获取机器人的seat
                    ITArray playerData = obj.getTArray("playerData");
                    Integer robotSeat = null;
                    for (int i = 0; i < playerData.size(); i++) {
                        ITObject tms = playerData.getTObject(i);
                        Integer tmuserid = tms.getInt("aid");
                        if (tmuserid == Integer.parseInt(robotUser.getRobotId())) {
                            robotSeat = tms.getInt("seat");
                            robotUser.setSeat(robotSeat);
                            //同步到HuNanPaoDeKuai实例
                            HuNanPaoDeKuai currentInstance = getHuNanPaoDeKuaiInstance(connecId);
                            currentInstance.seat = robotSeat;
                            System.out.println("断线重连：设置机器人座位号 seat=" + robotSeat);
                        }
                    }
                    System.out.println("playerData:" + playerData);

                    System.out.println("obj:" + obj);
                    System.out.println("reloadInfo:" + reloadInfo);
                    if (reloadInfo != null) {
                        //重连回来的
                        //同步手牌
                        ITArray hand_card = reloadInfo.getTArray("hand_card");
                        ITArray info_list = reloadInfo.getTArray("info_list");

                        List<Integer> hcard = new ArrayList<>();
                        if (hand_card != null) {
                            for (int i = 0; i < hand_card.size(); i++) {
                                hcard.add(hand_card.getInt(i));
                            }
                        }
                        
                        System.out.println("hcard>0" + hcard);
                        if (hcard.size() > 0) {
                            //同步手牌
                            HuNanPaoDeKuai currentInstance = getHuNanPaoDeKuaiInstance(connecId);

                            //同步手牌逻辑
                            if (hcard.size() > currentInstance.getPaoDekuaiCardInhand().size()) {
                                //服务器手牌更多 说明有新牌需要更新
                                currentInstance.updateHandCard(hcard);
                                System.out.println("断线重连：同步手牌数据，服务器手牌:" + hcard);
                            } else {
                                System.out.println("断线重连：本地手牌数量充足，无需更新");
                            }

                            //同步最后出牌信息 获取上家出牌信息
                            if(reloadInfo != null) {
                                //获取当前出牌的座位号
                                Integer lastOutCardSeat = reloadInfo.getInt("last_outcard_seat");
                                System.out.println("断线重连：上家座位号 = " + lastOutCardSeat);
                                
                                if(lastOutCardSeat != null && info_list != null) {
                                    //找到上家的出牌记录
                                    for (int i = 0; i < info_list.size(); i++) {
                                        ITObject playerInfo = info_list.getTObject(i);
                                        Integer playerid = playerInfo.getInt("playerid");
                                        Integer seat = getPlayerSeat(obj, playerid);

                                        //找到上家的出牌信息
                                        if(seat != null && seat.equals(lastOutCardSeat)) {
                                            //从last_outcard路径获取上家最新出牌信息
                                            ITObject lastOutCard = playerInfo.getTObject("last_outcard");
                                            if(lastOutCard != null) {
                                                //提取最后出牌的关键信息
                                                int minCard = lastOutCard.getInt("min_card");
                                                int len = lastOutCard.getInt("len");
                                                int type = lastOutCard.getInt("type");
                                                ITArray cardList = lastOutCard.getTArray("card_list");

                                                ITObject syncedCardList = TObject.newInstance();
                                                syncedCardList.putTArray("card_list", cardList);
                                                syncedCardList.putInt("min_card", minCard);
                                                syncedCardList.putInt("len", len);
                                                syncedCardList.putInt("type", type);

                                                currentInstance.setCard_list(syncedCardList);
                                                System.out.println("断线重连：同步上家最后出牌数据 - seat:" + seat + ", min_card:" + minCard + ", len:" + len + ", type:" + type + ", cards:" + cardList);
                                            } else {
                                                System.out.println("断线重连：上家seat=" + seat + "没有last_outcard信息");
                                                //如果上家没有出牌信息 清空card_list
                                                currentInstance.setCard_list(TObject.newInstance());
                                            }
                                            break;
                                        }
                                    }
                                } else {
                                    System.out.println("断线重连：未找到有效的last_outcard_seat或info_list为空");
                                    //清空出牌记录以避免使用过期数据
                                    currentInstance.setCard_list(TObject.newInstance());
                                }
                            }

                            sleepTime(2000);
                            //重连完成后强制同步座位号状态
                            if (robotSeat != null) {
                                currentInstance.seat = robotSeat;
                                System.out.println("重连后强制同步座位号: seat=" + robotSeat);
                            } else {
                                System.err.println("警告：未能获取到机器人座位号，使用默认值0");
                                currentInstance.seat = 0;
                            }
                            
                            //验证seat和guangboseat不同
                            if (currentInstance.seat == currentInstance.guangboseat && currentInstance.guangboseat != 0) {
                                System.err.println("严重警告：seat和guangboseat相同！seat=" + currentInstance.seat + ", guangboseat=" + currentInstance.guangboseat);
                                //强制修正
                                currentInstance.seat = (currentInstance.guangboseat == 1) ? 2 : 1;
                                System.out.println("已强制修正seat为: " + currentInstance.seat);
                            }
                            
                            currentInstance.outCard(client);
                        } else {
                            System.err.println("警告：重连时未获取到手牌数据");
                        }
                    }
                }
            }finally {

            }
        }else {
            renconnect(robotUser);
        }
    }

    /**
     * 处理接收到的游戏协议
     */
    private void handleProtocol(String command, Message message, TaurusClient client, String connecId) {
        RobotUser robotUser = robotRoomMapping.get(connecId);
        int robotId = Integer.parseInt(robotUser.getRobotId());
        ITObject param = message.param;
        HuNanPaoDeKuai huNanPaoDeKuai = getHuNanPaoDeKuaiInstance(connecId);
        Jedis jedis0 = Redis.use().getJedis();
        Jedis jedis2 = Redis.use("group1_db2").getJedis();
        try {
            //跑得快 机器人处理事件
            //跑的快 初始化手牌
            if ("2011".equalsIgnoreCase(command)) {
                huNanPaoDeKuai.paoDeKuaiCardInHead(param, client);
                //处理完协议后保存到Redis
                HuNanPaoDeKuai currentInstance = huNanPaoDeKuaiInstances.get(connecId);
                currentInstance.saveToRedis(connecId);
            }
            //出牌广播
            else if ("2021".equalsIgnoreCase(command)) {
                huNanPaoDeKuai.paoDekuaiChupaiGuangBo(param);
                //处理完协议后保存到Redis
                HuNanPaoDeKuai currentInstance = huNanPaoDeKuaiInstances.get(connecId);
                currentInstance.saveToRedis(connecId);
            }
            //出牌提示事件，牌权
            else if ("2004".equalsIgnoreCase(command)) {
                Integer player = param.getInt("player");
                Integer seat1 = param.getInt("seat");
                System.out.println("跑的快seat1 77777777777777777777777777" + seat1);
                System.out.println("跑的快palyer6666666666666666666666666" + player);
                
                //增加调试信息
                System.out.println("=== 2004协议调试信息 ===");
                System.out.println("当前机器人seat: " + huNanPaoDeKuai.seat);
                System.out.println("协议中的seat1: " + seat1);
                System.out.println("协议中的player: " + player);
                System.out.println("机器人ID: " + robotUser.getRobotId());
                
                if (seat1 != null) {
                    huNanPaoDeKuai.seat = seat1;
                    System.out.println("更新seat为: " + seat1);
                }

                //出牌
                System.out.println("准备调用outCard方法");
                huNanPaoDeKuai.outCard(client);
                //处理完协议后保存到Redis
                HuNanPaoDeKuai currentInstance = huNanPaoDeKuaiInstances.get(connecId);
                currentInstance.saveToRedis(connecId);
                System.out.println("2004协议处理完成");
            }
            //结算准备
            else if ("2007".equalsIgnoreCase(command)) {
                //type为1 为大结算  type为0为小结算
                Integer type = param.getInt("type");
                System.out.println("type ++++++++++++++++++++++++" + type);
                if (type == 0) {
                    huNanPaoDeKuai.getSeatRemainHistory().clear();
                    huNanPaoDeKuai.getPaoDekuaiCardInhand().clear();
                    ITArray card_list = huNanPaoDeKuai.getCard_list().getTArray("card_list");
                    card_list.clear();
                    huNanPaoDeKuai.ready(client);
                }

                if (type == 1) {
                    updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
                }

            }
            else if ("2009".equalsIgnoreCase(command)) {
                CompletableFuture.runAsync(() -> {
                    Integer paramRobotId = param.getInt("aid");
                    sleepTime(6000);

                    if (robotUser != null) {
                        String roomKey = String.valueOf(robotUser.getCurrentRoomId());

                        //查询该房间的玩家信息
                        String playersStr = jedis0.hget(roomKey, "players");
                        if (!playersStr.equals("[]")) {
                            String players = playersStr.substring(1, playersStr.length() - 1);
                            String[] playerIds = players.split(",");

                            //判断只有当前机器人一个玩家
                            if (playerIds.length == 1) {
                                int playerId = Integer.parseInt(playerIds[0].trim());
                                if (playerId == paramRobotId) {

                                    String gpid = jedis0.hget(roomKey, "gpid");
                                    String gpId = jedis0.hget(roomKey, "group");

                                    //发送退出房间协议
                                    ITObject params = TObject.newInstance();
                                    client.send("1005", params, response -> {
                                        EXGameController.removeRobotRoomInfo(String.valueOf(paramRobotId));
                                        //断开连接
                                        disconnectFromGameServer(connecId);
                                        //更新机器人剩余数量
                                        updateLeftoverRobot(paramRobotId);
                                        System.out.println("2009发送退出房间协议1005，robotId: {"+paramRobotId+"}");
                                    });
                                }
                            }
                        }
                    }
                });
            }
            //解散房间时候恢复机器人账号可以使用
            else if ("2008".equalsIgnoreCase(command)) {
                updateLeftoverRobot(Integer.parseInt(robotUser.getRobotId()));
                disconnectFromGameServer(connecId);
            }else if("2031".equalsIgnoreCase(command)) {
                //飘回复
                huNanPaoDeKuai.piao(client);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            jedis0.close();
            jedis2.close();
        }
    }

    /**
     * 增加leftover_robot数量 机器人退出房间
     */
    private void updateLeftoverRobot(int robotId) {
        Jedis jedis2 = Redis.use("group1_db2").getJedis();
        try {

            jedis2.hset("gallrobot", String.valueOf(robotId), "0");

            jedis2.hset("{grobot}:" + robotId, "start", "0");

            System.out.println("机器人 {"+robotId+"} 退出房间，修改gallrobot为0");
        } finally {
            jedis2.close();
        }
    }

    /**
     * 机器人登录
     */
    public void login(RobotUser robotUser){
        System.out.println("login:"+robotUser.getRobotId());
        ITObject object = null;
        AccountBusiness accountBusiness = null;
        accountBusiness = new AccountBusiness();
        try {
            //先快速登录
            object = accountBusiness.fastLogin(Integer.parseInt(robotUser.getRobotId()));
            System.out.println("object:"+object);
            if(object==null){
                object = accountBusiness.idPasswordLogin(Integer.parseInt(robotUser.getRobotId()), robotUser.getPassword());
            }
            ITObject finalObject = object;
            CompletableFuture.runAsync(() -> {
                if (finalObject != null) {
                    //判断是否有房间
                    if(finalObject.getTObject("account")!=null){
                        ITObject validate = TObject.newInstance();
                        validate.putString("token", finalObject.getString("token"));
                        robotUser.setToken(finalObject.getString("token"));;
                        robotUser.setLoginsession("{user}:"+robotUser.getRobotId());
                        if (robotUser.getLoginsession() != null) {
                            robotUser.setIsLogin(true);
                        }
                        if(finalObject.getTObject("account").get("roomid")!=null){
                            String roomid = finalObject.getTObject("account").get("roomid").toString();
                            robotUser.setCurrentRoomId(Integer.parseInt(roomid));
                            connectGame(robotUser);

                            robotUser.setConnecId(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId());
                            System.err.println("重启获取的机器人还有当前房间，准备加入: "+robotUser.getConnecId());
                            exGameController.webGroupJoinRoom(robotUser);
                        }
                    }
                }
            });
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void connectGame(RobotUser robotUser){
        if(robotUser.isLogin){
            if(robotUser.getClient()==null){
                TaurusClient client = new TaurusClient(robotUser.getGameHost()+":"+robotUser.getGamePort(), "game", TaurusClient.ConnectionProtocol.Tcp);
                client.setSession(robotUser.getLoginsession());
                client.connect();
                setupEventListeners(client, robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId());
                robotUser.setIsconnect(client.isConnected());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                robotUser.setClient(client);
                EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
            }else{
                System.out.println("reconnect");
                System.out.println("client.isConnected()"+robotUser.getClient().isConnected());
                if(robotUser.getClient().isConnected()){
                    robotUser.setIsconnect(true);
                }else{
                    System.out.println("reconnect"+robotUser.getClient().getGameID());
                    TaurusClient client = new TaurusClient(robotUser.getGameHost()+":"+robotUser.getGamePort(), "game", TaurusClient.ConnectionProtocol.Tcp);
                    client.setSession(robotUser.getLoginsession());
                    client.connect();
                    robotUser.setIsconnect(client.isConnected());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    robotUser.setClient(client);
                    EXGameController.robotRoomMapping.put(robotUser.getCurrentRoomId()+"_"+robotUser.getRobotId(), robotUser);
                }
            }
        }
    }

    /**
     * 重连
     */
    public void renconnect(RobotUser robotUser){
        TaurusClient client = robotUser.getClient();
        if(client!=null){
            if(client.isConnected()){
                client.connect();
                robotUser.setIsconnect(client.isConnected());
            }
        }
    }

    /**
     * 根据connecId获取游戏服务器连接
     */
    public TaurusClient getGameClient(String connecId) {
        return robotRoomMapping.get(connecId) != null ? robotRoomMapping.get(connecId).getClient() : null;
    }


    public int getTime(){
        return Integer.parseInt((System.currentTimeMillis() + "").substring(0, 10));
    }

    public static void sleepTime(int time) {
        try {
            //添加延迟
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据玩家ID获取座位号
     */
    private Integer getPlayerSeat(ITObject tableInfo, Integer playerId) {
        if (tableInfo == null || playerId == null) return null;
        
        ITArray playerData = tableInfo.getTArray("playerData");
        if (playerData != null) {
            for (int i = 0; i < playerData.size(); i++) {
                ITObject player = playerData.getTObject(i);
                Integer aid = player.getInt("aid");
                if (aid != null && aid.equals(playerId)) {
                    return player.getInt("seat");
                }
            }
        }
        return null;
    }

}