package com.ssyf.task.service;

import cn.hutool.core.thread.ThreadUtil;
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.helper.ConfigTimeHelper;
import com.ssyf.task.models.RobotTaskContext;
import com.ssyf.third.bmiss.model.ApiResponse;
import com.ssyf.third.bmiss.model.LiveRoom;
import com.ssyf.third.bmiss.model.LoginResponse;
import com.ssyf.third.bmiss.services.BusinessService;
import com.ssyf.third.bmiss.services.LiveService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 机器人自动化任务编排服务 (V5.0 Anti-Loop Optimized)
 * 修正：引入冷却机制和状态检查，防止队列为空时无限循环重载
 */
@Slf4j
@Service
public class RobotAutomationService {

    @Lazy
    @Autowired private RobotResourceManager resourceManager;
    @Lazy
    @Autowired private LiveRoomActionService actionService;
    @Lazy
    @Autowired private RobotRecordService recordService;
    @Lazy
    @Autowired private RobotSessionManager sessionManager;
    @Autowired private LiveService liveService;
    @Autowired private BusinessService businessService;
    @Autowired private RedissonClient redissonClient;

    private ThreadPoolExecutor executor;
    private final AtomicBoolean isRunning = new AtomicBoolean(false);
    private volatile List<LiveRoom> cachedLiveRooms = Collections.emptyList();
    private long lastRoomRefreshTime = 0;

    @PostConstruct
    public void init() {
        int cpu = Runtime.getRuntime().availableProcessors();
        executor = new ThreadPoolExecutor(
                cpu * 2, cpu * 8,
                60L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(500),
                ThreadUtil.createThreadFactory("robot-auto-"),
                new ThreadPoolExecutor.DiscardPolicy()
        );
        isRunning.set(true);
        log.debug("机器人自动化引擎已启动");
    }

    /**
     * 核心调度心跳 (每5秒触发一次)
     * 优化：如果机器人都在冷却期，Refill将返回0，此处会直接结束，不会空转死循环
     */
    @Scheduled(fixedDelay = 5000)
    public void taskTick() {
        if (!isRunning.get()){return;}

        try {
            // 1. 刷新直播间列表
            refreshLiveRooms();
            if (cachedLiveRooms.isEmpty()){
                log.debug("暂无在线直播间，跳过本轮调度");
                return;
            }

            // 2. 如果队列空，尝试从缓存中 Refill (带冷却检查)
            if (resourceManager.isQueueEmpty()) {
                int added = resourceManager.tryRefillQueue();
                if (added == 0) {
                    // 关键点：如果 Refill 返回 0，说明所有机器人都在 运行中、熔断中 或 冷却中
                    // 直接 return，等待下一个 tick (5秒后)，防止 CPU 死循环
                    return;
                }
            }

            // 3. 填充线程池
            int availableSlots = executor.getMaximumPoolSize() - executor.getActiveCount();
            if (availableSlots <= 0){return;}

            // 为了防止一次性塞满导致其他任务饥饿，限制单次提交数量
            int tasksToSubmit = Math.min(availableSlots, 50);

            for (int i = 0; i < tasksToSubmit; i++) {
                if (resourceManager.isQueueEmpty()) {break;}

                String robotUuid = resourceManager.pollPendingRobot();
                if (robotUuid != null) {
                    // 【关键】提交前标记为 Running，防止下一次 Refill 再次把该机器人加进来
                    resourceManager.markRunning(robotUuid);
                    try {
                        executor.submit(() -> executeSingleRobotTask(robotUuid));
                    } catch (RejectedExecutionException e) {
                        // 如果提交被拒绝，必须立刻标记结束(释放Running状态)，否则该机器人会永久卡死
                        log.warn("任务提交被线程池拒绝: {}", robotUuid);
                        resourceManager.markFinished(robotUuid);
                    }
                }
            }
        } catch (Exception e) {
            log.error("Tick error", e);
        }
    }

