package com.xvji.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xvji.common.core.domain.AjaxResult;
import com.xvji.domain.Component;
import com.xvji.domain.PredictTask;
import com.xvji.domain.vo.PageResult;
import com.xvji.domain.vo.PredictTaskVO;
import com.xvji.mapper.PredictTaskMapper;
import com.xvji.service.ComponentService;
import com.xvji.service.PredictTaskService;
import org.aspectj.weaver.loadtime.Aj;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/task/predict")
public class PredictTaskController {

    private static final Logger log = LoggerFactory.getLogger(PredictTaskController.class);

    @Autowired
    private PredictTaskService predictTaskService;

    @Autowired
    private ComponentService componentService;

    @Autowired
    private PredictTaskMapper predictTaskMapper;

    /**
     * 新增预测任务及关联组件
     */
    @PostMapping("/addTask")
    @Transactional
    public AjaxResult addPredictTask(@RequestBody Map<String, Object> taskInfo) {
        try {
            PredictTask task = new PredictTask();
            task.setPTaskName((String) taskInfo.get("pTaskName"));
            task.setPCronExpression((String) taskInfo.get("pCronExpression"));
            task.setPQuartzTask((String) taskInfo.get("pQuartzTask"));
            task.setPRunInfo((String) taskInfo.get("pRunInfo"));

            //暂时隐藏任务状态
//            Object ptaskStatusObj = taskInfo.get("ptaskStatus");
//            if (ptaskStatusObj != null){
//                try {
//                    Integer ptaskStatus = Integer.parseInt(ptaskStatusObj.toString());
//                    if (ptaskStatus != 1 && ptaskStatus != 0 && ptaskStatus != 2){
//                        return AjaxResult.error("任务状态必须是0,1,2，请检查输入");
//                    }
//                    task.setPTaskStatus(ptaskStatus);
//                }catch (Exception e){
//                    return AjaxResult.error("传递的任务状态格式不正确");
//                }
//            }

            Object pTaskIdObj = taskInfo.get("pTaskId");
            Long manualTaskId = null;
            if (pTaskIdObj != null) {
                // 校验ID格式
                try {
                    manualTaskId = Long.parseLong(pTaskIdObj.toString());
                } catch (NumberFormatException e) {
                    return AjaxResult.error("传入的任务ID格式不正确 ，请传数字类型");
                }
                // 校验ID是否已存在
                PredictTask existTask = predictTaskMapper.selectById(manualTaskId);
                if (existTask != null) {
                    return AjaxResult.error("任务ID已存在：" + manualTaskId + "，请更换其他 ID");
                }
                task.setPTaskId(manualTaskId);
            }

            boolean taskAdded = predictTaskService.save(task);
            if (!taskAdded) {
                return AjaxResult.error("预测任务新增失败");
            }

            Long taskId = task.getPTaskId();
            List<Long> componentIds = new ArrayList<>();

            // 数据获取组件
            Map<String, Object> dataAcquisition = (Map<String, Object>) taskInfo.get("dataAcquisition");
            if (dataAcquisition != null) {
                Boolean isEnable = parseEnableValue(dataAcquisition.get("isEnable"), "数据获取");
                String type = (String) dataAcquisition.get("componentType");
                String url = "http://ds3:10001/mysql_to_mongo";
                Component component = createComponent(taskId, type, dataAcquisition, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("数据获取组件保存失败");
                }
            }

            // 数据处理组件
            Map<String, Object> dataCleaning = (Map<String, Object>) taskInfo.get("dataCleaning");
            if (dataCleaning != null) {
                Boolean isEnable = parseEnableValue(dataCleaning.get("isEnable"), "数据处理");
                String type = (String) dataCleaning.get("componentType");
                String url = "http://ds3:10013/pre_process";
                Component component = createComponent(taskId, type, dataCleaning, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("数据处理组件保存失败");
                }
            }

            // 限电清洗组件
            Map<String, Object> powerRationing = (Map<String, Object>) taskInfo.get("powerRationing");
            if (powerRationing != null) {
                Boolean isEnable = parseEnableValue(powerRationing.get("isEnable"), "限电清洗");
                String type = (String) powerRationing.get("componentType");
                String url = "";
                if ("限电清洗-光伏".equals(type)){
                    url = "http://ds3:10008/processing_limit_power_by_statistics_light";
                }else if ("限电清洗-风电".equals(type)){
                    url = "http://ds3:10009/processing_limit_power_by_statistics_wind";
                }
                Component component = createComponent(taskId, type, powerRationing, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("限电清洗组件保存失败");
                }
            }

            // 模型组件
            Map<String, Object> model = (Map<String, Object>) taskInfo.get("model");
            if (model != null) {
                Boolean isEnable = parseEnableValue(model.get("isEnable"), "模型");
                String type = (String) model.get("componentType");
                String url = "";
                if ("光伏物理模型".equals(type)){
                    url = "http://ds3:10014/model_prediction_photovoltaic_physical";
                }else if ("风电物理模型".equals(type)){
                    url = "http://ds3:10014/model_prediction_wind_physical";
                }else if ("Holtwinters模型".equals(type)){
                    url = "http://ds3:10007/model_prediction_holtwinters";
                }else if ("LSTM-预测".equals(type)){
                    url = "http://ds3:10004/tf_lstm_predict";
                }else if ("机器学习模型-预测".equals(type)){
                    url = "http://ds3:10006/model_prediction_ml";
                }
                Component component = createComponent(taskId, type, model, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException(type + "组件保存失败");
                }
            }

            // 后处理组件
            Map<String, Object> postProcessing = (Map<String, Object>) taskInfo.get("processing");
            if (postProcessing != null) {
                Boolean isEnable = parseEnableValue(postProcessing.get("isEnable"), "后处理");
                String type = (String) postProcessing.get("componentType");
                String url = "http://ds3:10013/post_process";
                Component component = createComponent(taskId, type, postProcessing, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("后处理组件保存失败");
                }
            }

            // 分析报告组件
            Map<String, Object> analysisReport = (Map<String, Object>) taskInfo.get("report");
            if (analysisReport != null) {
                Boolean isEnable = parseEnableValue(analysisReport.get("isEnable"), "分析报告");
                String type = (String) analysisReport.get("componentType");
                String url = "http://ds1:10099/analysis_report_small";
                Component component = createComponent(taskId, type, analysisReport, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("分析报告组件保存失败");
                }
            }

            // 更新任务表中的组件 ID 关联（逗号分隔）
            if (!componentIds.isEmpty()) {
                String componentIdsStr = componentIds.stream()
                        .map(String::valueOf)
                        .collect(java.util.stream.Collectors.joining(","));
                task.setPComponentIds(componentIdsStr);
                predictTaskService.updateById(task);
            }

            return AjaxResult.success("预测任务新增成功");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("新增失败：" + e.getMessage());
        }
    }

