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

import api.common.pojo.common.PageVO;
import api.common.pojo.common.ResponseBodyVO;
import api.common.pojo.constants.DictConstants;
import api.common.pojo.enums.MultiSimulationStatusEnum;
import api.common.pojo.param.map.SimulationMapParam;
import api.common.pojo.param.map.SimulationMapPathParam;
import api.common.pojo.param.project.MultiSimulationProjectParam;
import api.common.pojo.param.project.MultiSimulationSceneCarParam;
import api.common.pojo.param.project.MultiSimulationSceneParam;
import api.common.pojo.po.algorithm.AlgorithmPO;
import api.common.pojo.po.map.SimulationMapPO;
import api.common.pojo.po.map.SimulationMapPathPO;
import api.common.pojo.po.model.ConfigPO;
import api.common.pojo.po.project.MultiSimulationProjectPO;
import api.common.pojo.po.project.MultiSimulationScenePO;
import api.common.pojo.vo.map.SimulationMapPathVO;
import api.common.pojo.vo.map.SimulationMapVO;
import api.common.pojo.vo.project.MultiSimulationProjectDetailVO;
import api.common.pojo.vo.project.MultiSimulationProjectVO;
import api.common.pojo.vo.project.MultiSimulationSceneCarVO;
import api.common.pojo.vo.project.MultiSimulationSceneVO;
import api.common.util.StringUtil;
import api.common.util.TimeUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.css.simulation.resource.server.app.service.job_manage.MultiSimulationProjectService;
import com.css.simulation.resource.server.app.service.job_manage.SimulationMapService;
import com.css.simulation.resource.server.infra.db.mysql.mapper.*;
import com.css.simulation.resource.server.infra.feign.service.FileDownService;
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.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class SimulationMapServiceImpl implements SimulationMapService {

    @Resource
    private SimulationMapMapper mapMapper;

    @Resource
    private FileDownService fileDownService;
    
    @Resource
    private SimulationMapPathMapper mapPathMapper;
    @Override
    @SneakyThrows
    public ResponseBodyVO<PageInfo<SimulationMapVO>> selectMultiSimulationMap(SimulationMapParam param){
        if (Objects.isNull(param.getPageNum())){
            param.setPageNum(1);
        }
        if (Objects.isNull(param.getPageSize())){
            param.setPageSize(10);
        }
        if (StringUtils.isBlank(param.getMapName())){
            param.setMapName(null);
        }
        if (StringUtils.isBlank(param.getMapDescription())){
            param.setMapDescription(null);
        }
        setPage(param.getPageNum(), param.getPageSize());
        List<SimulationMapVO> simulationMapVOS = mapMapper.selectSimulationMapList(param);
        PageInfo<SimulationMapVO> pageInfo = new PageInfo<>(simulationMapVOS);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, pageInfo);
    }

    @Override
    @SneakyThrows
    public ResponseBodyVO<List<SimulationMapVO>> selectAllSimulationMapList(SimulationMapParam param){
        List<SimulationMapVO> simulationMapVOS = mapMapper.selectSimulationMapList(param);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, simulationMapVOS);
    }

    @Override
    @SneakyThrows
    public ResponseBodyVO<SimulationMapVO> getSimulationMap(SimulationMapParam param){
        if (StringUtils.isBlank(param.getMapId())){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "地图id为空");
        }
        SimulationMapVO simulationMapVO = mapMapper.selectMapByMapId(param.getMapId());
        if (Objects.isNull(simulationMapVO)){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "未找到有效的id");
        }
        String mapPath = simulationMapVO.getMapPath();
        ResponseBodyVO<String> publicUrl = fileDownService.getPublicUrl(mapPath);
        if (publicUrl.isStatus()){
            simulationMapVO.setMapPath(publicUrl.getInfo());
        }
        String mapOsgbPath = simulationMapVO.getMapOsgbPath();
        ResponseBodyVO<String> osUrl = fileDownService.getPublicUrl(mapOsgbPath);
        if (osUrl.isStatus()){
            simulationMapVO.setMapOsgbPath(osUrl.getInfo());
        }
        
        SimulationMapPathParam simulationMapPathParam = new SimulationMapPathParam();
        simulationMapPathParam.setMapId(param.getMapId());
        List<SimulationMapPathVO> simulationMapPathPOS = mapPathMapper.selectSimulationMapPathList(simulationMapPathParam);
        if (CollectionUtils.isEmpty(simulationMapPathPOS)){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "查询地图详情失败");
        }
        for (SimulationMapPathVO pathDetail: simulationMapPathPOS) {
            String pathStartPoint = pathDetail.getPathStartPoint();
            String pathEndPoint = pathDetail.getPathEndPoint();
            String section = pathDetail.getPathDetail();
            List<JSONObject> startArr = new ArrayList<>();
            List<JSONObject> endArr = new ArrayList<>();
            List<JSONObject> pathDetailArr = new ArrayList<>();
            JSONArray arrayStart = JSONArray.parseArray(pathStartPoint);
            JSONArray arrayEnd = JSONArray.parseArray(pathEndPoint);
            JSONArray array = JSONArray.parseArray(section);
            for (int i = 0; i < arrayStart.size(); i++) {
                startArr.add(arrayStart.getJSONObject(i));
            }
            for (int i = 0; i < arrayEnd.size(); i++) {
                endArr.add(arrayEnd.getJSONObject(i));
            }
            for (int i = 0; i < array.size(); i++) {
                pathDetailArr.add(array.getJSONObject(i));
            }
            pathDetail.setStartPoints(startArr);
            pathDetail.setEndPoints(endArr);
            pathDetail.setSections(pathDetailArr);
        }
        simulationMapVO.setPath(simulationMapPathPOS);
        simulationMapVO.setMapJsonPathNum(simulationMapPathPOS.size());
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS,  simulationMapVO);
    }


    public ResponseBodyVO updateSimulationMap(SimulationMapParam param){
        String currentUserRoleCode = AuthUtil.getCurrentUserRoleCode();
        if (!StringUtils.equals(DictConstants.ROLE_CODE_ADMIN, currentUserRoleCode) && !StringUtils.equals(DictConstants.ROLE_CODE_SYSADMIN, currentUserRoleCode)){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "当前用户无该权限");
        }
        if (StringUtils.isBlank(param.getMapId())){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "地图id为空");
        }
        if (Objects.isNull(param.getPathNum())){
            param.setPathNum(0);
        }
        if (StringUtils.isBlank(param.getMapDescription())){
            param.setMapDescription("");
        }
        int i = mapMapper.updateMultiSimulationScene(param);
        if (i > 0){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);

    }
    public ResponseBodyVO deleteSimulationMap(SimulationMapParam param){
        String currentUserRoleCode = AuthUtil.getCurrentUserRoleCode();
        if (!StringUtils.equals(DictConstants.ROLE_CODE_ADMIN, currentUserRoleCode) && !StringUtils.equals(DictConstants.ROLE_CODE_SYSADMIN, currentUserRoleCode)){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "当前用户无该权限");
        }
        if (StringUtils.isBlank(param.getMapId())){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "地图id为空");
        }
        int i = mapMapper.deleteMultiSimulationScene(param);
        if (i > 0){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
        }
        return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
    }

    @SneakyThrows
    @Transactional
    public ResponseBodyVO uploadSimulationMap(MultipartFile fileJson, MultipartFile fileOsgb, MultipartFile fileDriver, SimulationMapParam param){
        String currentUserRoleCode = AuthUtil.getCurrentUserRoleCode();
        if (!StringUtils.equals(DictConstants.ROLE_CODE_ADMIN, currentUserRoleCode) && !StringUtils.equals(DictConstants.ROLE_CODE_SYSADMIN, currentUserRoleCode)){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "当前用户无该权限");
        }
        String mapName = param.getMapName();
        String mapJson = new String(fileJson.getBytes(), StandardCharsets.UTF_8);
        if (StringUtils.isBlank(mapJson) || param.getPathNum() == null || StringUtils.isBlank(mapName)){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
        }
        // map.json文件
        JSONObject object = JSONObject.parseObject(mapJson);
        String originName = fileDriver.getOriginalFilename();
        if (null == originName) {
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "文件名为空，请检查！");
        }
        String fileName = originName.substring(0, originName.lastIndexOf("."));
        Integer nowTime = TimeUtil.getRq(new Date(), 0);
        String randomCode = StringUtil.getRandomCode();
        String fileType = originName.substring(originName.lastIndexOf("."));
        fileName = "/" + DictConstants.MAP_DRIVER_FILE + "/" + nowTime + "/" + randomCode + "/" + fileName + fileType;
        ResponseBodyVO<String> response = fileDownService.upload(fileDriver, fileName);
        if (!response.isStatus()){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "上传失败");
        }
        String previewUrl = response.getInfo();
        String mapUrl = previewUrl.substring(previewUrl.indexOf("/" + DictConstants.MAP_DRIVER_FILE), previewUrl.indexOf("?"));

        String osgbFileName = fileOsgb.getOriginalFilename();
        if (osgbFileName == null){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "文件名为空，请检查！");
        }
        fileName = "/" + DictConstants.MAP_DRIVER_FILE + "/" + nowTime + "/" + randomCode + "/" + osgbFileName;
        ResponseBodyVO<String> responseOs = fileDownService.upload(fileDriver, fileName);
        if (!responseOs.isStatus()){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "上传失败");
        }
        String osUrl = responseOs.getInfo();
        String osMinioUrl = osUrl.substring(osUrl.indexOf("/" + DictConstants.MAP_DRIVER_FILE), osUrl.indexOf("?"));

        SimulationMapPO simulationMapPO = new SimulationMapPO();
        simulationMapPO.setMapPath(mapUrl).setMapOsgbPath(osMinioUrl).setMapName(param.getMapName()).setMapDescription(param.getMapDescription())
            .setMapJson(object.toJSONString()).setPathNum(param.getPathNum()).setMapCode("").setId(StringUtil.getRandomUUID());
        int i = mapMapper.addSimulationMap(simulationMapPO);
        if (i <= 0){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "添加失败");
        }
        String mapPOId = simulationMapPO.getId();
        JSONArray jsonArray = object.getJSONArray("path");
        if (jsonArray ==null || jsonArray.size() == 0){
            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "未解析出详细轨迹");
        }
        for (int j = 0; j < jsonArray.size(); j++) {
            JSONObject jsonObject = jsonArray.getJSONObject(j);
            SimulationMapPathPO simulationMapPathPO = new SimulationMapPathPO();
            simulationMapPathPO.setId(StringUtil.getRandomUUID()).setMapId(mapPOId)
                .setPathSort(jsonObject.getInteger("pathId")).setPathDetail(jsonObject.getJSONArray("sections").toJSONString())
                .setStartPointNum(jsonObject.getInteger("numOfStartPoints")).setPathStartPoint(jsonObject.getJSONArray("startPoints").toJSONString())
                .setEndPointNum(jsonObject.getInteger("numOfEndPoints")).setPathEndPoint(jsonObject.getJSONArray("endPoints").toJSONString());
            int i1 = mapPathMapper.addSimulationMap(simulationMapPathPO);
            if (i1 <= 0){
                throw new RuntimeException("处理地图详情失败");
            }
        }
        SimulationMapVO simulationMapVO = new SimulationMapVO();
        simulationMapVO.setMapId(mapPOId);
        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS, simulationMapVO);
    }
    private void setPage(Integer pageNum, Integer pageSize) {
        PageVO pageVO = new PageVO();
        pageVO.setCurrentPage(pageNum);
        pageVO.setPageSize(pageSize);
        PageUtil.setPageInfo(pageVO);
    }
}
