package com.xvji.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xvji.common.exception.job.TaskException;
import com.xvji.domain.Component;
import com.xvji.domain.PredictTask;
import com.xvji.mapper.PredictTaskMapper;
import com.xvji.quartz.domain.SysJob;
import com.xvji.quartz.service.ISysJobService;
import com.xvji.service.ComponentService;
import com.xvji.service.PredictTaskService;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.List;

@Service
public class PredictTaskServiceImpl extends ServiceImpl<PredictTaskMapper, PredictTask> implements PredictTaskService {

    @Autowired
    private ISysJobService sysJobService; // 若依定时任务Service

    @Autowired
    private ComponentService componentService;

    //Logger 对象
    private static final Logger log = LoggerFactory.getLogger(PredictTaskServiceImpl.class);

    /**
     * 新增预测任务并关联组件
     */
    @Transactional
    @Override
    public boolean addPredictTaskWithComponent(PredictTask predictTask, Component component) {
        // 设置预测任务默认值
        if (predictTask.getPCreateTime() == null) {
            predictTask.setPCreateTime(new Date());
        }
        if (predictTask.getPTaskStatus() == null) {
            //predictTask.setPTaskStatus(0); // 0-初始状态
        }

        // 插入预测任务
        boolean taskSaved = this.save(predictTask);
        if (!taskSaved) {
            throw new RuntimeException("预测任务插入失败");
        }

        // 设置关联的任务ID和类型（1-预测任务）
        component.setTaskId(predictTask.getPTaskId());
        component.setTaskType(1);
        if (component.getIsEnable() == null) {
            component.setIsEnable(true);
        }

        // 4. 插入组件
        boolean componentSaved = componentService.save(component);
        if (!componentSaved) {
            throw new RuntimeException("组件插入失败");
        }

        return true;
    }

    @Override
    public List<PredictTask> getAllPredictTasks() {
        return list();
    }

    /**
     * 根据id删除预测任务 以及关联组件
     * @param taskId
     * @return
     */
    @Transactional
    @Override
    public boolean deletePredictTaskWithComponents(Long taskId) {
        PredictTask predictTask = this.getById(taskId);
        if (predictTask == null) {
            return false; //无此预测任务
        }
        QueryWrapper<Component> componentQueryWrapper = new QueryWrapper<>();
        componentQueryWrapper
                .eq("TASK_ID" , taskId)
                .eq("TASK_TYPE" , 1); //预测任务类型为1
        componentService.remove(componentQueryWrapper);
        this.removeById(taskId);

        //同步删除关联的定时任务
        String targetInvokeTarget = "com.xvji.quartz.TaskQuartzJob.executePredictTask(" + taskId + ")";
        sysJobService.deleteJobByParam(targetInvokeTarget);
        log.info("预测任务[ID:{}]及关联组件、定时任务已删除", taskId);

        return true;
    }

    /**
     * 将业务任务同步到若依定时任务
     */
    private void syncToSysJob(PredictTask task) {
        // 检查是否是定时任务同步过来的更新，如果是则跳过
        // 通过判断任务名称是否包含特殊标记
        if (task.getPTaskName() != null && task.getPTaskName().contains("[SYNCED]")) {
            log.info("检测到是定时任务同步的更新，跳过反向同步");
            // 移除标记，避免影响显示
            task.setPTaskName(task.getPTaskName().replace("[SYNCED]", ""));
            this.updateById(task);
            return;
        }

        Long taskId = task.getPTaskId();
        String exactInvokeTarget = "com.xvji.quartz.TaskQuartzJob.executePredictTask(" + taskId + ")";
        SysJob sysJob = sysJobService.selectJobByParam(exactInvokeTarget);

        if (sysJob == null) {
            log.error("未找到关联业务任务ID[{}]的定时任务，同步失败", taskId);
            return;
        }

        // 校验Cron表达式
        String cron = task.getPCronExpression();
        if (cron != null && !sysJobService.checkCronExpressionIsValid(cron)) {
            log.error("Cron表达式[{}]无效，同步终止", cron);
            throw new RuntimeException("Cron表达式无效：" + cron);
        }

        // 同步核心字段
        sysJob.setJobName(task.getPTaskName());
        sysJob.setCronExpression(cron);
        sysJob.setStatus(task.getPTaskStatus().toString());
        sysJob.setJobGroup("PREDICT_TASK");

        // 执行更新
        boolean syncSuccess = sysJobService.updateSysJob(sysJob);
        if (syncSuccess) {
            log.info("预测任务[ID:{}]成功同步到定时任务[ID:{}]", taskId, sysJob.getJobId());
        } else {
            log.error("预测任务[ID:{}]同步到定时任务失败", taskId);
        }
    }


    @Transactional
    @Override
    public boolean updatePredictTask(PredictTask task) {
        // 更新业务任务表
        boolean updateResult = this.updateById(task);
        if (!updateResult) {
            log.error("预测任务[ID:{}]更新失败，同步定时任务终止", task.getPTaskId());
            return false;
        }

        //  调用同步方法，实现业务→定时同步
        syncToSysJob(task);
        return true;
    }

}