    /**
     * 分页查询预测任务及关联组件信息
     * @param pageNum 页码（默认1）
     * @param pageSize 每页条数（默认10）
     * @param taskName 任务名称
     */
    @GetMapping("/queryTasks")
    public AjaxResult queryPredictTasks(
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(required = false) String taskName) {

        try {
            Page<PredictTask> page = new Page<>(pageNum, pageSize);
            QueryWrapper<PredictTask> queryWrapper = new QueryWrapper<>();
            if (StringUtils.hasText(taskName)) {
                queryWrapper.like("P_TASK_NAME", taskName); // 预测任务名称字段
            }
            //按创建时间降序排序
            queryWrapper.orderByDesc("P_CREATE_TIME");

            //执行分页查询
            Page<PredictTask> taskPage = predictTaskService.page(page, queryWrapper);

            List<PredictTaskVO> taskVOList = taskPage.getRecords().stream().map(task -> {
                PredictTaskVO vo = new PredictTaskVO();
                BeanUtils.copyProperties(task, vo); // 复制基本属性

                String componentIds = task.getPComponentIds(); // 预测任务的组件ID字段
                if (StringUtils.hasText(componentIds)) {
                    List<Long> ids = Arrays.stream(componentIds.split(","))
                            .map(Long::parseLong)
                            .collect(Collectors.toList());
                    List<Component> components = componentService.listByIds(ids);
                    vo.setComponents(components); // 设置关联的组件列表
                }
                return vo;
            }).collect(Collectors.toList());

            // 5. 封装分页结果
            PageResult<PredictTaskVO> result = new PageResult<>(
                    taskPage.getTotal(),    // 总记录数
                    pageNum,                // 当前页码
                    pageSize,               // 每页条数
                    taskVOList              // 分页数据列表
            );

            return AjaxResult.success(result);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("查询预测任务失败：" + e.getMessage());
        }
    }

