package com.ruoyi.web.controller.ems;

import com.alibaba.fastjson2.JSONObject;
import com.huashe.common.domain.AjaxResult;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.ems.domain.OpEnergyStrategy;
import com.ruoyi.ems.domain.OpEnergyStrategyParam;
import com.ruoyi.ems.domain.OpEnergyStrategyStep;
import com.ruoyi.ems.model.ParamOption;
import com.ruoyi.ems.service.IOpEnergyStrategyParamService;
import com.ruoyi.ems.service.IOpEnergyStrategyService;
import com.ruoyi.ems.service.IOpEnergyStrategyStepService;
import io.swagger.annotations.Api;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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

/**
 * 能源策略Controller
 *
 * @author ruoyi
 * @date 2024-08-08
 */
@RestController
@RequestMapping("/ems/energyStrategy")
@Api(value = "OpEnergyStrategyController", description = "能源策略管理接口")
public class OpEnergyStrategyController extends BaseController {
    @Autowired
    private IOpEnergyStrategyService strategyService;

    @Autowired
    private IOpEnergyStrategyParamService paramService;

    @Autowired
    private IOpEnergyStrategyStepService stepService;

    private static final Map<String, List<ParamOption>> PARAM_OPTIONS = new HashMap<>();

    static {
        List<ParamOption> dcList = Arrays.asList(new ParamOption("maxPowerTrack", "最大功率点跟踪（MPPT）",
                "通过实时调整光伏阵列的工作状态，使光伏系统始终运行在最大功率点"),
            new ParamOption("inverterControl", "逆变器控制", "通过光伏逆变器实施控制"),
            new ParamOption("powerAndVoltage", "无功功率及电压控制",
                "根据电网需求，通过调节光伏系统输出的无功功率和电压，实现电压稳定和电力因素的优化"));

        PARAM_OPTIONS.put("default.controlMode", dcList);

        List<ParamOption> diList = Arrays.asList(
            new ParamOption("svpwm", "空间矢量控制（SVPWM）", "通过对逆变器开关状态的优化控制，实现并网电流的高精度控制"),
            new ParamOption("dtc", "直流转矩控制", "以控制逆变器输出转矩和磁链为目标，快速响应"));

        PARAM_OPTIONS.put("inverterControl.controlMode", diList);
    }

    /**
     * 查询能源策略列表
     */
    @GetMapping("/list")
    public TableDataInfo list(OpEnergyStrategy strategy) {
        startPage();
        List<OpEnergyStrategy> list = strategyService.selectStrategyList(strategy);
        return getDataTable(list);
    }

