package robot.mj;

import com.robot.GameController;
import com.robot.GameInterceptor;
import com.robot.MainServer;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TObject;
import com.taurus.core.plugin.redis.Redis;
import com.taurus.core.routes.ActionKey;
import com.taurus.permanent.data.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import robot.mj.info.RobotUser;
import taurus.client.TaurusClient;
import taurus.client.business.GroupRoomBusiness;
import taurus.util.ROBOTEventType;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 红中麻将游戏控制器 - 处理游戏协议
 */
public class EXGameController extends GameController {
    private static final Logger log = LoggerFactory.getLogger(EXGameController.class);

    private static final RobotConnectionManager robotConnectionManager = new RobotConnectionManager();

    //机器人房间
    protected static final Map<String, RobotUser> robotRoomMapping = new ConcurrentHashMap<>();

    public EXGameController() {
        super();
        log.info("红中麻将游戏控制器已初始化");
    }

    /**
     * 处理客户端初始化/认证协议
     */
    @ActionKey(value = Config.INIT_CONNECTION, validate = GameInterceptor.NOT_PLAYER)
    public void handleInitialization(Session session, ITObject params, int gid) {
        try {
            log.info("收到客户端初始化请求，Session: {}, GID: {}, 参数: {}", session, gid, params);

            String type = params.getString("type");
            String client = params.getString("client");
            log.info("客户端类型: {}, 客户端标识: {}", type, client);

            //验证参数
            if ("robot_mj_cs".equals(type) && "robot_mgr".equals(client)) {
                //返回成功响应
                ITObject response = TObject.newInstance();
                response.putString("status", "success");
                response.putString("message", "初始化成功");

                log.info("客户端初始化成功，发送响应");
                MainServer.instance.sendResponse(gid, 0, response, session);
            } else {
                log.warn("客户端初始化失败，参数验证不通过: type={}, client={}", type, client);

                ITObject response = TObject.newInstance();
                response.putString("status", "failed");
                response.putString("message", "参数验证失败");
                MainServer.instance.sendResponse(gid, 1, response, session);
            }
        } catch (Exception e) {
            log.error("处理初始化请求时发生错误", e);

            ITObject response = TObject.newInstance();
            response.putString("status", "error");
            response.putString("message", "服务器内部错误: " + e.getMessage());

            MainServer.instance.sendResponse(gid, 1, response, session);
        }
    }

    /**
     * 接收来自robot_mgr的创建房间协议
     */
    @ActionKey(value = Config.CREATE_ROOM_ROBOT, validate = GameInterceptor.NOT_PLAYER)
    public void createRoomForRobot(Session session, ITObject params, int gid) {
        try {
            int reqGroupId = params.getInt("groupId");
            int wanfaId = params.getInt("wanfaId");
            int robotId = params.getInt("robotId");

            //使用统一的房间创建器在Redis中创建房间
            RoomCreator.RoomInfo roomInfo = RoomCreator.createRoomInRedis(reqGroupId, wanfaId, robotId);

            if (roomInfo != null) {
                //返回房间信息给robot_mgr
                ITObject response = TObject.newInstance();
                response.putString("roomKey", roomInfo.getRoomId());
                response.putInt("groupId", roomInfo.getGroupId());
                response.putInt("wanfaId", roomInfo.getWanfaId());
                response.putInt("robotId", robotId);
                response.putString("server_ip", roomInfo.getServerIp());
                response.putInt("server_port", roomInfo.getServerPort());

                log.info("成功创建房间，房间ID: {}", roomInfo.getRoomId());
                //使用Taurus框架方法发送响应
                MainServer.instance.sendResponse(gid, 0, response, session);
            } else {
                log.error("创建房间失败，群组ID: {}, 玩法ID: {}", reqGroupId, wanfaId);
            }
        } catch (Exception e) {
            log.error("处理创建房间请求时发生错误", e);
        }
    }

