package com.ssyf.task.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.ssyf.module.robot.domain.entity.RConfigRelation;
import com.ssyf.module.robot.domain.entity.RRobotAccount;
import com.ssyf.module.robot.domain.entity.RRunningConfig;
import com.ssyf.module.robot.domain.query.RRunningConfigQuery;
import com.ssyf.module.robot.helper.ConfigTimeHelper;
import com.ssyf.module.robot.service.RConfigRelationService;
import com.ssyf.module.robot.service.RRobotAccountService;
import com.ssyf.module.robot.service.RRunningConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;

/**
 * 机器人资源管理器 (智能调度版)
 * 负责数据的缓存、去重、状态管理和冷却控制
 */
@Slf4j
@Component
public class RobotResourceManager {

    @Lazy
    @Autowired private RConfigRelationService configRelationService;
    @Lazy
    @Autowired private RRobotAccountService robotAccountService;
    @Lazy
    @Autowired private RRunningConfigService runningConfigService;
    @Autowired @Lazy private LiveRoomMonitorService monitorService; // 新增注入
    @Autowired @Lazy private RobotManualControlService manualControlService; // 新增手动控制服务

    // === 数据缓存 (DB镜像) ===
    private final Map<String, RRobotAccount> accountMap = new ConcurrentHashMap<>();
    private final Map<String, RConfigRelation> relationMap = new ConcurrentHashMap<>();
    private final Map<String, RRunningConfig> configMap = new ConcurrentHashMap<>();

    // === 状态管理 ===
    // 待执行队列
    private final Queue<String> pendingRobotUuids = new ConcurrentLinkedQueue<>();

    // 正在执行中的机器人UUID集合 (防并发：防止同一机器人同时被多个线程执行)
    private final Set<String> executingRobots = ConcurrentHashMap.newKeySet();

    // 机器人上次任务结束时间戳 (用于正常冷却控制，防止死循环)
    private final Map<String, Long> lastFinishTimeMap = new ConcurrentHashMap<>();

    // 熔断/异常冷却记录表：Key=RobotUuid, Value=冷却截止时间戳
    private final Map<String, Long> failureCoolDownMap = new ConcurrentHashMap<>();

    // === 常量 ===
    private static final long DEFAULT_COOLDOWN_MS = 1 * 60 * 1000L; // 正常任务冷却 5分钟* 60
    private static final long FAILURE_COOLDOWN_MS = 5 * 60 * 1000L; // 失败熔断冷却 10分钟
    private static final long DB_SYNC_INTERVAL_MS = 60 * 1000L; // 数据库同步间隔 1分钟

    private long lastDbSyncTime = 0;

    /**
     * 尝试填充执行队列 (高频调用)
     * 该方法只操作内存数据，筛选出符合条件的机器人入队。
     * @return 实际添加到队列的数量
     */
    public synchronized int tryRefillQueue() {
        long now = System.currentTimeMillis();

        // 1. 定期同步数据库 (每分钟一次，避免高频查库)
        if (now - lastDbSyncTime > DB_SYNC_INTERVAL_MS) {
            syncFromDatabase();
        }

        if (accountMap.isEmpty()) return 0;
        List<String> candidates = new ArrayList<>();

        for (String uuid : accountMap.keySet()) {
            // A. 正在执行登录/进房任务 -> 跳过
            if (executingRobots.contains(uuid)) continue;

            // B. 已经在等待队列 -> 跳过
            if (pendingRobotUuids.contains(uuid)) continue;

            // C. 【新增核心逻辑】 正在直播间监控中 (驻留互动) -> 跳过
            // 此时机器人正在 LiveRoomMonitorService 的 map 里，不要打扰它
            if (monitorService.isMonitoring(uuid)) continue;

            // D. 【新增核心逻辑】 被手动控制 -> 跳过
            // 机器人被运营手动接管时，自动化服务不应干预
            if (manualControlService.isManuallyControlled(uuid)) continue;

            // E. 熔断检查
            if (failureCoolDownMap.containsKey(uuid)) { /* ... */ }

            // F. 冷却检查 (只有当 Monitor 把它踢出来并调用 markFinished 后，这里才会通过)
            if (!isCooldownReady(uuid, now)) continue;

            // G. 配置有效性
            if (!isValid(uuid)) continue;

            candidates.add(uuid);
        }

        if (CollUtil.isNotEmpty(candidates)) {
            Collections.shuffle(candidates);
            pendingRobotUuids.addAll(candidates);
            log.debug("队列填充完成，新增候选机器人: {}", candidates.size());
            return candidates.size();
        }

        return 0;
    }

