package com.aps.controller;

import com.aps.common.util.R;
import com.aps.common.util.ExceptionMessageUtil;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.ProdSceneConfig;
import com.aps.service.LanuchService;
import com.aps.service.ProdSceneConfigService;
import com.aps.service.plan.PlanResultService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@RestController
@RequestMapping("/lanuch")
@Tag(name = "启动工单", description = "启动工单接口")
public class LanuchController {

    @Autowired
    private LanuchService lanuchService;

    @Autowired
    private PlanResultService planResultService;

    @Autowired
    private ProdSceneConfigService prodSceneConfigService;
    private static final Logger log = LoggerFactory.getLogger(LanuchController.class);

    /**
     * 启动工单
     */
    @PostMapping("/execute")
    @Operation(summary = "启动工单")
    public R<ProdSceneConfig> lanuch(@RequestBody Map<String, String> params) {

        String sceneName = params.get("sceneName");
        String userId = params.get("userId");

        R<ProdSceneConfig> result = lanuchService.lanuch(sceneName, userId);

        // 异步更新物料和设备缓存，不等待完成
        CompletableFuture.runAsync(this::updateMaterialAndEquipmentCacheAsync);

        return result;
    }

    @Async
    public void updateMaterialAndEquipmentCacheAsync() {
        try {
            log.info("开始异步更新物料缓存");
            planResultService.getMaterials();
            log.info("物料缓存更新完成");
            log.info("开始异步更新设备缓存");
            planResultService.InitCalendarToAllMachines();
            log.info("设备缓存更新完成");
        } catch (Exception e) {
            log.error("异步更新物料和设备缓存时发生错误: ", e);
        }
    }

    /**
     * 执行排程
     */
    @PostMapping("/schedule")
    @Operation(summary = "运算")
    public R<String> schedule(@RequestBody Map<String, Object> params) {
        String sceneId = getStringParam(params, "sceneId");
        if (sceneId == null || sceneId.trim().isEmpty()) {
            throw new IllegalArgumentException("场景ID不能为空");
        }

        // 如果需要处理时间字段，可以从params中获取并转换
        // 例如：开始时间、结束时间等
        String startTimeStr = getStringParam(params, "startTime");
        String endTimeStr = getStringParam(params, "endTime");

        // 在这里可以添加时间格式转换逻辑
        // 根据不同格式解析时间字符串

        // 这些参数前端可以不传；不传时后端会根据 sceneId 找场景创建人，再查这个人的策略。
        Long userId = getLongParam(params, "userId");
        Long baseRuleId = getLongParam(params, "baseRuleId");
        if (baseRuleId == null) {
            baseRuleId = getLongParam(params, "ruleId");
        }
        if (baseRuleId == null) {
            baseRuleId = getLongParam(params, "referenceId");
        }
        String userRuleId = getStringParam(params, "userRuleId");
        String id = getStringParam(params, "id");
        if (id != null) {
            int index = id.indexOf(":");
            if (index > 0 && index < id.length() - 1) {
                String source = id.substring(0, index);
                String ruleId = id.substring(index + 1);
                // 前端如果传的是组合 id：USER:用户策略ID 走用户策略；GLOBAL:基础策略ID 走全局策略。
                if ("USER".equalsIgnoreCase(source) && userRuleId == null) {
                    userRuleId = ruleId;
                } else if ("GLOBAL".equalsIgnoreCase(source) && baseRuleId == null) {
                    baseRuleId = parseLongParam("id", ruleId);
                }
            }
        }

        Chromosome scheduleChromosomes = planResultService.execute2(sceneId, userId, baseRuleId, userRuleId);
        return R.ok("排产计算成功", "排产计算成功");
    }

    /**
     * 复制场景
     */
    @PostMapping("/copyScene")
    @Operation(summary = "复制场景")
    public R<ProdSceneConfig> copyScene(@RequestBody Map<String, String> params) {
        String oldSceneId = params.get("oldSceneId");
        String newSceneName = params.get("newSceneName");
        String userId = params.get("userId");

        return lanuchService.copyScene(oldSceneId, userId, newSceneName);
    }

    /**
     * 导出计划
     */
    @PostMapping("/exportPlan")
    @Operation(summary = "导出计划")
    public R<String> exportPlan(@RequestBody Map<String, String> params) {
        String sceneId = params.get("sceneId");

        return lanuchService.exportPlan(sceneId);
    }