    /**
     * 接收来自robot_mgr的加入房间协议
     */
    @ActionKey(value = Config.JOIN_ROOM, validate = GameInterceptor.NOT_PLAYER)
    public void joinRoom(Session session, ITObject params, int gid) {
        try {
            String connecId = params.getString("connecId");
            TaurusClient client = getCsMjGameServerConnection(connecId);
            System.out.println("接收来自robot_mgr的加入房间协议 connecId: = "+connecId);
            System.out.println("接收来自robot_mgr的加入房间协议 client: = "+client);
            if (client == null) {
                ITObject errorResponse = TObject.newInstance();
                errorResponse.putString("status", "failed");
                errorResponse.putString("message", "无法获取游戏服务器连接");
                MainServer.instance.sendResponse(gid, 1, errorResponse, session);
                return;
            }

            //设置session和token
            String sessionToken = params.getString("session");
            String robotSession = null;
            String token = null;
            if (sessionToken != null && sessionToken.contains(",")) {
                String[] sessionParts = sessionToken.split(",");
                if (sessionParts.length >= 2) {
                    robotSession = sessionParts[0];
                    token = sessionParts[1];
                    robotConnectionManager.setSessionAndToken(robotSession, token, connecId);
                }
            }

            Integer groupId = params.getInt("groupId");
            String roomId = params.getString("roomId");
            String robotId = params.getString("robotId");

            GroupRoomBusiness.joinRoom(groupId, roomId, robotSession, null);

            Thread.sleep(5000);

            params.del("groupId");
            params.del("roomId");
            params.del("connecId");
            //发送加入房间请求到game_mj_cs
            client.send(Config.JOIN_ROOM_CS, params, response -> {
                System.out.println("joinRoomController: " + response);
                RobotUser roomInfo = new RobotUser();
                roomInfo.setCurrentRoomId(Integer.parseInt(roomId));
                roomInfo.setConnecId(connecId);
                roomInfo.setUserId(0);
                //机器人房间映射关系
                robotRoomMapping.put(robotId, roomInfo);
            });

            ITObject paramsReq = TObject.newInstance();
            paramsReq.putString("status", "success");
            MainServer.instance.sendResponse(gid, 0, paramsReq, session);

        } catch (Exception e) {
            log.error("处理加入房间请求时发生错误", e);
            ITObject errorResponse = TObject.newInstance();
            errorResponse.putString("status", "error");
            errorResponse.putString("message", "处理加入房间请求时发生错误: " + e.getMessage());
            MainServer.instance.sendResponse(gid, 1, errorResponse, session);
        }
    }

    /**
     * 接收来自robot_mgr的机器人准备协议
     */
    @ActionKey(value = Config.GAME_READY, validate = GameInterceptor.NOT_PLAYER)
    public void robotReadyRoom(Session session, ITObject params, int gid) {
        try {
            String connecId = params.getString("connecId");
            TaurusClient client = getCsMjGameServerConnection(connecId);
            System.out.println("接收来自robot_mgr的机器人准备协议 connecId: = "+connecId);
            System.out.println("接收来自robot_mgr的机器人准备协议 client: = "+client);
            if (client == null) {
                ITObject errorResponse = TObject.newInstance();
                errorResponse.putString("status", "failed");
                errorResponse.putString("message", "无法获取游戏服务器连接");
                MainServer.instance.sendResponse(gid, 1, errorResponse, session);
                return;
            }

            params.del("connecId");
            Thread.sleep(1000);
            //发送准备请求到game_mj_cs
            client.send(Config.GAME_READY_CS, params, response -> {
                System.out.println("robotReadyRoom: " + response);
            });

            ITObject paramsReq = TObject.newInstance();
            paramsReq.putString("status", "success");
            MainServer.instance.sendResponse(gid, 0, paramsReq, session);

        } catch (Exception e) {
            log.error("处理机器人准备请求时发生错误", e);
            ITObject errorResponse = TObject.newInstance();
            errorResponse.putString("status", "error");
            errorResponse.putString("message", "服务器内部错误: " + e.getMessage());
            MainServer.instance.sendResponse(gid, 1, errorResponse, session);
        }
    }

