package com.css.simulation.resource.server.adapter.controller.scene_library.score_rule;

import api.common.pojo.common.ResponseBodyVO;
import api.common.pojo.constants.DictConstants;
import api.common.pojo.constants.LogConstants;
import api.common.pojo.enums.SceneEvaluationEnum;
import api.common.pojo.param.scene.SceneEvaluationDetailParam;
import api.common.pojo.param.scene.SceneEvaluationRuleParam;
import api.common.pojo.param.scene.SceneEvaluationScriptParam;
import api.common.pojo.param.scene.ScoringRulesParam;
import api.common.pojo.po.scene.SceneComplexityPO;
import api.common.pojo.po.scene.SceneEvaluationRulePO;
import api.common.pojo.po.scene.SceneRiskPO;
import api.common.pojo.po.scene.ScoringRulesPO;
import api.common.pojo.vo.scene.SceneComplexityVO;
import api.common.pojo.vo.scene.SceneEvaluationRuleVO;
import api.common.pojo.vo.scene.SceneRiskVO;
import api.common.pojo.vo.scene.ScoringRulesVO;
import api.common.util.CollectionUtil;
import api.common.util.ObjectUtil;
import api.common.util.PythonUtil;
import api.common.util.StringUtil;
import com.css.simulation.resource.server.app.service.SceneEvaluationRuleService;
import com.css.simulation.resource.server.app.service.ScoringRulesService;
import com.css.simulation.resource.server.infra.util.AuthUtil;
import com.css.simulation.resource.server.infra.util.PageUtil;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//打分规则
@Slf4j
@RestController
@RequestMapping(value = "/ScoringRules", name = LogConstants.MODULE_SCORING)
public class ScoreRuleController {

    @Resource
    private ScoringRulesService scoringRulesService;

    @Resource
    private SceneEvaluationRuleService sceneEvaluationRuleService;

    //查询列表
    @PostMapping("/queryScoringRulesList")
    public ResponseBodyVO<PageInfo<ScoringRulesVO>> queryScoringRulesList(@RequestBody ScoringRulesParam parms) {
        PageUtil.setPageInfo(parms);
        List<ScoringRulesPO> list = scoringRulesService.queryScoringRulesList(parms);
        PageInfo<ScoringRulesPO> scoringRulesPOPageInfo = new PageInfo<>(list);
        List<ScoringRulesVO> list1 = new ArrayList<>();
        //po转vo
        for (ScoringRulesPO po : list) {
            ScoringRulesVO vo = new ScoringRulesVO();
            BeanUtils.copyProperties(po, vo);
            list1.add(vo);
        }
        PageInfo<ScoringRulesVO> pageInfo = new PageInfo<>(list1);
        pageInfo.setTotal(scoringRulesPOPageInfo.getTotal());

        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
    }

