package com.group.robot;

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

import com.group.robot.connect.RobotDisconnect;
import com.group.robot.handler.*;
import com.group.robot.info.RobotInfo;
import com.group.robot.matcher.RoomWanfaMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import com.taurus.core.plugin.redis.Redis;
import com.taurus.core.plugin.database.DataBase;
import com.taurus.core.entity.ITObject;
import com.group.robot.matcher.majiang.CSMJRoomMatcher;
import com.group.robot.matcher.majiang.HZMJRoomMatcher;
import com.group.robot.matcher.poker.PokerRoomMatcher;
import com.group.robot.matcher.majiang.ZZMJRoomMatcher;
import com.group.robot.matcher.GameRoomMatcherInterface;
import taurus.client.business.AccountBusiness;

/**
 * 机器人管理器 - 管理游戏机器人、游戏房间、监听
 */
public class RobotManager {
    private static final Logger log = LoggerFactory.getLogger(RobotManager.class);

    //静态实例
    private static RobotManager robotManager;

    //机器人处理器映射
    private final Map<Integer, RobotManagerInterface> gameHandlers = new ConcurrentHashMap<>();

    //已连接的机器人
    private final Map<Integer, RobotInfo> connectedRobots = new ConcurrentHashMap<>();

    //游戏特定的房间匹配器
    private final Map<Integer, GameRoomMatcherInterface> gameRoomMatchers = new ConcurrentHashMap<>();

    //使用数量计数器 跟踪每种玩法的机器人使用数量
    private final Map<Integer, Integer> count = new ConcurrentHashMap<>();
    
    //玩法对应的机器人轮询索引
    private final Map<Integer, Integer> wanfaRobotIndex = new ConcurrentHashMap<>();

    //玩法房间轮询器
    private final Map<String, RoomWanfaMatcher> wanfaRoomPollers = new ConcurrentHashMap<>();

    //定时任务调度器
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

    //机器人断开连接处理
    private final RobotDisconnect robotDisconnect;
    
    //跟踪已经恢复leftover_robot的机器人
    private final Set<Integer> leftoverRobotRecovered = ConcurrentHashMap.newKeySet();
    
    //房间级别的锁，用于细粒度的同步控制
    private final Map<String, Object> roomLocks = new ConcurrentHashMap<>();


    public RobotManager() {
        this.robotDisconnect = new RobotDisconnect(this);
        robotManager = this;

        //1、启动 ==》2、登录，3、是否快捷登录 4、分配做什么工作（a:长麻，b:红中，c:跑得快）5、干活，6、销毁回收

        //初始化游戏处理器
        initializeGameHandlers();
        //1、设定每个玩法多少机器人
        //2、实际机器人身份

        //初始化游戏房间匹配器
        initializeGameRoomMatchers();

        //定时任务
        startCleanupTask();
    }

    /**
     * 初始化游戏处理器
     */
    private void initializeGameHandlers() {
        //添加麻将机器人处理器 - 按具体玩法区分处理
        addGameHandler(10, new CSMJRobotHandler()); //长沙麻将
        addGameHandler(22, new HZMJRobotHandler()); //红中麻将
        addGameHandler(108, new ZZMJRobotHandler()); //转转麻将

        //添加扑克机器人处理器
        addGameHandler(66, new PokerRobotHandler()); //跑得快

        log.info("已初始化 {} 个游戏处理器", gameHandlers.size());
    }

    /**
     * 初始化游戏房间匹配器
     */
    private void initializeGameRoomMatchers() {
        //长沙麻将房间匹配器
        CSMJRoomMatcher csMjMatcher = new CSMJRoomMatcher(this);
        gameRoomMatchers.put(10, csMjMatcher);

        //红中麻将房间匹配器
        HZMJRoomMatcher hzMjMatcher = new HZMJRoomMatcher(this);
        gameRoomMatchers.put(22, hzMjMatcher);

        //转转麻将房间匹配器
        ZZMJRoomMatcher zzMjMatcher = new ZZMJRoomMatcher(this);
        gameRoomMatchers.put(108, zzMjMatcher);

        //扑克房间匹配器
        PokerRoomMatcher pokerMatcher = new PokerRoomMatcher(this);
        for (Integer gameId : pokerMatcher.getSupportedWanfaIds()) {
            gameRoomMatchers.put(gameId, pokerMatcher);
        }
        log.info("已初始化 {} 个游戏房间匹配器", gameRoomMatchers.size());
    }