    /**
     * 根据id删除预测任务
     * @param pTaskId
     * @return
     */
    @DeleteMapping("/{pTaskId}")
    public AjaxResult deleteById(@PathVariable Long pTaskId){
        try {

            boolean result = predictTaskService.deletePredictTaskWithComponents(pTaskId);
            if (result){
                return AjaxResult.success("预测任务删除成功");
            }else {
                return AjaxResult.error("预测任务id不存在");
            }
        }catch (Exception e){
            return AjaxResult.error("预测任务删除失败" + e.getMessage());
        }
    }

    /**
     * 编辑预测任务
     * @param taskInfo
     * @return
     */
    @Transactional
    @PostMapping("/updateTask")
    public AjaxResult updateTask(@RequestBody Map<String , Object> taskInfo){
        try {
            PredictTask task = new PredictTask();
            if (taskInfo == null){
                return AjaxResult.error("预测任务不存在 , 无法编辑");
            }
            // id校验
            Object pTaskIdObj = taskInfo.get("pTaskId");
            if (pTaskIdObj == null){
                return AjaxResult.error("任务id 不可为空");
            }
            Long pTaskId = null;
            try {
                pTaskId = Long.parseLong(pTaskIdObj.toString());
            }catch (Exception e){
                return AjaxResult.error("传入的任务id不正确");
            }

            //状态校验
//            Integer pTaskStatus = null;
//            try {
//                Object pTaskStatusObj = taskInfo.get("pTaskStatus");
//                if (pTaskStatusObj != null){
//                    pTaskStatus = Integer.parseInt(pTaskStatusObj.toString());
//                    if (pTaskStatus != 0 && pTaskStatus != 1 && pTaskStatus != 2){
//                        return AjaxResult.error("任务状态必须是0,1,2，请检查输入");
//                    }
//                }
//            }catch (Exception e){
//                return AjaxResult.error("任务状态格式不正确");
//            }

            task.setPTaskId(pTaskId);
            task.setPTaskName((String) taskInfo.get("pTaskName"));
            task.setPCronExpression((String) taskInfo.get("pCronExpression"));
            task.setPQuartzTask((String) taskInfo.get("pQuartzTask"));
            task.setPRunInfo((String) taskInfo.get("pRunInfo"));
//            task.setPTaskStatus(pTaskStatus);

            boolean updateTask = predictTaskService.updateById(task);
            if (!updateTask){
                return AjaxResult.error("编辑任务失败");
            }
            QueryWrapper<Component> componentQueryWrapper = new QueryWrapper<>();
            componentQueryWrapper
                    .eq("TASK_ID", pTaskId)
                    .eq("TASK_TYPE", 1);//预测任务类型为1
            componentService.remove(componentQueryWrapper);

            List<Long> componentIds = new ArrayList<>();

            // 数据获取组件
            Map<String, Object> dataAcquisition = (Map<String, Object>) taskInfo.get("dataAcquisition");
            if (dataAcquisition != null) {
                Boolean isEnable = parseEnableValue(dataAcquisition.get("isEnable"), "数据获取");
                String type = (String) dataAcquisition.get("componentType");
                String url = "http://ds3:10001/mysql_to_mongo";
                Component component = createComponent(pTaskId, type, dataAcquisition, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("数据获取组件保存失败");
                }
            }

            // 数据处理组件
            Map<String, Object> dataCleaning = (Map<String, Object>) taskInfo.get("dataCleaning");
            if (dataCleaning != null) {
                Boolean isEnable = parseEnableValue(dataCleaning.get("isEnable"), "数据处理");
                String type = (String) dataCleaning.get("componentType");
                String url = "http://ds3:10013/pre_process";
                Component component = createComponent(pTaskId, type, dataCleaning, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("数据处理组件保存失败");
                }
            }

            // 限电清洗组件
            Map<String, Object> powerRationing = (Map<String, Object>) taskInfo.get("powerRationing");
            if (powerRationing != null) {
                Boolean isEnable = parseEnableValue(powerRationing.get("isEnable"), "限电清洗");
                String type = (String) powerRationing.get("componentType");
                String url = "";
                if ("限电清洗-光伏".equals(type)){
                    url = "http://ds3:10008/processing_limit_power_by_statistics_light";
                }else if ("限电清洗-风电".equals(type)){
                    url = "http://ds3:10009/processing_limit_power_by_statistics_wind";
                }
                Component component = createComponent(pTaskId, type, powerRationing, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("限电清洗组件保存失败");
                }
            }

            // 模型组件（预测任务不需要额外添加modelTest组件）
            Map<String, Object> model = (Map<String, Object>) taskInfo.get("model");
            if (model != null) {
                Boolean isEnable = parseEnableValue(model.get("isEnable"), "模型");
                String type = (String) model.get("componentType");
                String url = "";
                if ("光伏物理模型".equals(type)){
                    url = "http://ds3:10014/model_prediction_photovoltaic_physical";
                }else if ("风电物理模型".equals(type)){
                    url = "http://ds3:10014/model_prediction_wind_physical";
                }else if ("Holtwinters模型".equals(type)){
                    url = "http://ds3:10007/model_prediction_holtwinters";
                }else if ("LSTM-预测".equals(type)){
                    url = "http://ds3:10004/tf_lstm_predict";
                }else if ("机器学习模型-预测".equals(type)){
                    url = "http://ds3:10006/model_prediction_ml";
                }
                Component component = createComponent(pTaskId, type, model, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException(type + "组件保存失败");
                }
            }

            // 后处理组件
            Map<String, Object> postProcessing = (Map<String, Object>) taskInfo.get("processing");
            if (postProcessing != null) {
                Boolean isEnable = parseEnableValue(postProcessing.get("isEnable"), "后处理");
                String type = (String) postProcessing.get("componentType");
                String url = "http://ds3:10013/post_process";
                Component component = createComponent(pTaskId, type, postProcessing, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("后处理组件保存失败");
                }
            }

            // 分析报告组件
            Map<String, Object> analysisReport = (Map<String, Object>) taskInfo.get("report");
            if (analysisReport != null) {
                Boolean isEnable = parseEnableValue(analysisReport.get("isEnable"), "分析报告");
                String type = (String) analysisReport.get("componentType");
                String url = "http://ds1:10099/analysis_report_small";
                Component component = createComponent(pTaskId, type, analysisReport, isEnable , url);
                if (componentService.save(component)) {
                    componentIds.add(component.getComponentId());
                } else {
                    throw new RuntimeException("分析报告组件保存失败");
                }
            }

            // 更新任务表中的组件 ID 关联（逗号分隔）
            if (!componentIds.isEmpty()) {
                String componentIdsStr = componentIds.stream()
                        .map(String::valueOf)
                        .collect(java.util.stream.Collectors.joining(","));
                task.setPComponentIds(componentIdsStr);
                predictTaskService.updateById(task);
            }

            return AjaxResult.success("编辑预测任务成功");

        }catch (Exception e){
            return AjaxResult.error("编辑预测任务失败" + e.getMessage());
        }
    }


