package com.fs.app.task;

import cn.hutool.json.JSONUtil;
import com.fs.app.taskService.SopLogsTaskService;
import com.fs.common.core.redis.RedisCache;
import com.fs.course.config.CourseConfig;
import com.fs.course.domain.FsCourseWatchLog;
import com.fs.course.domain.FsUserCourseVideo;
import com.fs.course.dto.UserCourseStudyDto;
import com.fs.course.mapper.FsCourseLinkMapper;
import com.fs.course.mapper.FsCourseWatchLogMapper;
import com.fs.course.mapper.FsUserCourseVideoMapper;
import com.fs.course.service.IFsCourseLinkService;
import com.fs.course.service.IFsCourseRedPacketRetryService;
import com.fs.course.service.IFsCourseWatchLogService;
import com.fs.course.service.IFsUserCourseStudyService;
import com.fs.framework.config.ThreadPoolConfig;
import com.fs.gtPush.service.uniPush2Service;
import com.fs.his.enums.PushLogDesTypeEnum;
import com.fs.his.enums.PushLogTypeEnum;
import com.fs.sop.domain.QwSopLogs;
import com.fs.sop.mapper.QwSopLogsMapper;
import com.fs.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.*;

import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicBoolean;

@Component
@Slf4j
public class CourseWatchLogScheduler {
    private final AtomicBoolean isRunning1 = new AtomicBoolean(false);

    private final AtomicBoolean isRunning2 = new AtomicBoolean(false);

    private final AtomicBoolean isRunning3 = new AtomicBoolean(false);
    @Autowired
    private FsCourseWatchLogMapper courseWatchLogMapper;

    @Autowired
    private QwSopLogsMapper qwSopLogsMapper;

    @Autowired
    RedisCache redisCache;

    @Autowired
    private FsUserCourseVideoMapper courseVideoMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IFsCourseWatchLogService courseWatchLogService;

    @Autowired
    private SopLogsTaskService sopLogsTaskService;

    @Autowired
    private IFsCourseRedPacketRetryService redPacketRetryService;

    @Autowired
    private IFsUserCourseStudyService fsUserCourseStudyService;
    @Autowired
    @Qualifier("threadPoolTaskExecutor")  // 使用异步线程池
    private ThreadPoolTaskExecutor  threadPoolTaskExecutor;

    @Autowired
    private com.fs.gtPush.service.uniPush2Service uniPush2Service;

//    // 定时任务批量更新到数据库
//    @Scheduled(fixedRate = 60000) // 每分钟执行一次
//    public void scheduleBatchUpdateToDatabase() {
//        courseWatchLogService.scheduleBatchUpdateToDatabase();
//    }



    /**
     * 检查看课状态
     */
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    public void checkWatchStatus() {
        // 尝试设置标志为 true，表示任务开始执行
        if (!isRunning1.compareAndSet(false, true)) {
            log.warn("检查看课中任务执行 - 上一个任务尚未完成，跳过此次执行");
            return;
        }
        try {
            log.info("检查看课中任务执行>>>>>>>>>>>>");
            courseWatchLogService.scheduleBatchUpdateToDatabase();
            courseWatchLogService.checkWatchStatus();
            log.info("检查看课中任务执行完成>>>>>>>>>>>>");
        }catch (Exception e) {
            log.error("检查看课中任务执行完成 - 定时任务执行失败", e);
        } finally {
            // 重置标志为 false，表示任务已完成
            isRunning1.set(false);
        }

    }



    /**
     * 创建完课消息
     */
    @Scheduled(cron = "0 */5 * * * ?") // 每五分钟执行一次
    public void createCourseFinishMsg() {
        // 尝试设置标志为 true，表示任务开始执行
        if (!isRunning3.compareAndSet(false, true)) {
            log.warn("创建完课消息 - 上一个任务尚未完成，跳过此次执行");
            return;
        }

        try {
            log.info("创建完课消息 - 定时任务开始");
            sopLogsTaskService.createCourseFinishMsg();
            log.info("创建完课消息 - 定时任务成功完成");
        } catch (Exception e) {
            log.error("创建完课消息 - 定时任务执行失败", e);
        } finally {
            // 重置标志为 false，表示任务已完成
            isRunning3.set(false);

        }

    }

    @Autowired
    private IFsCourseLinkService courseLinkService;


    // 定时任务，每天0点执行

    /**
     * 每天删除过期短链
     */
    @Scheduled(cron = "0 5 0 * * ?")  // 0点5分0秒执行
    public void delCourseExpireLink() {
        try {
            log.info("删除过期短链 - 定时任务开始");
            courseLinkService.delCourseExpireLink();
            log.info("删除过期短链 - 定时任务成功完成");
        } catch (Exception e) {
            log.error("删除过期短链 - 定时任务执行失败", e);
        }

    }

    /**
     * 红包补发定时任务
     */
//    @Scheduled(cron = "0 */5 * * * ?")  //每5分钟执行一次
    public void redPacketRetry() {
        try {
            log.info("红包补发任务开始");
            redPacketRetryService.redPacketRetry();
            log.info("红包补发任务开始");
        } catch (Exception e) {
            log.error("红包补发 - 定时任务执行失败", e);
        }

    }

    @Scheduled(cron = "0 0 10 * * ?") // 每天10点执行
    public void scheduleRandomTask() {
        Random random = new Random();
        int randomMinute = random.nextInt(240); // 在10:00到14:00之间随机生成分钟数
        long delay = randomMinute * 60 * 1000; // 转换为毫秒

        // 提交一个带有延迟的异步任务
        threadPoolTaskExecutor.execute(() -> {
            try {
                Thread.sleep(delay); // 在执行任务前先延迟
                jPush(); // 执行具体任务
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
    }

    @Async("threadPoolTaskExecutor") // 指定使用自定义线程池的 Bean 名称
    public void jPush() {
       //使用极光推送通知到用户
        List<UserCourseStudyDto> userCourseStudyDtos = fsUserCourseStudyService.selectCourseGroupByUser();
        if (userCourseStudyDtos.size() > 0) {
            // 使用线程池或异步执行，提升性能
            userCourseStudyDtos.parallelStream().forEach(userCourse -> {
                try {
                    // 添加推送逻辑
                    uniPush2Service.pushOne(userCourse.getUserId(), null, null, "课程提醒",
                            "您的课程" + userCourse.getCourseName() + "还没学习完哦",
                            PushLogTypeEnum.MARKET.getValue(), PushLogDesTypeEnum.STUDY_COURSE.getValue());
                } catch (Exception e) {
                    // 处理推送异常
                    log.error("推送失败，用户ID: " + userCourse.getUserId(), e);
                }
            });
        }

    }




}
