package com.css.simulation.resource.server.app.impl;

import api.common.pojo.common.ResponseBodyVO;
import api.common.pojo.constants.DictConstants;
import api.common.pojo.param.MinioParameter;
import api.common.pojo.param.algorithm.AlgorithmParameter;
import api.common.pojo.param.project.SimulationManualProjectParam;
import api.common.pojo.param.system.DictParam;
import api.common.pojo.po.algorithm.AlgorithmPO;
import api.common.pojo.vo.algorithm.AlgorithmVO;
import api.common.pojo.vo.algorithm.RunningProjectVO;
import api.common.util.*;
import com.css.simulation.resource.server.infra.feign.service.AlgoPlatformService;
import com.css.simulation.resource.server.infra.feign.service.FileDownService;
import com.css.simulation.resource.server.infra.feign.service.SchedulerService;
import com.css.simulation.resource.server.app.service.AlgorithmService;
import com.css.simulation.resource.server.app.service.DictService;
import com.css.simulation.resource.server.app.service.job_manage.SimulationProjectService;
import com.css.simulation.resource.server.domain.service.UserDomainService;
import com.css.simulation.resource.server.infra.git.GitConfiguration;
import com.css.simulation.resource.server.infra.util.AuthUtil;
import com.css.simulation.resource.server.infra.util.PageUtil;
import com.css.simulation.resource.server.infra.util.PoUtil;
import com.css.simulation.resource.server.infra.db.mysql.mapper.AlgorithmExpandMapper;
import com.css.simulation.resource.server.infra.db.mysql.mapper.AlgorithmMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Slf4j
@Service
public class AlgorithmServiceImpl implements AlgorithmService {

    @Resource
    private AlgoPlatformService algoPlatformService;
    @Resource
    private SchedulerService schedulerService;
    @Resource
    private FileDownService fileDownService;
    @Resource
    private AlgorithmMapper algorithmMapper;
    @Resource
    private DictService dictService;
    @Resource
    private GitConfiguration gitConfiguration;
    @Resource
    private AlgorithmExpandMapper algorithmExpandMapper;
    @Resource
    private UserDomainService userDomainService;

    @Resource
    private SimulationProjectService simulationProjectService;

    //* -------------------------------- Comment --------------------------------


    @Override
    @SneakyThrows
    public ResponseBodyVO<Object> addOrUpdate(AlgorithmParameter param) {
        String currentUserId = AuthUtil.getCurrentUserId();
        param.setCreateUserId(currentUserId);

        //* -------------------------------- 校验算法名称 --------------------------------
        // 公有另存为私有
        if (Objects.equals(DictConstants.IS_SHARED, param.getShare())) {
            // 设置 share 为 0
            // 设置创建人为当前用户
            param.setShare(DictConstants.IS_NOT_SHARED);
            param.setCreateUserId(AuthUtil.getCurrentUserId());
        }
        List<AlgorithmPO> algorithmPOS = algorithmMapper.selectAlgorithmName(param);
        if (CollectionUtil.isNotEmpty(algorithmPOS)) {
            throw new RuntimeException("该算法名称已存在。");
        }
        //* -------------------------------- comment --------------------------------
        String uploadMode = param.getUploadMode();
        if (DictConstants.FILE.equals(uploadMode)) {
            String minioPath = param.getMinioPath();
            ResponseBodyVO<String> checkRes = schedulerService.check(minioPath);
            if (ObjectUtil.isNull(checkRes)) {
                throw new RuntimeException("算法校验服务异常，请联系管理人员。");
            }
            if (!checkRes.isStatus()) { //校验失败
                MinioParameter minioParameter = new MinioParameter();
                minioParameter.setObjectName(minioPath);
                fileDownService.remove(minioParameter);
                throw new RuntimeException("该算法经校验不可用，无法保存。");
            }
        }
        return doAddOrUpdate(param);
    }