    /**
     * 获取能源策略详细信息
     */
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return success(strategyService.selectStrategyById(id));
    }

    /**
     * 新增能源策略
     */
    @PreAuthorize("@ss.hasPermi('power-mgr:strategy:add')")
    @Log(title = "能源策略", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody OpEnergyStrategy strategy) {
        return toAjax(strategyService.insertStrategy(strategy));
    }

    /**
     * 修改能源策略
     */
    @PreAuthorize("@ss.hasPermi('power-mgr:strategy:edit')")
    @Log(title = "能源策略", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody OpEnergyStrategy strategy) {
        return toAjax(strategyService.updateStrategy(strategy));
    }

    /**
     * 删除能源策略
     */
    @PreAuthorize("@ss.hasPermi('power-mgr:strategy:remove')")
    @Log(title = "能源策略", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(strategyService.deleteStrategyByIds(ids));
    }

    /**
     * 获取能源策略参数
     *
     * @param strategyCode 策略编码
     * @return 参数集合
     */
    @GetMapping(value = "/param")
    public AjaxResult getStrategyParam(@RequestParam(name = "strategyCode") String strategyCode) {
        // 补充策略参数
        List<OpEnergyStrategyParam> paramList = paramService.selectParamByStrategyCode(strategyCode);
        return success(buildStrategyParams(paramList));
    }

    /**
     * 修改能源策略
     */
    @PreAuthorize("@ss.hasPermi('power-mgr:strategy:edit')")
    @Log(title = "能源策略参数", businessType = BusinessType.UPDATE)
    @PutMapping("/param")
    public AjaxResult editParam(@RequestBody OpEnergyStrategyParam strategyParam) {
        AjaxResult result = null;

        try {
            int updateCnt = paramService.updateParamValue(strategyParam);
            result = toAjax(updateCnt);
        }
        catch (BusinessException e) {
            result = error(e.getMessage());
        }

        return result;
    }

    /**
     * 获取能源策略执行步骤
     *
     * @param strategyCode 策略编码
     * @return 步骤列表
     */
    @GetMapping(value = "/step")
    public AjaxResult getStrategyStep(@RequestParam(name = "strategyCode") String strategyCode) {
        return success(stepService.selectStepByStrategyCode(strategyCode));
    }

    /**
     * 新增能源策略执行步骤
     *
     * @param strategyStep 策略步骤
     * @return 步骤列表
     */
    @PostMapping(value = "/step")
    public AjaxResult addStrategyStep(@RequestBody OpEnergyStrategyStep strategyStep) {
        return toAjax(stepService.insertStep(strategyStep));
    }

    /**
     * 删除能源策略执行步骤
     *
     * @param strategyCode 策略代码
     * @return 步骤列表
     */
    @DeleteMapping(value = "/step")
    public AjaxResult delStrategyStep(@RequestParam(name = "strategyCode") String strategyCode) {
        return toAjax(stepService.deleteStepByStrategyCode(strategyCode));
    }

    /**
     * 修改能源策略执行步骤
     *
     * @param strategyStep 策略步骤
     * @return 步骤列表
     */
    @PutMapping(value = "/step")
    public AjaxResult editStrategyStep(@RequestBody OpEnergyStrategyStep strategyStep) {
        return toAjax(stepService.updateStep(strategyStep));
    }

    /**
     * 修改能源策略执行步骤
     *
     * @param strategySteps 策略步骤
     * @return 步骤列表
     */
    @PutMapping(value = "/step/batch")
    public AjaxResult editStrategyStep(List<OpEnergyStrategyStep> strategySteps) {
        stepService.deleteStepByStrategyCode(strategySteps.get(0).getStrategyCode());
        return toAjax(stepService.insertStepBatch(strategySteps));
    }

    /**
     * 获取能源策略参数选项
     *
     * @param strategyType 策略类型
     * @param paramKey     参数键
     * @return 选项
     */
    @GetMapping(value = "/param/option")
    public AjaxResult getStrategyParamOption(@RequestParam(name = "strategyType") int strategyType,
        @RequestParam(name = "paramKey") String paramKey) {
        List<ParamOption> options = null;

        switch (strategyType) {
            case 1:
                options = getYwParamOption(paramKey);
                break;
            case 2:
                options = getYhParamOption(paramKey);
                break;
            case 3:
                options = getWcParamOption(paramKey);
                break;
        }

        return CollectionUtils.isNotEmpty(options) ? success(options) : success(new ArrayList<>());
    }

    private List<ParamOption> getYwParamOption(String paramKey) {
        return PARAM_OPTIONS.get(paramKey);
    }

    private List<ParamOption> getYhParamOption(String paramKey) {
        return null;
    }

    private List<ParamOption> getWcParamOption(String paramKey) {
        return null;
    }

    private Map<String, Map<String, JSONObject>> buildStrategyParams(List<OpEnergyStrategyParam> paramList) {
        Map<String, Map<String, JSONObject>> params = new HashMap<>();

        Map<String, List<OpEnergyStrategyParam>> groupedMap = paramList.stream()
            .collect(Collectors.groupingBy(OpEnergyStrategyParam::getParamGroup, Collectors.toList()));

        for (Map.Entry<String, List<OpEnergyStrategyParam>> entry : groupedMap.entrySet()) {
            String groupName = entry.getKey();
            List<OpEnergyStrategyParam> groupParams = entry.getValue();

            if (params.containsKey(groupName)) {
                Map<String, JSONObject> groupParamMap = params.get(groupName);

                for (OpEnergyStrategyParam param : groupParams) {
                    JSONObject option = new JSONObject();
                    option.put("paramName", param.getParamName());
                    option.put("paramValue", param.getParamValue());
                    option.put("editEnable", param.getEditEnable());
                    option.put("paramValueFormat", param.getParamValueFormat());
                    groupParamMap.put(param.getParamKey(), option);
                }
            }
            else {
                Map<String, JSONObject> groupParamMap = new HashMap<>();

                for (OpEnergyStrategyParam param : groupParams) {
                    JSONObject option = new JSONObject();
                    option.put("paramName", param.getParamName());
                    option.put("paramValue", param.getParamValue());
                    option.put("editEnable", param.getEditEnable());
                    option.put("paramValueFormat", param.getParamValueFormat());
                    groupParamMap.put(param.getParamKey(), option);
                }

                params.put(groupName, groupParamMap);
            }
        }

        return params;
    }
}