    /**
     * 登录单个机器人
     */
    public void loginRobots(List<RobotInfo> robots, int gameId) {
        try (Jedis jedis0 = Redis.use().getJedis(); Jedis jedis2 = Redis.use("group1_db2").getJedis()){
            for (RobotInfo robot : robots) {
                AccountBusiness accountBusiness = new AccountBusiness();
                //检查Redis中是否存在已有token
                //todo 还要验证登录的token是否是最新的
                Set<String> tokenKeys = jedis0.keys("{user}:" + robot.getRobotId() + "_token");
                ITObject loginResult;

                if (tokenKeys != null && !tokenKeys.isEmpty()) {
                    log.debug("机器人 {} 存在已有token，直接使用", robot.getRobotId());
                    Set<String> tokenSet = jedis0.smembers("{user}:" + robot.getRobotId() + "_token");
                    List<String> tokenList = new ArrayList<>(tokenSet);

                    robot.setSession("{user}:" + robot.getRobotId());
                    if (!tokenList.isEmpty()) {
                        robot.setToken(tokenList.get(0));
                    } else {
                        //如果没有token 则执行正常登录
                        loginResult = accountBusiness.idPasswordLogin(robot.getRobotId(), "123456");
                        robot.setToken(loginResult.getString("token"));
                        robot.setSession(accountBusiness.getSession());
                    }
                } else {
                    log.debug("机器人 {} 执行常规登录", robot.getRobotId());
                    //执行正常登录流程
                    loginResult = accountBusiness.idPasswordLogin(robot.getRobotId(), "123456");
                    robot.setToken(loginResult.getString("token"));
                    robot.setSession(accountBusiness.getSession());
                }
                robot.setOnline(true);
                robot.setWanfaId(gameId);
                robot.setGroupId(-1);
                robot.setLastActiveTime(System.currentTimeMillis());

                HashMap<String, String> robotMap = new HashMap<>();
                robotMap.put("acc", robot.getAccount());
                robotMap.put("nick", robot.getNickName());
                robotMap.put("portrait", robot.getPortrait());
                robotMap.put("password", robot.getPassword());
                jedis2.hmset("{robot}:" + robot.getRobotId(), robotMap);

                Map<String, String> gRobotMap = new HashMap<>();
                gRobotMap.put("start", "0");
                gRobotMap.put("pid", String.valueOf(gameId));
                jedis2.hmset("{grobot}:" + robot.getRobotId(), gRobotMap);

                //更新数据库状态为已使用
                String sql = String.format("UPDATE `account` SET start = %d WHERE id = %d", 1, robot.getRobotId());
                DataBase.use().executeUpdate(sql);
                log.info("机器人{}登录成功，分配到玩法{}", robot.getRobotId(), gameId);

                //连接对应游戏服务器
                RobotManagerInterface handler = getGameHandler(gameId);
                handler.connectRobot(robot);
                //将登录后的机器人添加到已连接列表中 等待连接服务器
                connectedRobots.put(robot.getRobotId(), robot);
            }
        } catch (Exception e) {
            log.error("机器人登录时发生错误", e);
        }
    }

    /**
     * 添加游戏处理器
     */
    public void addGameHandler(int gameId, RobotManagerInterface handler) {
        gameHandlers.put(gameId, handler);
        log.info("添加游戏处理器: gameId={}, handler={}", gameId, handler.getClass().getSimpleName());
    }

    /**
     * 获取游戏处理器
     */
    public RobotManagerInterface getGameHandler(int gameId) {
        return gameHandlers.get(gameId);
    }

    /**
     * 定时任务
     */
    private void startCleanupTask() {
        //每15秒检查一次玩法配置
        scheduler.scheduleAtFixedRate(this::manageWanfaPollers, 15, 15, TimeUnit.SECONDS);
    }