    private ResponseBodyVO<Object> doAddOrUpdate(AlgorithmParameter param) {
        if (isEmpty(param.getId())) {
            // 添加
            String algorithmId = StringUtil.getRandomUUID();
            param.setId(algorithmId);
            String algorithmCode = StringUtil.getRandomCode();
            param.setAlgorithmCode(algorithmCode);
            AlgorithmPO po = setPo(param, false);
            int add = algorithmMapper.add(po);
            if (add > 0) {
                LogUtil.insert();
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
            } else {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "添加失败");
            }
        } else {
            // 编辑
            AlgorithmPO po = setPo(param, true);
            int add = algorithmMapper.update(po);
            if (add > 0) {
                LogUtil.update();
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
            } else {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "编辑失败");
            }
        }

    }

    @Override
    public ResponseBodyVO<Object> selectAlgorithmList(AlgorithmParameter param) {
        param.setIsDeleted("0");
        param.setCreateUserId(AuthUtil.getCurrentUserId());
        PageUtil.setPageInfo(param);
        List<AlgorithmVO> vos = algorithmMapper.selectAlgorithmList(param);
        for (AlgorithmVO vo : vos) {
            vo.setValidationStatus(getDictName(DictConstants.VALIDATION_STATUS, vo.getValidationStatus()));
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, new PageInfo<>(vos));
    }

    @Override
    public ResponseBodyVO<Object> selectAlgoPlatformList(AlgorithmParameter param) {

        // 判断用户是否是管理员
        final boolean admin = userDomainService.isAdmin(AuthUtil.getCurrentUserId(), AuthUtil.getCurrentUserRoleCode());

        //1 同步算法平台数据到仿真云
//        final String algorithmId = param.getAlgorithmCode();
        final String algorithmName = param.getAlgorithmName();
        final String description = param.getDescription();
        final String algorithmVersion = param.getAlgorithmVersion();
        final String team = param.getTeam();
        final String topic = param.getTopic();
        final String status = param.getStatus();
        Integer page = param.getPageNum();
        Integer size = param.getPageSize();
        String sort = "";
        String urlParam = "";
//        if (StringUtil.isNotEmpty(algorithmId)) {
//            urlParam = urlParam + "&algorithmId=" + algorithmId;
//        }
        if (StringUtil.isNotEmpty(algorithmName)) {
            urlParam = urlParam + "&algorithmName=" + algorithmName;
        }
        if (StringUtil.isNotEmpty(description)) {
            urlParam = urlParam + "&description=" + description;
        }
        // 获取所有算法
        urlParam = urlParam + "&page=0&size=999999&sort=algorithmId-desc";
        // 此接口在此处只作为同步更新数据到仿真云数据库，分页查询通过仿真云数据库来查
        algoPlatformService.getAlgorithmList(urlParam);
        //2 查询仿真数据库里的数据
        PageHelper.startPage(page, size);
        final List<AlgorithmVO> algorithmVOS;
        if (admin) {
            algorithmVOS = algorithmExpandMapper.select(param);
            PageInfo<AlgorithmVO> objectPageInfo = new PageInfo<>(algorithmVOS);
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, objectPageInfo);
        } else {
            algorithmVOS = algorithmExpandMapper.selectWithNoTeam(param);
            PageInfo<AlgorithmVO> objectPageInfo = new PageInfo<>(algorithmVOS);
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, objectPageInfo);
        }