    /**
     * 删除场景
     */
    @PostMapping("/deleteScene")
    @Operation(summary = "删除场景")
    public R<Boolean> deleteScene(@RequestBody Map<String, String> params) {
        String sceneId = params.get("sceneId");

        boolean result = prodSceneConfigService.deleteSceneById(sceneId);
        return result ? R.ok(true) : R.ok(false, "删除场景失败");
    }

    /**
     * 删除用户下所有场景
     */
    @PostMapping("/deleteAllScenesByUser")
    @Operation(summary = "删除用户下所有场景")
    public R<Boolean> deleteAllScenesByUser(@RequestBody Map<String, String> params) {
        String userId = params.get("userId");

        if (userId == null || userId.isEmpty()) {
            return R.failed("用户ID不能为空");
        }

        // 查询该用户的所有场景
        List<ProdSceneConfig> scenes = prodSceneConfigService.lambdaQuery()
                .eq(ProdSceneConfig::getCreateUser, userId)
                .list();

        boolean hasDeletionFailure = false;
        String failureMessage = "";

        // 逐个删除场景
        for (ProdSceneConfig scene : scenes) {
            try {
                boolean result = prodSceneConfigService.deleteSceneById(scene.getSceneId());
                if (!result) {
                    hasDeletionFailure = true;
                    failureMessage += "场景ID " + scene.getSceneId() + " 删除失败; ";
                }
            } catch (Exception e) {
                hasDeletionFailure = true;
                failureMessage += "场景ID " + scene.getSceneId() + " 删除异常: "
                        + ExceptionMessageUtil.toClientMessage(e, "删除场景失败") + "; ";
            }
        }

        if (hasDeletionFailure) {
            return R.ok(false, failureMessage);
        }

        return R.ok(true, "成功删除用户 " + userId + " 下的 " + scenes.size() + " 个场景");
    }

    /**
     * 获取用户所有场景
     */
    @PostMapping("/getAllScene")
    @Operation(summary = "获取用户场景")
    public R<List<ProdSceneConfig>> getAllScene(@RequestBody Map<String, String> params) {
        String userId = params.get("userId");

        List<ProdSceneConfig> scenes = prodSceneConfigService.lambdaQuery()
                .eq(ProdSceneConfig::getCreateUser, userId)
                .orderByDesc(ProdSceneConfig::getCreateTime)
                .list();
        return R.ok(scenes);
    }

    /**
     * 保存方案
     */
    @PostMapping("/savePlan")
    @Operation(summary = "保存方案")
    public R<String> savePlan(@RequestBody Map<String, String> params) {
        String sceneId = params.get("sceneId");

        return lanuchService.savePlan(sceneId);
    }

    /**
     * 插单：向现有场景添加新订单
     */
    @PostMapping("/insertOrder")
    @Operation(summary = "插单", description = "向现有场景添加新订单，订单ID会自动生成UUID格式")
    public R<String> insertOrder(@RequestBody Map<String, Object> params) {
        String sceneId = (String) params.get("sceneId");
        String orderCode = (String) params.get("orderCode");
        String materialId = (String) params.get("materialId");
        
        // 解析时间参数
        String startDateStr = (String) params.get("startDate");
        String endDateStr = (String) params.get("endDate");
        java.time.LocalDateTime startDate = java.time.LocalDateTime.parse(startDateStr);
        java.time.LocalDateTime endDate = java.time.LocalDateTime.parse(endDateStr);
        
        // 解析优先级和数量
        Integer priority = params.get("priority") != null ? 
                Integer.valueOf(params.get("priority").toString()) : 1;
        Double quantity = params.get("quantity") != null ? 
                Double.valueOf(params.get("quantity").toString()) : 0.0;

        return lanuchService.insertOrder(sceneId, orderCode, materialId, 
                startDate, endDate, priority, quantity);
    }

    private String getStringParam(Map<String, ?> params, String key) {
        if (params == null || params.get(key) == null) {
            return null;
        }
        String value = String.valueOf(params.get(key)).trim();
        return value.isEmpty() ? null : value;
    }

    private Long getLongParam(Map<String, ?> params, String key) {
        String value = getStringParam(params, key);
        return parseLongParam(key, value);
    }

    private Long parseLongParam(String key, String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        try {
            return Long.valueOf(value.trim());
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException(key + "必须是数字");
        }
    }
}