    //查询详情
    @PostMapping("/queryScoringRules")
    public ResponseBodyVO<ScoringRulesPO> queryScoringRules(@RequestBody ScoringRulesParam parms) {
        if (ObjectUtil.isNull(parms.getRulesId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "参数RulesId不能为空，请检查");
        }
        ScoringRulesPO po = scoringRulesService.queryScoringRules(parms);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, po);

    }

    //查唯一
    @PostMapping("/queryScoringRulesCount")
    public ResponseBodyVO<ScoringRulesPO> queryScoringRulesCount(@RequestBody ScoringRulesParam parms) {
        if (ObjectUtil.isNull(parms.getRuleName())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "参数RulesName不能为空，请检查");
        }
        ScoringRulesPO po = scoringRulesService.queryScoringRulesByRuleName(parms);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, po);
    }


    /**
     * 新增打分规则
     */
    @PostMapping("/saveScoringRules")
    public ResponseBodyVO<String> saveScoringRules(@RequestBody ScoringRulesPO scoringRulesPO) {
        //1 校验 python 语法错误
        String pylint = PythonUtil.pylint(scoringRulesPO.getRuleDetails(), PythonUtil.C, PythonUtil.R, PythonUtil.W, PythonUtil.E0401, PythonUtil.E0601);
        if (!pylint.contains(PythonUtil.PASS)) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "代码格式错误，请检查。");
        }
        //2 判断 ruleId 是否为空
        if (StringUtil.isEmpty(scoringRulesPO.getRulesId())) {
            /*
                1 共有另存为私有
                2 私有另存为私有
                3 新增
             */
            // 检查私有是否存在同名平分规则
            ScoringRulesPO tmPo = scoringRulesService.querySelfOnly(scoringRulesPO.getRuleName(), AuthUtil.getCurrentUserId());
            if (ObjectUtil.isNotNull(tmPo)) {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "私有规则 " + tmPo.getRuleName() + " 已存在，请重新命名。");
            }
            scoringRulesService.saveScoringRules(scoringRulesPO);
        } else {
            /*
                修改保存
             */
            scoringRulesService.updateScoringRules(scoringRulesPO);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
    }

    //分享
    @PostMapping("/fxScoringRules")
    @PreAuthorize("@AuthorityCheck.admin()")
    public ResponseBodyVO<String> fxScoringRules(@RequestBody ScoringRulesParam params) {
        if (ObjectUtil.isNull(params.getRulesId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "参数 RulesId 不能为空，请检查", "");
        }
        ScoringRulesPO po = scoringRulesService.queryScoringRules(params);
        params.setShare("1");
        params.setRuleName(po.getRuleName());
        ScoringRulesPO tmPo = scoringRulesService.queryScoringRulesByRuleName(params);
        if (ObjectUtil.isNotNull(tmPo)) {
            po.setShare("1");
            po.setRulesId(tmPo.getRulesId());
            scoringRulesService.updateScoringRules(po);
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
        }
        po.setShare("1");
        scoringRulesService.saveScoringRules(po);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
    }


    /**
     * 删除打分规则
     *
     * @param params 参数
     * @return 结果
     */
    @PostMapping("/deleteScoringRules")
    public ResponseBodyVO<String> deleteScoringRules(@RequestBody ScoringRulesPO params) {
        scoringRulesService.deleteScoringRules(params);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
    }

    //测试包里面对应查询打分规则列表
    @PostMapping("/queryCsb")
    public ResponseBodyVO<List<ScoringRulesPO>> queryCsb() {
        ScoringRulesParam params = new ScoringRulesParam();
        params.setShare("0");
        List<ScoringRulesPO> list = scoringRulesService.queryScoringRulesListCSB(params);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, list);
    }

    //测试包里面对应查询打分规则列表
    @PostMapping("/queryCsbNew")
    public ResponseBodyVO<List<Map<String, Object>>> queryCsbNew() {
        ScoringRulesParam params = new ScoringRulesParam();
        params.setShare("0");
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, scoringRulesService.queryScoringRulesListCSBNew(params));
    }

    //该打分规则是否被引用
    @PostMapping("/queryCsbById")
    public ResponseBodyVO<Integer> queryCsbById(@RequestBody ScoringRulesParam params) {
        if (ObjectUtil.isNull(params.getRulesId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "rulesId 为空，请检查");
        }
        Integer num = scoringRulesService.queryCsbById(params);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, num);
    }


    /**
     * 新增场景评价规则
     */
    @PostMapping("/saveSceneEvaluationRule")
    public ResponseBodyVO<String> saveSceneEvaluationRule(@RequestParam(value = "file", required = false) MultipartFile file, @RequestPart("content") SceneEvaluationRulePO sceneEvaluationRulePO) {
        if (ObjectUtil.isNull(sceneEvaluationRulePO.getRuleName())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "参数 RulesName 不能为空，请检查");
        }
        return sceneEvaluationRuleService.uploadPyScriptAndSaveRule(file, sceneEvaluationRulePO);
    }


    /**
     * 新增场景评价规则支持传入路径
     */
    @PostMapping("/saveSceneEvaluationRuleByPath")
    public ResponseBodyVO<String> saveSceneEvaluationRule(@RequestBody SceneEvaluationRulePO sceneEvaluationRulePO, HttpServletRequest request) {
        if (ObjectUtil.isNull(sceneEvaluationRulePO.getRuleName())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "参数 RulesName 不能为空，请检查");
        }
        return sceneEvaluationRuleService.uploadPyScriptAndSaveRuleByPath(sceneEvaluationRulePO, request);
    }

    /**
     * 查询场景评分规则列表
     */
    @PostMapping("/querySceneEvaluationRuleList")
    public ResponseBodyVO<PageInfo<SceneEvaluationRuleVO>> querySceneEvaluationRuleList(@RequestBody SceneEvaluationRuleParam params) {
        PageUtil.setPageInfo(params);
        List<SceneEvaluationRulePO> list = sceneEvaluationRuleService.querySceneEvaluationRuleList(params);
        PageInfo<SceneEvaluationRulePO> sceneEvaluationRulePOPageInfo = new PageInfo<>(list);
        List<SceneEvaluationRuleVO> list1 = new ArrayList<>();
        // po 转 vo
        for (SceneEvaluationRulePO po : list) {
            SceneEvaluationRuleVO vo = new SceneEvaluationRuleVO();
            BeanUtils.copyProperties(po, vo);
            list1.add(vo);
        }
        PageInfo<SceneEvaluationRuleVO> pageInfo = new PageInfo<>(list1);
        pageInfo.setTotal(sceneEvaluationRulePOPageInfo.getTotal());
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
    }

    /**
     * 查询复杂度脚本
     */
    @PostMapping("/queryEvaluationScript")
    public ResponseBodyVO<Map<String, List<SceneEvaluationRuleVO>>> queryEvaluationScript(@RequestBody SceneEvaluationScriptParam sceneEvaluationScriptParam) {
        if (sceneEvaluationScriptParam.getSceneEvaluationType() == null || CollectionUtil.isEmpty(sceneEvaluationScriptParam.getSceneEvaluationType())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "请输入脚本类型");
        }
        List<SceneEvaluationRulePO> list = sceneEvaluationRuleService.queryEvaluationScript(sceneEvaluationScriptParam);
        Map<String, List<SceneEvaluationRuleVO>> stringSceneEvaluationRuleVOMap = new HashMap<>();

        // po 转 vo
        for (SceneEvaluationRulePO po : list) {
            stringSceneEvaluationRuleVOMap.computeIfAbsent(po.getRuleType(), k -> new ArrayList<>());
            SceneEvaluationRuleVO vo = new SceneEvaluationRuleVO();
            BeanUtils.copyProperties(po, vo);
            stringSceneEvaluationRuleVOMap.get(po.getRuleType()).add(vo);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, stringSceneEvaluationRuleVOMap);
    }

    /**
     * 删除场景评分规则
     */
    @PostMapping("/deleteSceneEvaluationRule")
    public ResponseBodyVO<String> deleteSceneEvaluationRule(@RequestBody SceneEvaluationRulePO params) {
        String roleCode = AuthUtil.getCurrentUserRoleCode();
        if (!DictConstants.ROLE_CODE_ADMIN.equals(roleCode) && !DictConstants.ROLE_CODE_SYSADMIN.equals(roleCode)) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "非管理员禁止删除");
        }
        sceneEvaluationRuleService.deleteSceneEvaluationRule(params);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
    }

    /**
     * 查询复杂度详情
     */
    @PostMapping("/querySceneEvaluationRiskDetail")
    public ResponseBodyVO<PageInfo<SceneRiskVO>> querySceneEvaluationRiskDetail(@RequestBody SceneEvaluationDetailParam params) {
        if (StringUtil.isEmpty(params.getSceneId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "请输入 sceneId");
        }
        PageUtil.setPageInfo(params);
        List<SceneRiskPO> list = sceneEvaluationRuleService.querySceneEvaluationRiskDetail(params);
        list.forEach(po -> po.setRiskLevel(SceneEvaluationEnum.matchLevelEnumByLevelValue(po.getRiskLevel())));
        PageInfo<SceneRiskPO> sceneRiskPOPageInfo = new PageInfo<>(list);
        List<SceneRiskVO> list1 = new ArrayList<>();
        // po 转 vo
        for (SceneRiskPO po : list) {
            SceneRiskVO vo = new SceneRiskVO();
            BeanUtils.copyProperties(po, vo);
            list1.add(vo);
        }
        PageInfo<SceneRiskVO> pageInfo = new PageInfo<>(list1);
        pageInfo.setTotal(sceneRiskPOPageInfo.getTotal());
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
    }

    /**
     * 查询危险度详情
     */
    @PostMapping("/querySceneEvaluationComplexityDetail")
    public ResponseBodyVO<PageInfo<SceneComplexityVO>> querySceneEvaluationComplexityDetail(@RequestBody SceneEvaluationDetailParam params) {
        if (StringUtil.isEmpty(params.getSceneId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "请输入 sceneId");
        }
        PageUtil.setPageInfo(params);
        List<SceneComplexityPO> list = sceneEvaluationRuleService.querySceneEvaluationComplexityDetail(params);
        list.forEach(po -> po.setComplexityLevel(SceneEvaluationEnum.matchLevelEnumByLevelValue(po.getComplexityLevel())));
        PageInfo<SceneComplexityPO> sceneComplexityPOPageInfo = new PageInfo<>(list);
        List<SceneComplexityVO> list1 = new ArrayList<>();
        // po 转 vo
        for (SceneComplexityPO po : list) {
            SceneComplexityVO vo = new SceneComplexityVO();
            BeanUtils.copyProperties(po, vo);
            list1.add(vo);
        }
        PageInfo<SceneComplexityVO> pageInfo = new PageInfo<>(list1);
        pageInfo.setTotal(sceneComplexityPOPageInfo.getTotal());
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
    }

    /**
     * 查询复杂度详情
     */
    @PostMapping("/querySceneEvaluationRiskDetailNoPage")
    public ResponseBodyVO<List<SceneRiskVO>> querySceneEvaluationRiskDetailNoPage(@RequestBody SceneEvaluationDetailParam params) {
        if (StringUtil.isEmpty(params.getSceneId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "请输入 sceneId");
        }
        List<SceneRiskPO> list = sceneEvaluationRuleService.querySceneEvaluationRiskDetail(params);
        list.forEach(po -> po.setRiskLevel(SceneEvaluationEnum.matchLevelEnumByLevelValue(po.getRiskLevel())));
        List<SceneRiskVO> list1 = new ArrayList<>();
        // po 转 vo
        for (SceneRiskPO po : list) {
            SceneRiskVO vo = new SceneRiskVO();
            BeanUtils.copyProperties(po, vo);
            list1.add(vo);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, list1);
    }

    /**
     * 查询危险度详情
     */
    @PostMapping("/querySceneEvaluationComplexityDetailNoPage")
    public ResponseBodyVO<List<SceneComplexityVO>> querySceneEvaluationComplexityDetailNoPage(@RequestBody SceneEvaluationDetailParam params) {
        if (StringUtil.isEmpty(params.getSceneId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "请输入 sceneId");
        }
        List<SceneComplexityPO> list = sceneEvaluationRuleService.querySceneEvaluationComplexityDetail(params);
        list.forEach(po -> po.setComplexityLevel(SceneEvaluationEnum.matchLevelEnumByLevelValue(po.getComplexityLevel())));
        List<SceneComplexityVO> list1 = new ArrayList<>();
        // po 转 vo
        for (SceneComplexityPO po : list) {
            SceneComplexityVO vo = new SceneComplexityVO();
            BeanUtils.copyProperties(po, vo);
            list1.add(vo);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, list1);
    }

}