//        //解析数据
//        final String json = algorithmList.getInfo();
//        Map jsonMap = JsonUtil.jsonToMap(json);
//        if (CollectionUtil.isNotEmpty(jsonMap)) {
//            Map<String, Object> dataMap = (Map<String, Object>) jsonMap.get("data");
//            if (CollectionUtil.isNotEmpty(dataMap)) {
//                List<Map<String, String>> contentList = (List<Map<String, String>>) dataMap.get("content");
//                if (CollectionUtil.isNotEmpty(contentList)) {
//                    totalElements = (Integer) dataMap.get("totalElements");
//                    if (totalElements > 0) {
//                        for (Map<String, String> content : contentList) {
//                            AlgorithmVO vo = new AlgorithmVO();
//                            String id0 = content.get("id");
//                            String algorithmId0 = content.get("algorithmId");
//                            String algorithmName0 = content.get("algorithmName");
//                            String description0 = content.get("description");
//                            String evaluationName0 = content.get("evaluationName");
//                            String teamName0 = content.get("teamName");
//                            String match0 = content.get("match");
//                            vo.setId(id0);
//                            vo.setAlgorithmCode(algorithmId0);
//                            vo.setAlgorithmName(algorithmName0);
//                            vo.setDescription(description0);
//                            vo.setAlgorithmVersion(evaluationName0);
//                            vo.setTeam(teamName0);
//                            vo.setTopic(match0);
//                            vo.setStatus(algorithmExpandMapper.selectStatusByAlgorithmId(algorithmId0));
//                            vos.add(vo);
//                        }
//                    }
//                } else {
//                    log.info("算法列表接口返回值中的 data.content 字段为空：" + contentList);
//                }
//            } else {
//                log.info("算法列表接口返回值中的 data 字段为空：" + dataMap);
//            }
//        } else {
//            log.info("算法列表接口返回值为空：" + json);
//        }


    }


    @Override
    public ResponseBodyVO<Object> selectSharedAlgorithmList(AlgorithmParameter param) {
        param.setShare("1");
        PageUtil.setPageInfo(param);
        List<AlgorithmVO> vos = algorithmMapper.selectSharedAlgorithmList(param);
        for (AlgorithmVO vo : vos) {
            vo.setValidationStatus(getDictName(DictConstants.VALIDATION_STATUS, vo.getValidationStatus()));
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, new PageInfo<>(vos));
    }

    @Override
    public ResponseBodyVO<Object> shareAlgorithm(AlgorithmParameter param) {
        if (isEmpty(param.getId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
        } else {
            String algorithmId = param.getId();
            AlgorithmPO po = algorithmMapper.selectDetailsById(algorithmId);
            List<AlgorithmPO> algorithmPOS = algorithmMapper.selectSharedAlgorithmName(po.getAlgorithmName());
            if (algorithmPOS != null && algorithmPOS.size() > 0) {
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "该算法名称已存在, 无法分享！", null);
            } else {
                po.setShare("1");
                po.setId(StringUtil.getRandomUUID());
                po.setAlgorithmCode(StringUtil.getRandomCode());
                int add = algorithmMapper.add(po);
                if (add > 0) {
                    LogUtil.share();
                    return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, "分享成功", null);
                }
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SERVER_FAILURE, "分享失败", null);

            }
        }
    }

    @Override
    public ResponseBodyVO<String> testConnection(AlgorithmParameter param) {
        final String gitUrl = param.getGitUrl().replace(gitConfiguration.getName(), gitConfiguration.getUrl());
        final String gitUserName = param.getGitUserName();
        final String gitPassword = param.getGitPassword();
        if (StringUtil.isEmpty(gitUserName) && StringUtil.isEmpty(gitPassword)) {
            JgitUtil.testPublicConnection(gitUrl);
        } else if (StringUtil.isNotEmpty(gitUserName) && StringUtil.isNotEmpty(gitPassword)) {
            JgitUtil.testPrivateConnection(gitUrl, gitUserName, gitPassword);
        } else {
            JgitUtil.testPublicConnection(gitUrl);
            JgitUtil.testPrivateConnection(gitUrl, gitUserName, gitPassword);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
    }

    @Override
    public String getGitVersion(String algorithmId) {
        AlgorithmPO algorithmPO = algorithmMapper.selectDetailsById(algorithmId);
        String gitUrl = algorithmPO.getGitUrl();
        String replace = gitUrl.replace(gitConfiguration.getName(), gitConfiguration.getUrl());
        String gitUserName = algorithmPO.getGitUserName();
        String gitPassword = algorithmPO.getGitPassword();
        return String.valueOf(GitLabUtil.getLastCommitTimestamp(replace, gitUserName, gitPassword));
    }

    @Override
    public ResponseBodyVO<String> deleteById(AlgorithmParameter param) {
        if (isEmpty(param.getId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
        }
        String algorithmId = param.getId();
        // 查询算法相关的正在运行的项目
        List<RunningProjectVO> runningProjectVos = algorithmMapper.selectRunningProject(algorithmId);
        if (runningProjectVos != null && runningProjectVos.size() > 0) {
            StringBuilder stringBuilder = new StringBuilder();
            for (RunningProjectVO vo : runningProjectVos) {
                // 删除算法将停止所有使用该算法的正在运行中的工作项目
                // 子项目
                SimulationManualProjectParam voparam = new SimulationManualProjectParam();
                voparam.setId(vo.getId());
                voparam.setNowRunState(DictConstants.PROJECT_TERMINATED);
                simulationProjectService.updateProjectNowRunState(voparam);
            }

            // 停用所有父项目
            List<RunningProjectVO> runningParentProjectVos = algorithmMapper.selectRunningProjectParent(algorithmId);
            if (runningParentProjectVos != null && runningParentProjectVos.size() > 0) {
                for (RunningProjectVO voParent : runningParentProjectVos) {
                    SimulationManualProjectParam voParamParent = new SimulationManualProjectParam();
                    stringBuilder.append(voParent.getProjectId()).append(",");
                    voParamParent.setId(voParent.getId());
                    voParamParent.setAutomaticRunState("1");
                    simulationProjectService.updateAutomaticRunState(voParamParent);
                }
            }
            String substring = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
        }
        algorithmMapper.deleteById(algorithmId);
        LogUtil.delete();
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);

    }

    @Override
    public ResponseBodyVO<Map<String, String>> deleteCheck(AlgorithmParameter param) {
        if (isEmpty(param.getId())) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
        } else {
            Map<String, String> map = new HashMap<>();
            String algorithmId = param.getId();
            List<RunningProjectVO> runningParentProjectVos = algorithmMapper.selectAutoProjectIdByAlgorithmId(algorithmId);
            if (runningParentProjectVos != null && runningParentProjectVos.size() > 0) {
                StringBuilder stringBuilder = new StringBuilder();
                for (RunningProjectVO voParent : runningParentProjectVos) {
                    stringBuilder.append(voParent.getProjectId()).append(",");
                }
                String substring = stringBuilder.substring(0, stringBuilder.lastIndexOf(","));
                map.put("substring", substring);
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, "该算法已绑定 ID 为 " + substring + " 的自动运行项目，删除后该项目将停止自动运行。", map);
            } else {
                map.put("substring", "");
                return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, "该算法未绑定自动运行项目。", map);
            }
        }
    }

    @Override
    public ResponseBodyVO<Object> selectDetailsById(String algorithmId) {
        if (isEmpty(algorithmId)) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
        } else {
            AlgorithmPO po = algorithmMapper.selectDetailsById(algorithmId);
            po.setValidationStatus(getDictName(DictConstants.VALIDATION_STATUS, po.getValidationStatus()));
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, po);
        }

    }


    private boolean isEmpty(String value) {
        if (value == null) {
            return true;
        }
        value = value.trim();
        return value.length() == 0;
    }


    private AlgorithmPO setPo(AlgorithmParameter param, Boolean isEdit) {

        AlgorithmPO po = new AlgorithmPO();
        //设置po信息
        if (DictConstants.GIT.equals(param.getUploadMode())) { //使用仓库地址上传
            String gitUrl = param.getGitUrl();
            String gitUserName = param.getGitUserName();
            String gitPassword = param.getGitPassword();
            po.setGitUrl(gitUrl);
            po.setGitUserName(gitUserName);
            po.setGitPassword(gitPassword);
        } else {
            String minioPath = param.getMinioPath();
            String[] splits = minioPath.split("/");
            String fileName = splits[splits.length - 1];
            po.setMinioPath(param.getMinioPath());
            po.setFileName(fileName);
        }
        po.setAlgorithmCode(param.getAlgorithmCode());
        po.setAlgorithmName(param.getAlgorithmName());
        po.setDescription(param.getDescription());
        po.setUploadMode(param.getUploadMode());
        po.setValidationStatus(DictConstants.SUCCESS);
        po.setShare(DictConstants.NO);
        po.setId(param.getId());

        if (isEdit) {
            PoUtil.initUpdatePo(po);
        } else {
            PoUtil.initAddPo(po);
        }
        return po;

    }

    private String getDictName(String type, String code) {
        DictParam dictParam = new DictParam();
        dictParam.setDictTypes(type);
        Map<String, Map<String, String>> dictMapsByTypes = dictService.getDictMapsByTypes(dictParam);
        Map<String, String> stringStringMap = dictMapsByTypes.get(type);
        if (stringStringMap != null && stringStringMap.size() > 0) {
            return stringStringMap.get(code);
        }
        return "";
    }

    @Override
    public Map<String, String> selectDetailsBySy() {
        AlgorithmParameter param = new AlgorithmParameter();
        param.setUploadMode("1");
        param.setShare("0");
        param.setCreateUserId(AuthUtil.getCurrentUserId());
        int fileNum = algorithmMapper.selectDetailsBySy(param);
        param.setUploadMode("2");
        int pathNum = algorithmMapper.selectDetailsBySy(param);
        Map<String, String> map = new HashMap<>();
        map.put("fileNum", fileNum + "");
        map.put("pathNum", pathNum + "");
        return map;
    }

}