    /**
     * 从数据库同步数据到内存缓存 (低频调用)
     */
    private synchronized void syncFromDatabase() {
        try {
            List<RConfigRelation> relations = configRelationService.getAvailableConfigs();
            if (CollUtil.isEmpty(relations)) {
                // 数据库没数据时，清空现有缓存
                accountMap.clear();
                relationMap.clear();
                configMap.clear();
                return;
            }

            Set<String> robotUuids = relations.stream()
                    .map(RConfigRelation::getRobotUuid)
                    .filter(StrUtil::isNotBlank)
                    .collect(Collectors.toSet());
            Set<String> groupUuids = relations.stream()
                    .map(RConfigRelation::getRobotGroupUuid)
                    .filter(StrUtil::isNotBlank)
                    .collect(Collectors.toSet());
            Set<String> configUuids = relations.stream()
                    .map(RConfigRelation::getConfigUuid)
                    .filter(StrUtil::isNotBlank)
                    .collect(Collectors.toSet());

            List<RRobotAccount> accounts = robotAccountService.getEnabledRobotAccountsBy(robotUuids, groupUuids);
            List<RRunningConfig> configs = runningConfigService.getList(
                    new RRunningConfigQuery()
                            .setUuids(new ArrayList<>(configUuids))
                            .setStatus(1)
            );

            // 构建新的缓存数据
            Map<String, RRunningConfig> newConfigMap = configs.stream()
                    .collect(Collectors.toMap(RRunningConfig::getUuid, c -> c));

            Map<String, RConfigRelation> groupToRelation = new HashMap<>();
            Map<String, RConfigRelation> newRelationMap = new HashMap<>();

            relations.forEach(r -> {
                if (!newConfigMap.containsKey(r.getConfigUuid())) {
                    return;
                }
                if (StrUtil.isNotBlank(r.getRobotGroupUuid())) {
                    groupToRelation.put(r.getRobotGroupUuid(), r);
                }
                if (StrUtil.isNotBlank(r.getRobotUuid())) {
                    newRelationMap.put(r.getRobotUuid(), r);
                }
            });

            // 构建新的账号映射
            Map<String, RRobotAccount> newAccountMap = new HashMap<>();
            for (RRobotAccount acc : accounts) {
                String uuid = acc.getUuid();

                if (newRelationMap.containsKey(uuid)) {
                    newAccountMap.put(uuid, acc);
                    continue;
                }

                if (StrUtil.isNotBlank(acc.getGroupId()) && groupToRelation.containsKey(acc.getGroupId())) {
                    newAccountMap.put(uuid, acc);
                    newRelationMap.put(uuid, groupToRelation.get(acc.getGroupId()));
                }
            }

            // 批量替换旧数据，确保数据一致性
            configMap.clear();
            configMap.putAll(newConfigMap);

            relationMap.clear();
            relationMap.putAll(newRelationMap);

            accountMap.clear();
            accountMap.putAll(newAccountMap);

            lastDbSyncTime = System.currentTimeMillis();
            log.debug("数据库资源同步完成，当前内存缓存机器人: {}", accountMap.size());

        } catch (Exception e) {
            log.error("同步数据库资源异常", e);
        }
    }

    private boolean isCooldownReady(String uuid, long now) {
        Long lastFinish = lastFinishTimeMap.get(uuid);
        if (lastFinish == null) {
            return true; // 从未运行过，无需冷却
        }
        // 检查配置的间隔时间，如果没配置则使用默认5分钟
        // 这里为了简化，直接使用常量，如果需要支持动态间隔，可从 relationMap 获取 Config
        return (now - lastFinish) > DEFAULT_COOLDOWN_MS;
    }

    // === 状态标记方法 ===

    /**
     * 标记机器人开始执行
     */
    public void markRunning(String uuid) {
        executingRobots.add(uuid);
    }

    /**
     * 标记机器人执行结束 (无论成功失败)
     * 更新最后执行时间，触发冷却
     */
    public void markFinished(String uuid) {
        executingRobots.remove(uuid);
        lastFinishTimeMap.put(uuid, System.currentTimeMillis());
    }

    /**
     * 标记执行失败（触发长冷却熔断）
     */
    public void reportFailure(String robotUuid) {
        failureCoolDownMap.put(robotUuid, System.currentTimeMillis() + FAILURE_COOLDOWN_MS);
        log.warn("机器人 {} 异常/失败，进入 10 分钟熔断冷却", robotUuid);
    }

    public void reportSuccess(String robotUuid) {
        failureCoolDownMap.remove(robotUuid);
    }

    // === Getters & Cleaners ===

    public RRobotAccount getAccount(String uuid) { return accountMap.get(uuid); }
    public RConfigRelation getRelation(String robotUuid) { return relationMap.get(robotUuid); }
    public RRunningConfig getConfig(String configUuid) { return configMap.get(configUuid); }

    public String pollPendingRobot() { return pendingRobotUuids.poll(); }
    public boolean isQueueEmpty() { return pendingRobotUuids.isEmpty(); }

    public synchronized void clear() {
        accountMap.clear();
        relationMap.clear();
        configMap.clear();
        pendingRobotUuids.clear();
        executingRobots.clear();
        lastFinishTimeMap.clear();
        failureCoolDownMap.clear();
        lastDbSyncTime = 0;
        monitorService.clear(); // 级联清理
    }

    private boolean isValid(String robotUuid) {
        RConfigRelation rel = relationMap.get(robotUuid);
        if (rel == null) return false;
        RRunningConfig conf = configMap.get(rel.getConfigUuid());
        return conf != null && ConfigTimeHelper.isInValidTime(rel);
    }

    /**
     * 仅移除执行标记，不更新结束时间 (用于移交监控服务时)
     */
    public void removeFromExecuting(String uuid) {
        executingRobots.remove(uuid);
    }

    public Set<String> getExecutingRobots() {
        return executingRobots;
    }
}