    private void executeSingleRobotTask(String robotUuid) {
        RobotTaskContext.clear();
        RRobotAccount account = null;
        RLock lock = null;

        try {
            account = resourceManager.getAccount(robotUuid);
            if (account == null) {
                log.warn("无法获取机器人账户信息: {}", robotUuid);
                return;
            }

            String lockKey = "lock:robot:exec:" + robotUuid;
            lock = redissonClient.getLock(lockKey);

            // 尝试获取分布式锁，防止多实例并发
            if (!lock.tryLock()) {
                log.debug("获取分布式锁失败(可能在其他节点运行): {}", account.getEmail());
                return;
            }

            RConfigRelation relation = resourceManager.getRelation(robotUuid);
            RRunningConfig config = resourceManager.getConfig(relation.getConfigUuid());

            RobotTaskContext.initContext();
            RobotTaskContext.setRobotAccount(account);
            RobotTaskContext.setConfigRelation(relation);
            RobotTaskContext.setRunningConfig(config);

            // 1. 获取会话
            LoginResponse session = sessionManager.getOrRefreshSession(account);
            if (session == null) {
                log.warn("机器人登录/刷新Session失败: {}", account.getEmail());
                resourceManager.reportFailure(robotUuid);
                recordService.recordRobotRunRecord(null, account, relation, config, null, "登录失败", "登录失败", "接口无响应", 2);
                return;
            }
            RobotTaskContext.setLoginContext(session);

            recordService.recordRobotRunningInfo(null, account, relation, config, session.getUser_info());

            // 2. 执行直播间业务
            boolean success = actionService.enterAndHandover(account, relation, config, cachedLiveRooms);

            if (success) {
                resourceManager.reportSuccess(robotUuid);
            } else {
                log.debug("进入直播间流程返回False(可能无符合条件房间或Action出错): {}", account.getEmail());
            }

            // 3. 登出判断
            if (!ConfigTimeHelper.isInValidTime(relation)) {
                log.debug("机器人 {} 已不在配置有效期内，执行登出操作", account.getEmail());
                performLogout(account, session, relation, config);
            }

        } catch (Exception e) {
            log.error("Task Exception: {}", (account != null ? account.getEmail() : robotUuid), e);
            if (account != null) {
                // 捕获未处理的异常并记录
                recordService.recordRobotRunRecord(null, account, null, null, null, "任务异常", "运行时未捕获异常", e.getMessage(), 2);
            }
            resourceManager.reportFailure(robotUuid);
        } finally {
            // 无论成功失败，必须释放 Running 状态，并更新 LastFinishTime
            resourceManager.markFinished(robotUuid);

            RobotTaskContext.clear();
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    private void performLogout(RRobotAccount account, LoginResponse session, RConfigRelation relation, RRunningConfig config) {
        try {
            if (session != null && StrUtil.isNotBlank(session.getToken()) && session.getUser_info() != null) {
                ApiResponse resp = businessService.logout(Integer.parseInt(session.getUser_info().getUser_id()), session.getToken());
                if (!resp.isSuccess()) {
                    log.warn("机器人登出失败: {}, Msg: {}", account.getEmail(), resp.getMessage());
                    recordService.recordRobotRunRecord(null, account, relation, config, session.getUser_info(), "登出", "登出失败", resp.getMessage(), 2);
                } else {
                    recordService.recordRobotRunRecord(null, account, relation, config, session.getUser_info(), "登出", "登出成功", "OK", 4);
                }
            }
            sessionManager.invalidateSession(account.getUuid());
            recordService.updateRobotRunningInfoAfterQuit(account, null, null);
            actionService.clearRobotCacheOnLogout(account);
        } catch (Exception e) {
            log.error("登出操作异常: {}", account.getEmail(), e);
            recordService.recordRobotRunRecord(null, account, relation, config, (session != null ? session.getUser_info() : null), "登出", "登出异常", e.getMessage(), 2);
        }
    }

    private void refreshLiveRooms() {
        //30秒刷新一次
        if (System.currentTimeMillis() - lastRoomRefreshTime > 1 * 30 * 1000) {
            liveService.clearLiveRoomCache();
            try {
                List<LiveRoom> latest = liveService.getLiveRoomList();
                if (latest != null) {
                    this.cachedLiveRooms = latest;
                    this.lastRoomRefreshTime = System.currentTimeMillis();
                } else {
                    log.warn("获取直播间列表返回Null");
                }
            } catch (Exception e) {
                log.error("Live room refresh failed", e);
            }
        }
    }

    public void stop() { isRunning.set(false); }
    public void start() { isRunning.set(true); }

    public void reset() {
        log.debug("触发任务重置...");
        executor.getQueue().clear();
        resourceManager.clear();
        actionService.clearAllCacheOnTaskEnd();
        lastRoomRefreshTime = 0;
    }
}