    ////////////////////////////////////////// 辅助方法 //////////////////////////////////////////////////////////////////////

    /**
     * 辅助方法：创建组件对象
     */
    private Component createComponent(Long taskId, String componentType, Map<String, Object> config, Boolean isEnable , String url) {
        Component component = new Component();
        component.setTaskId(taskId);         // 关联当前预测任务 ID
        component.setTaskType(1);            // 1-预测任务（固定标识）
        component.setComponentType(componentType);
        component.setParamsMap((Map<String, Object>) config.get("params"));
        component.setIsEnable(isEnable);     // 使用解析后的enable值
        component.setInterfaceUrl(url); // 接口地址

        return component;
    }

    /**
     * 统一解析enable值，兼容非Boolean类型
     */
    private Boolean parseEnableValue(Object enableObj, String componentName) {
        if (enableObj instanceof Boolean) {
            return (Boolean) enableObj;
        }
        // 非Boolean类型或null，默认false并记录日志
        if (enableObj != null) {
            log.warn("组件[{}]的enable参数类型错误非boolean类型，实际类型为{} 值{}，默认设为false",
                    componentName, enableObj.getClass().getSimpleName(), enableObj);
        } else {
            log.warn("组件[{}]未传递enable参数，已默认设为false", componentName);
        }
        return false;
    }
}
