package com.group.robot.matcher;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;

import com.group.robot.RobotManager;
import com.group.robot.handler.RobotConnectionHandler;
import com.group.robot.info.RobotInfo;
import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import com.taurus.core.plugin.database.DataBase;
import com.taurus.core.plugin.redis.Redis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import taurus.client.business.GroupRoomBusiness;

/**
 * 玩法房间轮询器 - 按玩法定期查询房间
 */
public class RoomWanfaMatcher {
    private static final Logger log = LoggerFactory.getLogger(RoomWanfaMatcher.class);
    
    private final RobotManager robotManager;
    private final int groupId;
    private final int wanfaId;
    private final Object lock = new Object();
    private volatile ScheduledExecutorService scheduler;
    private volatile boolean isRunning = false;
    //机器人连接处理器
    private final RobotConnectionHandler robotConnectionHandler;
    
    //记录上一次leftover_robot数量
    private volatile int lastLeftoverRobot = -1;
    
    //机器人加入房间锁
    private final Object joinRoomLock = new Object();
    
    //正在处理的房间
    private final Set<String> processingRooms = ConcurrentHashMap.newKeySet();
    
    //房间ID到机器人ID
    private final Map<String, Integer> roomToRobotMap = new ConcurrentHashMap<>();

    public RoomWanfaMatcher(RobotManager robotManager, int groupId, int wanfaId) {
        this.robotManager = robotManager;
        this.groupId = groupId;
        this.wanfaId = wanfaId;
        this.scheduler = Executors.newSingleThreadScheduledExecutor();
        this.robotConnectionHandler = RobotConnectionHandler.getInstance();
        
        //设置房间创建回调
        this.robotConnectionHandler.setRoomCreatedCallback(this::onRoomCreated);
        
        //初始化轮询时会触发连接管理
        this.lastLeftoverRobot = -1;
    }
    
    /**
     * 启动轮询
     */
    public void startPolling() {
        synchronized(lock) {
            if (isRunning) {
                return;
            }
            
            if (scheduler == null || scheduler.isShutdown()) {
                scheduler = Executors.newSingleThreadScheduledExecutor();
            }
            
            isRunning = true;
            log.info("开始为群组 {} 玩法ID {} 启动房间轮询", groupId, wanfaId);
            
            //10秒轮询一次
            scheduler.scheduleWithFixedDelay(this::pollRooms, 0, 20, TimeUnit.SECONDS);
        }
    }
    