    /**
     * 接收来自web_group的加入房间协议
     */
    @ActionKey(value = Config.WEB_GROUP_JOIN_ROOM, validate = GameInterceptor.NOT_PLAYER)
    public void webGroup(Session session, ITObject params, int gid) {
        int robotId = params.getInt("robotid");
        String roomId = params.getString("roomid");
        int groupId = params.getInt("groupid");
        
        //防止玩家操作同一房间 导致其他机器人加入
        List<RobotUser> robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId));
        if (!robotUsers.isEmpty()) {
            synchronized (robotUsers) {
                RobotUser robotUser = robotUsers.get(0);
                if (robotId != Integer.parseInt(robotUser.getRobotId())) {
                    System.err.println("房间{"+ roomId +"}中已有机器人{"+robotUser.getRobotId()+"}，当前机器人{"+robotId+"}不执行加入逻辑");
                    return;
                }
            }
        }
        System.err.println("225开始进房间: "+"room:"+ roomId +"robot:"+robotId);
        //加入房间
        joinRoomCommon(robotId, roomId, groupId, params);
        System.err.println("225已进入房间准备成功: "+"room:"+ roomId +"robot:"+robotId);
    }

    /**
     * 接收来自web_group的主动重连协议
     */
    @ActionKey(value = Config.WEB_GROUP_ACTIVE_RECONNECT, validate = GameInterceptor.NOT_PLAYER)
    public void webGroupActive(Session session, ITObject params, int gid) {
        int robotId = params.getInt("robotid");
        String roomId = params.getString("roomid");
        //检查Redis中该房间是否真的包含当前机器人
        if (!checkRobotInRoomRedis(roomId, String.valueOf(robotId))) {
            //Redis中不存在该机器人 清理本地可能的错误映射
            List<RobotUser> robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId));
            if (!robotUsers.isEmpty()) {
                synchronized (robotUsers) {
                    RobotUser robotUser = robotUsers.get(0);
                    System.err.println("房间{"+ roomId +"}中Redis未找到机器人{"+robotId+"}，但本地映射存在{"+robotUser.getRobotId()+"}，清理本地映射");
                    robotRoomMapping.remove(robotUser.getConnecId());
                    robotRoomMapping.remove(robotUser.getRobotId());
                }
            }
        } else {
            //Redis中存在该机器人 检查是否是不同机器人的冲突
            List<RobotUser> robotUsers = getRobotUsersByRoomId(Integer.parseInt(roomId));
            if (!robotUsers.isEmpty()) {
                synchronized (robotUsers) {
                    RobotUser robotUser = robotUsers.get(0);
                    int existingRobotId = Integer.parseInt(robotUser.getRobotId());

                    if (robotId != existingRobotId) {
                        //不同机器人的冲突
                        System.err.println("房间{"+ roomId +"}中Redis已存在机器人{"+existingRobotId+"}，当前机器人{"+robotId+"}不执行加入逻辑");
                        return;
                    }
                }
            }
        }
        System.err.println("226开始进房间: " + "room:" + roomId + "robot:" + robotId);
        //加入房间
        joinRoomCommon(params.getInt("robotid"), params.getString("roomid"), params.getInt("groupid"), params);
        System.err.println("226已进入房间准备成功: " + "room:" + roomId + "robot:" + robotId);
    }

    /**
     * 重启服务断线重连
     * */
    public void webGroupJoinRoom(RobotUser robotUser) {
        String connecId = robotUser.getConnecId();
        Jedis jedis0 = Redis.use("group1_db0").getJedis();
        Jedis jedis2 = Redis.use("group1_db2").getJedis();
        //重启检查
        try {
            Set<String> robotTokens = jedis0.smembers("{user}:"+robotUser.getRobotId()+"_token");
            String robotSession = null;

            for (String token : robotTokens) {
                if (jedis0.exists(token)) {
                    robotSession = token;
                    break;
                }
            }
            String gallrobot = jedis2.hget("gallrobot", robotUser.getRobotId());
            if (gallrobot.equals("0")) {
                robotRoomMapping.remove(connecId);
                return;
            }

            System.err.println("重启后开始进房间: " + "room:" + robotUser.getCurrentRoomId() + "robot:" + robotUser.getRobotId());
            ITObject params = new TObject();
            params.putString("session", "{user}:" + robotUser.getRobotId() + "," + robotSession);
            //加入房间
            joinRoomCommon(Integer.parseInt(robotUser.getRobotId()), String.valueOf(robotUser.getCurrentRoomId()), Integer.parseInt(robotUser.getRobotGroupid()), params);
            System.err.println("重启后已进入房间准备成功: " + "room:" + robotUser.getCurrentRoomId() + "robot:" + robotUser.getRobotId());

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

    /**
     * 加入房间逻辑
     */
    private void joinRoomCommon(int robotId, String roomId, int groupId, ITObject params) {
        Jedis jedis0 = Redis.use("group1_db0").getJedis();
        Jedis jedis2 = Redis.use("group1_db2").getJedis();
        try {
            Set<String> robotTokens = jedis0.smembers("{user}:" + robotId + "_token");
            String robotSession = null;

            for (String token : robotTokens) {
                if (jedis0.exists(token)) {
                    robotSession = token;
                    break;
                }
            }

            System.err.println("开始进房间: room:" + roomId);
            System.err.println("开始进房间: {user}:" + robotId);

            TaurusClient client = getCsMjGameServerConnection(roomId + "_" + robotId);
            GroupRoomBusiness.joinRoom(groupId, "room:" + roomId, "{user}:" + robotId, null);

            //机器人房间映射关系
            RobotUser robotUser = getRobotRoomInfo(String.valueOf(robotId));
            String connecId = roomId + "_" + robotId;
            if (robotUser.getCurrentRoomId() == 0) {
                robotUser.setCurrentRoomId(Integer.parseInt(roomId));
                robotUser.setClient(client);
                robotUser.setConnecId(connecId);
            }
            //先不放入映射 等确认加入成功后再放入
            //robotRoomMapping.put(robotUser.getConnecId(), robotUser);
            robotRoomMapping.remove(robotUser.getRobotId());
            Thread.sleep(2000);
            params.putString("session", "{user}:" + robotId + "," + robotSession);

            //发送加入房间请求到game_mj_cs
            client.send(Config.JOIN_ROOM_CS, params, response -> {
                //成功响应后才建立映射关系
                robotRoomMapping.put(robotUser.getConnecId(), robotUser);
                robotConnectionManager.reconnectToGameServer(response, robotUser, client);
            });
            System.err.println("已进入房间成功: " + robotUser.getConnecId());
            Thread.sleep(1000);
            if (client.isConnected()) {
                client.send(Config.GAME_READY_CS, params, response -> {
                    System.out.println("1003:" + response);
                });
                jedis2.hset("gallrobot", String.valueOf(robotUser.getRobotId()), "1");

                robotUser.setStatus(ROBOTEventType.ROBOT_INTOROOM_READY);
                robotConnectionManager.setSessionAndToken("{user}:" + robotId, robotSession, robotUser.getConnecId());
            }
            //添加超时检查机制
            CompletableFuture.runAsync(() -> {
                try {
                    Thread.sleep(15000);
                    //15秒后还没有建立映射关系 加入可能失败
                    if (robotRoomMapping.get(robotUser.getConnecId()) == null) {
                        System.err.println("机器人{"+robotId+"}加入房间{"+roomId+"}超时，清理临时状态");
                        //清理可能残留的状态
                        robotConnectionManager.disconnectFromGameServer(connecId);
                    }
                } catch (InterruptedException e) {
                    log.error("加入房间超时异常");
                }
            });
            robotUser.setIntoRoomTime(robotConnectionManager.getTime());
            System.err.println("已进入房间准备成功: " + robotUser.getConnecId());
        } catch (Exception e) {
           // throw new RuntimeException(e);
        } finally {
            jedis0.close();
            jedis2.close();
        }
    }

    /**
     * 根据机器人ID获取其所在的房间信息
     */
    public static RobotUser getRobotRoomInfo(String robotId) {
        RobotUser robotUser = robotRoomMapping.get(robotId);
        if (robotUser ==null) {
            RobotUser robotUserCopy = new RobotUser();
            robotUserCopy.setRobotId(robotId);
            robotUserCopy.setPassword(Config.DEFAULT_PASSWORD);
            robotUserCopy.setGameHost(Config.GAME_SERVER_HOST);
            robotUserCopy.setGamePort(Config.GAME_SERVER_PORT);
            robotUserCopy.setRobotGroupid(Config.DEFAULT_GROUP_ID);
            robotUserCopy.setRobotPid(Config.DEFAULT_PID);
            return robotUserCopy;
        }
        return robotRoomMapping.get(robotId);
    }

    /**
     * 根据房间ID获取所有对应的RobotUser
     */
    public List<RobotUser> getRobotUsersByRoomId(int roomId) {
        String prefix = roomId + "_";
        List<RobotUser> result = new ArrayList<>();

        for (Map.Entry<String, RobotUser> entry : robotRoomMapping.entrySet()) {
            if (entry.getKey().startsWith(prefix)) {
                result.add(entry.getValue());
            }
        }
        return result;
    }

    /**
     * 根据机器人ID删除其所在的房间信息
     */
    public static void removeRobotRoomInfo(String robotId) {
        robotRoomMapping.remove(robotId);
    }

    /**
     * 根据机器人ID和连接ID获取红中麻将游戏服务器连接
     * 基于robotId和connectionId的组合复用连接
     */
    public static TaurusClient getCsMjGameServerConnection(String connecId) {
        TaurusClient taurusClient = robotConnectionManager.getGameClient(connecId);
        System.out.println("根据机器人ID和连接ID获取红中麻将游戏服务器连接 client: = "+taurusClient);
        if (taurusClient != null) {
            log.debug("成功获取游戏服务器连接，connecId: {}", connecId);
            return taurusClient;
        }
        taurusClient = robotConnectionManager.connectToGameServer(connecId);
        return taurusClient;
    }

    /**
     * 检查Redis中房间是否包含指定机器人
     * @param roomId 房间ID
     * @param robotId 机器人ID
     * @return 是否包含该机器人
     */
    private boolean checkRobotInRoomRedis(String roomId, String robotId) {
        Jedis jedis = Redis.use().getJedis();
        try {
            //查询该房间的玩家信息
            String playersStr = jedis.hget("room:" + roomId, "players");
            if (playersStr == null || playersStr.equals("[]")) {
                return false;
            }

            String players = playersStr.substring(1, playersStr.length() - 1);
            String[] playerIds = players.split(",");

            //检查是否包含该机器人
            int targetRobotId = Integer.parseInt(robotId);
            for (String playerIdStr : playerIds) {
                int playerId = Integer.parseInt(playerIdStr.trim());
                if (playerId == targetRobotId) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            log.error("检查Redis房间玩家信息时发生错误，roomId: {}, robotId: {}", roomId, robotId, e);
            return false;
        } finally {
            jedis.close();
        }
    }

}