    /**
     * 管理玩法轮询器
     */
    private void manageWanfaPollers() {
        try (Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
            Set<String> playKeys = jedis11.keys("g{*}:play:*");
            
            for (String playKey : playKeys) {
                try {
                    String[] parts = playKey.split(":");
                    if (parts.length >= 3) {
                        String groupStr = parts[0];
                        int groupId = Integer.parseInt(groupStr.substring(2, groupStr.length() - 1));
                        int wanfaId = Integer.parseInt(parts[parts.length - 1]);

                        //检查是否配置了机器人
                        int shangxianRobot = Integer.parseInt(jedis11.hget(playKey, "shangxian_robot"));
                        int leftoverRobot = Integer.parseInt(jedis11.hget(playKey, "leftover_robot"));

                        //配置有机器人的玩法 开始轮询
                        if (shangxianRobot != 0 && leftoverRobot > 0) {
                            RoomWanfaMatcher poller = getWanfaRoomPoller(groupId, wanfaId);
                            if (!poller.isRunning()) {
                                poller.startPolling();
                                log.info("为群组 {} 玩法ID {} 启动房间轮询器", groupId, wanfaId);
                            }
                        } else {
                            //没有配置机器人的玩法 停止轮询
                            String key = groupId + ":" + wanfaId;
                            RoomWanfaMatcher poller = wanfaRoomPollers.get(key);
                            if (poller != null) {
                                poller.stopPolling();
                                log.info("为群组 {} 玩法ID {} 停止房间轮询器", groupId, wanfaId);
                            }
                        }
                    }
                } catch (NumberFormatException e) {
                    log.debug("无法解析玩法ID: {}", playKey);
                }
            }
        } catch (Exception e) {
            log.error("管理玩法轮询器时发生错误", e);
        }
    }
    

    
    /**
     * 断开多余的机器人连接
     */
    public void disconnectExcessRobots(int wanfaId) {
        List<RobotInfo> allWanfaRobots = new ArrayList<>();
        for (RobotInfo robot : connectedRobots.values()) {
            if (robot.getWanfaId() == wanfaId) {
                allWanfaRobots.add(robot);
            }
        }
        
        //断开该玩法下未使用的机器人
        int disconnectedCount = 0;
        for (RobotInfo robot : allWanfaRobots) {
            synchronized(robot) {
                if (!robot.isUsing() && robot.isConnected()) {
                    RobotManagerInterface handler = getGameHandler(robot.getWanfaId());
                    if (handler != null) {
                        handler.disconnectRobot(robot);
                        log.debug("断开未使用机器人 {} TCP连接，玩法ID: {}", robot.getRobotId(), wanfaId);
                    }
                    disconnectedCount++;
                }
            }
        }

        if (disconnectedCount > 0) {
            log.debug("玩法 {} 成功断开 {} 个未使用机器人的TCP连接", wanfaId, disconnectedCount);
        }
    }
    
    /**
     * 连接所需的机器人
     */
    public void connectRequiredRobots(int wanfaId, int requiredCount) {
        List<RobotInfo> allWanfaRobots = new ArrayList<>();
        for (RobotInfo robot : connectedRobots.values()) {
            if (robot.getWanfaId() == wanfaId) {
                allWanfaRobots.add(robot);
            }
        }
        
        //空闲机器人
        int availableCount = 0;
        for (RobotInfo robot : allWanfaRobots) {
            if (robot.isConnected() && !robot.isUsing()) {
                availableCount++;
            }
        }
        
        //可用机器人数量少于需求 连接更多机器人
        if (availableCount < requiredCount) {
            int needToConnect = requiredCount - availableCount;
            int connectedCount = 0;

            for (RobotInfo robot : allWanfaRobots) {
                if (connectedCount >= needToConnect) {
                    break;
                }

                if (!robot.isConnected() && !robot.isUsing()) {
                    RobotManagerInterface handler = getGameHandler(robot.getWanfaId());
                    if (handler != null) {
                        if (shouldConnectRobot(robot)) {
                            synchronized(robot) {
                                if (!robot.isConnected() && !robot.isUsing()) {
                                    handler.connectRobot(robot);
                                    log.debug("连接玩法 {} 的空闲机器人: {}", wanfaId, robot.getRobotId());
                                    connectedCount++;
                                }
                            }
                        } else {
                            log.debug("玩法 {} 当前不允许连接机器人: {}", wanfaId, robot.getRobotId());
                        }
                    }
                }
            }

            if (connectedCount > 0) {
                log.debug("玩法 {} 新连接了 {} 个机器人以满足需求", wanfaId, connectedCount);
            }
        }
    }