    /**
     * 轮询房间
     */
    private void pollRooms() {
        try {
            if (!isRunning) {
                return;
            }

            try (Jedis jedis0 = Redis.use().getJedis(); Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
                String playKey = "g{" + groupId + "}:play:" + wanfaId;
                String leftoverRobotStr = jedis11.hget(playKey, "leftover_robot");

                int leftoverRobot = Integer.parseInt(leftoverRobotStr);

                //根据leftover_robot数量管理机器人连接状态
                manageRobotConnections(leftoverRobot);

                if (leftoverRobot > 0) {
                    //查询当前群组和玩法的房间
                    Set<String> roomIds = jedis0.keys("room:*");
                    
                    if (roomIds.isEmpty()) {
                        createRobotWanfaRoomTCP(groupId, this.wanfaId);
                        return;
                    }
                    
                    //满人房间
                    int fullRooms = 0;
                    //所有房间
                    int totalRooms = 0;
                    List<String> roomsList = new ArrayList<>();

                    //统计所有当前群组和玩法的2人房间
                    for (String roomId : roomIds) {
                        int currentWanfaId = Integer.parseInt(jedis0.hget(roomId, "gpid"));
                        int currentGroup = Integer.parseInt(jedis0.hget(roomId, "group"));
                        int maxPlayers = Integer.parseInt(jedis0.hget(roomId, "maxPlayers"));

                        //处理当前群组和玩法maxPlayers为2的房间
                        if (maxPlayers == 2 && currentWanfaId == this.wanfaId && currentGroup == this.groupId) {
                            totalRooms++;

                            String playersStr = jedis0.hget(roomId, "players");
                            int currentPlayers = 0;
                            if (!playersStr.equals("[]")) {
                                String playersClean = playersStr.substring(1, playersStr.length() - 1);
                                if (!playersClean.isEmpty()) {
                                    String[] playerIds = playersClean.split(",");
                                    currentPlayers = playerIds.length;
                                }
                            }
                            if (currentPlayers == maxPlayers) {
                                fullRooms++;
                            } else {
                                roomsList.add(roomId);
                            }
                        }
                    }

                    //todo该玩法机器人房间满了 创建新房间
                    /*if (fullRooms == totalRooms && totalRooms > 0) {
                        createRobotWanfaRoomTCP(groupId, this.wanfaId);
                        return;
                    }*/

                    for (String roomId : roomsList) {
                        int status = Integer.parseInt(jedis0.hget(roomId, "status"));

                        //处理未开始的陪打房间
                        if (status == 0) {
                            String playersStr = jedis0.hget(roomId, "players");
                            RobotInfo robot = new RobotInfo();
                            robot.setWanfaId(this.wanfaId);
                            robot.setGroupId(this.groupId);
                            robot.setRoomId(roomId);
                            robot.setRobotId(-1);

                            //房间没人 加入房间
                            if (playersStr.equals("[]")) {
                                Object roomSpecificLock = robotManager.getRoomLock(roomId);
                                synchronized (roomSpecificLock) {
                                    if (!processingRooms.contains(roomId)) {
                                        processingRooms.add(roomId);
                                        robotJoinRoom(robot, true);
                                    }
                                }
                            } else {
                                //房间有人 不是机器人则加入房间
                                Integer robotInRoom = playerIsRobotRedis(playersStr);
                                if (robotInRoom == null) {
                                    Object roomSpecificLock = robotManager.getRoomLock(roomId);
                                    synchronized (roomSpecificLock) {
                                        if (!processingRooms.contains(roomId)) {
                                            processingRooms.add(roomId);
                                            robotJoinRoom(robot, false);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Throwable t) {
            log.error("轮询群组 {} 玩法ID {} 的房间时发生严重错误", groupId, wanfaId, t);
        }
    }

    /**
     * 机器人加入房间
     * @param isRobot 是否是机器人创建房间
     * @param robot 机器人实例
     * */
    private void robotJoinRoom(RobotInfo robot, boolean isRobot) {
        String roomId = robot != null ? robot.getRoomId() : null;
        Object roomSpecificLock = robotManager.getRoomLock(roomId);
        synchronized (roomSpecificLock) {
            RobotInfo robotInfo = robot;
            int groupId = robot.getGroupId();
            try {
                if (robotInfo.getRobotId() == -1) {
                    robotInfo = robotManager.getWanfaLoggedInRobot(wanfaId);
                    System.out.println("robotJoinRoom机器人加入房间 机器人状态 :" + robot.isConnecting());
                    if (robotInfo == null) {
                        return;
                    }
                    robotInfo.setGroupId(groupId);
                    robotInfo.setRoomId(roomId);

                    //验证机器人连接状态
                    if (robotInfo.isUsing()) {
                        robotManager.releaseRobot(robotInfo.getRobotId());
                        return;
                    }
                }
                CompletableFuture<Boolean> future = new CompletableFuture<>();
                RobotInfo finalRobotInfo = robotInfo;
                //加入房间
                CompletableFuture<Boolean> joinFuture = robotConnectionHandler.sendReadyMessage(finalRobotInfo, future);

                joinFuture.thenCompose(joinSuccess -> {
                    if (joinSuccess) {
                        System.out.println("机器人"+robot.getRobotId()+" 加入了房间 机器人状态 :" + robot.isConnecting());
                        //准备阶段
                        return robotConnectionHandler.sendReadyMessageAsyncCompletable(finalRobotInfo);
                    } else {
                        System.out.println("robotJoinRoomInternal机器人加入了房间 失败 :" + robot.isConnecting());
                        //加入失败 释放机器人
                        robotManager.releaseRobot(finalRobotInfo.getRobotId());
                        return CompletableFuture.completedFuture(false);
                    }
                }).thenAccept(readySuccess -> {
                    if (readySuccess) {
                        System.out.println("robotJoinRoomInternal机器人准备 房间 机器人状态 :" + robot.isConnecting());
                        roomToRobotMap.put(roomId, finalRobotInfo.getRobotId());
                        updateRobotStatusRedis(finalRobotInfo);
                        if (isRobot) {
                            //6秒没有玩家加入 则退出房间
                            //robotConnectionHandler.readyTimeRobotExit(finalRobotInfo, robotManager.getRoomLock(roomId));
                        }
                    } else {
                        System.out.println("robotJoinRoomInternal机器人准备 房间 失败 :" + robot.isConnecting());
                        //准备失败时释放机器人
                        robotManager.releaseRobot(finalRobotInfo.getRobotId());
                    }
                }).exceptionally(throwable -> {
                    log.error("机器人加入房间流程异常", throwable);
                    robotManager.releaseRobot(finalRobotInfo.getRobotId());
                    return null;
                });

            } catch (Exception e) {
                if (robotInfo != null) {
                    //释放机器人
                    robotManager.releaseRobot(robotInfo.getRobotId());
                }
            } finally {
                //移除房间
                processingRooms.remove(roomId);
            }
        }
    }

    /**
     * 通过TCP服务为指定群组和玩法创建房间
     */
    private void createRobotWanfaRoomTCP(int groupId, int wanfaId) {
        synchronized (joinRoomLock) {
            try {
                RobotInfo robot = robotManager.getWanfaLoggedInRobot(wanfaId);
                //使用机器人连接处理器发送创建房间请求
                robotConnectionHandler.sendCreateRoom(robot, groupId, wanfaId);
            } catch (Exception e) {
                log.error("创建玩法ID {} 的房间时发生错误", wanfaId, e);
            }
        }
    }

    /**
     * 房间创建成功后的回调方法
     */
    private void onRoomCreated(RobotInfo robot) {
        try {
            robotJoinRoom(robot, true);
        } catch (Exception e) {
            if (robot != null) {
                robotConnectionHandler.disconnectRobot(robot.getRobotId());
            }
        }
    }

    /**
     * 检查玩家列表中是否包含机器人
     */
    public static Integer playerIsRobotRedis(String playersStr) {
        String playersClean = playersStr.substring(1, playersStr.length() - 1);
        String[] playerIds = playersClean.split(",");

        for (String playerIdStr : playerIds) {
            try {
                int playerId = Integer.parseInt(playerIdStr.trim());
                //检查是否为机器人账户（jiqiren=9998）
                String checkSql = String.format("SELECT jiqiren FROM `account` WHERE id = %d", playerId);
                ITArray checkArray = DataBase.use().executeQueryByTArray(checkSql);

                if (checkArray.size() > 0) {
                    ITObject checkObj = checkArray.getTObject(0);
                    int jiqiren = checkObj.getInt("jiqiren");
                    //是机器人
                    if (jiqiren == 9998) {
                        return playerId;
                    }
                }
            } catch (Exception e) {
                log.warn("检查玩家是否为机器人时发生错误: {}", playerIdStr, e);
            }
        }
        return null;
    }

    public boolean isRunning() {
        return isRunning;
    }
    
    /**
     * 根据leftover_robot数量管理机器人连接状态
     */
    private void manageRobotConnections(int currentLeftoverRobot) {
        if (lastLeftoverRobot != currentLeftoverRobot) {
            if (currentLeftoverRobot <= 0 && lastLeftoverRobot > 0) {
                //leftover_robot变为0 断开该玩法下未使用的机器人连接
                robotManager.disconnectExcessRobots(wanfaId);
                lastLeftoverRobot = 0;
            } else if (currentLeftoverRobot > 0 && lastLeftoverRobot <= 0) {
                //leftover_robot变为正数 检查是否有可用的空闲机器人 没有则连接新的
                robotManager.connectRequiredRobots(wanfaId, currentLeftoverRobot);
                lastLeftoverRobot = currentLeftoverRobot;
            }
        }
    }

    /**
     * 停止轮询
     */
    public void stopPolling() {
        synchronized(lock) {
            isRunning = false;
            if (scheduler != null && !scheduler.isShutdown()) {
                scheduler.shutdown();
                try {
                    if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                        scheduler.shutdownNow();
                    }
                } catch (InterruptedException e) {
                    scheduler.shutdownNow();
                    Thread.currentThread().interrupt();
                }
            }
        }
        log.info("玩法ID {} 的房间轮询已停止", wanfaId);
    }
    
    /**
     * 更新机器人状态 减少leftover_robot计数并更新机器人start状态
     */
    private void updateRobotStatusRedis(RobotInfo robot) {
        try (Jedis jedis11 = Redis.use("group1_db11").getJedis(); Jedis jedis2 = Redis.use("group1_db2").getJedis()) {
        
            String playKey = "g{" + robot.getGroupId() + "}:play:" + robot.getWanfaId();
            jedis11.hincrBy(playKey, "leftover_robot", -1);
            
            String gRobotKey = "{grobot}:" + robot.getRobotId();
            jedis2.hset(gRobotKey, "start", "1");
            
        } catch (Exception e) {
            log.error("更新机器人状态时异常，机器人={}, 群组={}, 玩法={}", robot.getRobotId(), robot.getGroupId(), robot.getWanfaId(), e);
        }
    }
    
    /**
     * 通知房间处理完成 从processingRooms集合中移除指定房间
     */
    public void roomProcessingFinish(String roomId) {
        processingRooms.remove(roomId);
        Integer robotId = roomToRobotMap.remove(roomId);
        if (robotId != null) {
            robotManager.releaseRobot(robotId);
        }
    }
}