    /**
     * 获取玩法房间轮询器
     */
    public RoomWanfaMatcher getWanfaRoomPoller(int groupId, int wanfaId) {
        String key = groupId + ":" + wanfaId;
        return wanfaRoomPollers.computeIfAbsent(key, k -> {
            RoomWanfaMatcher poller = new RoomWanfaMatcher(this, groupId, wanfaId);
            log.info("创建群组 {} 玩法ID {} 的房间轮询器", groupId, wanfaId);
            return poller;
        });
    }

    /**
     * 断开机器人连接
     */
    public void disconnectRobot(RobotInfo robot) {
        int robotId = robot.getRobotId();
        int groupId = getGroupIdFromRoomId(robot.getRoomId());
        int gameId = robot.getWanfaId();
        String roomId = robot.getRoomId();

        //断开机器人服务
        safeDisconnectRobot(robotId, groupId, gameId, roomId);
    }

    /**
     * 从房间ID获取群组ID
     */
    private int getGroupIdFromRoomId(String roomId) {
        try (Jedis jedis = Redis.use().getJedis()) {
            String groupIdStr = jedis.hget(roomId, "group");
            if (groupIdStr != null) {
                return Integer.parseInt(groupIdStr);
            }
        } catch (Exception e) {
            log.error("获取房间 {} 的群组ID时发生异常", roomId, e);
        }
        return 0;
    }

    /**
     * 获取已登录的指定玩法的机器人
     */
    public RobotInfo getWanfaLoggedInRobot(int wanfaId) {
        //获取指定玩法的所有可用机器人
        List<RobotInfo> availableRobots = new ArrayList<>();
        for (RobotInfo robot : connectedRobots.values()) {
            if (robot.getWanfaId() == wanfaId && robot.isOnline() && !robot.isUsing() && robot.isConnected()) {
                //检查Redis中机器人的start状态
                if (!isRobotStartStatusOne(robot.getRobotId())) {
                    availableRobots.add(robot);
                }
            }
        }

        if (!availableRobots.isEmpty()) {
            int currentIndex = wanfaRobotIndex.getOrDefault(wanfaId, 0);
            if (currentIndex >= availableRobots.size()) {
                currentIndex = 0;
            }

            RobotInfo selectedRobot = availableRobots.get(currentIndex);

            synchronized (selectedRobot) {
                if (!selectedRobot.isUsing()) {
                    selectedRobot.setLastActiveTime(System.currentTimeMillis());
                    int nextIndex = (currentIndex + 1) % availableRobots.size();
                    wanfaRobotIndex.put(wanfaId, nextIndex);
                    return selectedRobot;
                }
            }
        }
        
        //如果没有连接的可用机器人 检查是否有未连接的机器人并尝试连接
        List<RobotInfo> allWanfaRobots = new ArrayList<>();
        for (RobotInfo robot : connectedRobots.values()) {
            if (robot.getWanfaId() == wanfaId && robot.isOnline()) {
                //检查Redis中机器人的start状态
                if (!isRobotStartStatusOne(robot.getRobotId())) {
                    allWanfaRobots.add(robot);
                }
            }
        }
        
        if (!allWanfaRobots.isEmpty()) {
            int currentIndex = wanfaRobotIndex.getOrDefault(wanfaId, 0);
            if (currentIndex >= allWanfaRobots.size()) {
                currentIndex = 0;
            }
            
            RobotInfo selectedRobot = allWanfaRobots.get(currentIndex);
            
            //机器人未连接 尝试重新连接
            if (!selectedRobot.isConnected()) {
                selectedRobot.setUsing(false);
                RobotManagerInterface handler = getGameHandler(selectedRobot.getWanfaId());
                if (handler != null) {
                    handler.connectRobot(selectedRobot);
                }
            }

            if (!selectedRobot.isUsing()) {
                //使用同步块确保原子操作
                synchronized (selectedRobot) {
                    if (!selectedRobot.isUsing()) {
                        selectedRobot.setLastActiveTime(System.currentTimeMillis());
                        int nextIndex = (currentIndex + 1) % allWanfaRobots.size();
                        wanfaRobotIndex.put(wanfaId, nextIndex);
                        return selectedRobot;
                    }
                }
            }
        }

        return null;
    }

    /**
     * 获取机器人管理器实例
     */
    public static RobotManager getRobotManager() {
        return robotManager;
    }

    /**
     * 减少指定玩法ID的机器人使用计数
     */
    public void decreaseRobotCount(int wanfaId) {
        Integer currentCount = count.get(wanfaId);
        if (currentCount != null && currentCount > 0) {
            count.put(wanfaId, currentCount - 1);
            log.debug("玩法ID {} 的机器人使用计数减少到: {}", wanfaId, count.get(wanfaId));
        }
    }

    /**
     * 获取已连接的机器人
     */
    public RobotInfo getConnectedRobot(int robotId) {
        return connectedRobots.get(robotId);
    }

    /**
     * 标记leftover_robot已恢复 避免重复恢复
     */
    public void markLeftoverRobotRecovered(int robotId) {
        leftoverRobotRecovered.add(robotId);
        log.debug("机器人 {} 的leftover_robot已标记为已恢复", robotId);
    }
    
    /**
     * 检查leftover_robot是否已恢复
     */
    public boolean isLeftoverRobotRecovered(int robotId) {
        return leftoverRobotRecovered.contains(robotId);
    }
    
    /**
     * 从leftover_robot恢复集合中移除
     */
    public void leftoverRobotRemoved(int robotId) {
        leftoverRobotRecovered.remove(robotId);
        log.debug("机器人 {} 从leftover_robot恢复集合中移除", robotId);
    }
    
    /**
     * 安全的断开机器人连接
     */
    public void safeDisconnectRobot(int robotId, int groupId, int gameId, String roomId) {
        if (robotDisconnect != null) {
            robotDisconnect.disconnectRobot(robotId, groupId, gameId, roomId);
        } else {
            RobotInfo robot = connectedRobots.get(robotId);
            if (robot != null) {
                disconnectRobot(robot);
            }
        }
    }
    
    /**
     * 房间处理完成移除指定房间
     */
    public void roomProcessingFinish(String roomId) {
        for (RoomWanfaMatcher matcher : wanfaRoomPollers.values()) {
            matcher.roomProcessingFinish(roomId);
        }
    }

    /**
     * 释放机器人 使其可以被重新使用
     */
    public void releaseRobot(int robotId) {
        RobotInfo robot = connectedRobots.get(robotId);
        if (robot != null) {
            synchronized(robot) {
                robot.setUsing(false);
            }
        }
    }

    /**
     * 根据玩法的leftover_robot数量检查是否连接机器人
     */
    public boolean shouldConnectRobot(RobotInfo robot) {
        if (robot.getGroupId() == -1) {
            return true;
        }
        
        try (Jedis jedis11 = Redis.use("group1_db11").getJedis()) {
            String playKey = "g{" + robot.getGroupId() + "}:play:" + robot.getWanfaId();
            String leftoverRobotStr = jedis11.hget(playKey, "leftover_robot");

            if (leftoverRobotStr != null) {
                int leftoverRobot = Integer.parseInt(leftoverRobotStr);
                return leftoverRobot > 0;
            }

            return false;
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 检查机器人在Redis中的start状态是否为1
     * @param robotId 机器人ID
     * @return true表示start=1，false表示start!=1或其他情况
     */
    private boolean isRobotStartStatusOne(int robotId) {
        try (Jedis jedis2 = Redis.use("group1_db2").getJedis()) {
            String gRobotKey = "{grobot}:" + robotId;
            String startValue = jedis2.hget(gRobotKey, "start");
            
            if (startValue != null) {
                return "1".equals(startValue);
            }
            return false;
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 获取房间级别的锁
     */
    public Object getRoomLock(String roomId) {
        return roomLocks.computeIfAbsent(roomId, k -> new Object());
    }
}