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

import api.common.pojo.constants.DictConstants;
import api.common.pojo.param.model.*;
import api.common.pojo.po.model.*;
import api.common.pojo.vo.model.*;
import api.common.util.*;
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.db.mysql.mapper.ConfigMapper;
import com.css.simulation.resource.server.infra.db.mysql.mapper.ModelConfigMapper;
import com.css.simulation.resource.server.infra.db.mysql.mapper.RelationConfigSensorMapper;
import com.css.simulation.resource.server.infra.db.mysql.mapper.VehicleMapper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.buf.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ConfigService {

    @Resource
    private ConfigMapper configMapper;
    @Resource
    private VehicleMapper vehicleMapper;
    @Resource
    private VehicleService vehicleService;
    @Resource
    private CameraService cameraService;
    @Resource
    private LidarService lidarService;
    @Resource
    private OgtService ogtService;
    @Resource
    private GpsService gpsService;
    @Resource
    private RelationConfigSensorMapper relationConfigSensorMapper;
    @Resource
    private ModelConfigMapper modelConfigMapper;

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

    /**
     * 获取车辆配置列表
     */
    public PageInfo<ConfigVO> getConfigPageList(ConfigPageParam pageParam) {
        PageUtil.setPageInfo(pageParam);
        pageParam.setCreateUserId(AuthUtil.getCurrentUserId());

        // 私有查询需获取当前人 userId
        if (DictConstants.IS_NOT_SHARED.equals(pageParam.getShare())) {
            pageParam.setCreateUserId(AuthUtil.getCurrentUserId());
        }
        // 公有查询不需要当前人 userId
        if (DictConstants.IS_SHARED.equals(pageParam.getShare())) {
            pageParam.setCreateUserId(null);
        }
        List<ConfigVO> list = configMapper.getConfigPageList(pageParam);    // 查询《配置-传感器关系表》
        list.forEach(configVO -> {
            List<ConfigSensorVO> sensorList = configMapper.getConfigSensors(configVO);  // 根据配置 id 获取传感器列表
            Map<String, List<ConfigSensorVO>> configSensors = sensorList.stream().collect(Collectors.groupingBy(ConfigSensorVO::getSensorType));
            Map<String, String> sensorCount = new HashMap<>();
            configSensors.forEach((sensorType, configSensorVOs) -> sensorCount.put(sensorType, String.valueOf(configSensorVOs.size())));
            configVO.setSensorCount(sensorCount);
        });
        return new PageInfo<>(list);
    }

    public ConfigVO getConfigInfo(ConfigVO configVO) {
        configVO = configMapper.getConfigInfo(configVO);
        List<ConfigSensorVO> sensorList = configMapper.getConfigSensors(configVO);
        Map<String, List<ConfigSensorVO>> configSensors = sensorList.stream().collect(Collectors.groupingBy(ConfigSensorVO::getSensorType));
        configVO.setConfigSensors(configSensors);
        if (ObjectUtil.isNotNull(configVO.getVehicleArray())) {
            configVO.setVehicleArrayS(configVO.getVehicleArray().split(","));
        }
        return configVO;
    }
    public ConfigVO getConfigInfoNew(ConfigVO configVO) {
        configVO = configMapper.getConfigInfo(configVO);
        List<ConfigSensorVO> sensorList = configMapper.getConfigSensors(configVO);
        for (ConfigSensorVO vo:sensorList) {
            if(vo.getShare().equals("0")){
                vo.setSensorName("私有/"+vo.getSensorName());
            }else if(vo.getShare().equals("1")){
                vo.setSensorName("公有/"+vo.getSensorName());
            }
        }
        Map<String, List<ConfigSensorVO>> configSensors = sensorList.stream().collect(Collectors.groupingBy(ConfigSensorVO::getSensorType));
        configVO.setConfigSensors(configSensors);
        if (ObjectUtil.isNotNull(configVO.getVehicleArray())) {
            configVO.setVehicleArrayS(configVO.getVehicleArray().split(","));
        }
        return configVO;
    }

    public ConfigPO saveConfig(ConfigVO configVO) {
        // 构建主表对象
        ConfigPO configPO = new ConfigPO();
        String currentUserId = AuthUtil.getCurrentUserId();
        Timestamp currentTime = TimeUtil.getNowForMysql();
        // vo 转 po
        ObjectUtil.voToPo(configVO, configPO);
        configPO.setCreateUserId(currentUserId);
        configPO.setCreateTime(currentTime);
        configPO.setModifyUserId(currentUserId);
        configPO.setModifyTime(currentTime);
        configPO.setIsDeleted(DictConstants.NO);
        configPO.setShare(DictConstants.NO);//私有
        if (ObjectUtil.isNotNull(configVO.getVehicleArrayS())) {
            configPO.setVehicleArray(StringUtils.join(Arrays.asList(configVO.getVehicleArrayS()), ','));
        }
        //单独处理配置描述
        configPO.setDescription(configVO.getConfigDescription());
        //名称校验
        List<ConfigVO> list = configMapper.checkConfigName(configPO);
        if (ObjectUtil.isNotNull(list)) {
            configPO.setId(null);
            return configPO;
        }
        //主表主键
        String configId = configPO.getId();
        if (ObjectUtil.isNull(configId)) {//新增
            configId = StringUtil.getRandomUUID();
            configPO.setId(configId);
            configPO.setConfigCode(StringUtil.getRandomCode());
            configMapper.insertConfig(configPO);
            LogUtil.insert();
        } else {//修改
            configMapper.updateConfig(configPO);
            LogUtil.update();
        }
        //删除子表旧数据
        configMapper.delConfigSensors(configPO);
        //构建字表新数据
        //List<ConfigSensorVO> configSensorVOs = configVO.getConfigSensors();
        Map<String, List<ConfigSensorVO>> configSensors = configVO.getConfigSensors();
        List<ConfigSensorPO> configSensorPOs = new ArrayList<>();
        if (ObjectUtil.isNotNull(configSensors)) {
            configSensors.forEach((sensorType, configSensorVOs) -> {
                if (ObjectUtil.isNotNull(configSensorVOs)) {
                    configSensorVOs.forEach(vo -> {
                        ConfigSensorPO po = new ConfigSensorPO();
                        ObjectUtil.voToPo(vo, po);
                        po.setId(StringUtil.getRandomUUID());
                        //子表外键
                        po.setConfigId(configPO.getId());
                        po.setCreateUserId(currentUserId);
                        po.setCreateTime(currentTime);
                        po.setModifyUserId(currentUserId);
                        po.setModifyTime(currentTime);
                        po.setIsDeleted(DictConstants.NO);
                        configSensorPOs.add(po);
                    });
                }
            });
        }
        if (ObjectUtil.isNotNull(configSensorPOs)) {
            configMapper.insertConfigSensors(configSensorPOs);
        }
        return configPO;
    }

    public ConfigPO saveAnotherConfig(ConfigVO configVO) {
        //构建主表对象
        ConfigPO configPO = new ConfigPO();
        String currentUserId = AuthUtil.getCurrentUserId();
        Timestamp currentTime = TimeUtil.getNowForMysql();
        ObjectUtil.voToPo(configVO, configPO);
        configPO.setCreateUserId(currentUserId);
        configPO.setCreateTime(currentTime);
        configPO.setModifyUserId(currentUserId);
        configPO.setModifyTime(currentTime);
        configPO.setIsDeleted(DictConstants.NO);
        configPO.setShare(DictConstants.NO);//私有
        //新增公私有展示
        if (ObjectUtil.isNotNull(configVO.getVehicleArrayS())) {
            configPO.setVehicleArray(StringUtils.join(Arrays.asList(configVO.getVehicleArrayS()), ','));
        }
        //单独处理配置描述
        configPO.setDescription(configVO.getConfigDescription());
        //名称校验
        List<ConfigVO> list = configMapper.checkConfigName(configPO);
        if (ObjectUtil.isNotNull(list)) {
            configMapper.updateConfig(configPO);
            LogUtil.update();
        } else {
            //主表主键
            String configId = configPO.getId();
            configId = StringUtil.getRandomUUID();
            configPO.setId(configId);
            configPO.setConfigCode(StringUtil.getRandomCode());
            configMapper.insertConfig(configPO);
            LogUtil.insert();
        }

        //删除子表旧数据
        configMapper.delConfigSensors(configPO);
        //构建字表新数据
        //List<ConfigSensorVO> configSensorVOs = configVO.getConfigSensors();
        Map<String, List<ConfigSensorVO>> configSensors = configVO.getConfigSensors();
        List<ConfigSensorPO> configSensorPOs = new ArrayList<>();
        if (ObjectUtil.isNotNull(configSensors)) {
            configSensors.forEach((sensorType, configSensorVOs) -> {
                if (ObjectUtil.isNotNull(configSensorVOs)) {
                    configSensorVOs.forEach(vo -> {
                        ConfigSensorPO po = new ConfigSensorPO();
                        ObjectUtil.voToPo(vo, po);
                        po.setId(StringUtil.getRandomUUID());
                        //子表外键
                        po.setConfigId(configPO.getId());
                        po.setCreateUserId(currentUserId);
                        po.setCreateTime(currentTime);
                        po.setModifyUserId(currentUserId);
                        po.setModifyTime(currentTime);
                        po.setIsDeleted(DictConstants.NO);
                        configSensorPOs.add(po);
                    });
                }
            });
        }
        if (ObjectUtil.isNotNull(configSensorPOs)) {
            configMapper.insertConfigSensors(configSensorPOs);
        }
        return configPO;
    }

    public int delConfigById(ConfigVO vo) {
        ConfigPO po = new ConfigPO();
        ObjectUtil.voToPo(vo, po);
        po.setIsDeleted(DictConstants.YES);
        po.setModifyUserId(AuthUtil.getCurrentUserId());
        po.setModifyTime(TimeUtil.getNowForMysql());
        int i = configMapper.delConfigById(po);
        LogUtil.delete();
        return i;
    }

    public ConfigPO shareConfigByInfo(ConfigVO configVO) {

        final String isUnavailable = modelConfigMapper.selectIsUnavailableByModelConfigId(configVO.getId());
        if (DictConstants.IS_UNAVAILABLE.equals(isUnavailable)) {
            throw new RuntimeException("车辆配置处于禁用状态，请编辑后重试。");
        }

        // 构建新的车辆配置对象
        ConfigPO configPO = new ConfigPO();
        ObjectUtil.voToPo(configVO, configPO);
        configPO.setDescription(configVO.getConfigDescription());   // 私有转公有
        configPO.setShare(DictConstants.IS_SHARED);   // 私有转公有
        configPO.setCreateUserId(null);

        String currentUserId = AuthUtil.getCurrentUserId();
        Timestamp currentTime = TimeUtil.getNowForMysql();
        // 车辆配置名称相同则覆盖，名称不同则新增
        // 车辆模型名称相同则覆盖，名称不同则新增
        // 传感器模型名称相同则覆盖，名称不同则新增

        // 复制车辆表旧数据
        String vehicleId = null;
        if (configPO.getVehicleId() != null) {
            VehicleParam vehicleParam = new VehicleParam();
            vehicleParam.setId(configPO.getVehicleId());
            VehicleVO vehicleInfo = vehicleMapper.getVehicleInfo(vehicleParam);
            if (ObjectUtil.isNotNull(vehicleInfo.getVehicleTypeStr())) {
                vehicleInfo.setVehicleType(vehicleInfo.getVehicleTypeStr().split(","));
            }
            VehiclePO vehiclePO = vehicleService.shareVehicle(vehicleInfo);
            vehicleId = vehiclePO.getId();
        }

        // 复制传感器表数据
        Map<String, List<ConfigSensorVO>> configSensors = configVO.getConfigSensors();
        log.info("该车辆配置的所有传感器信息为：" + configSensors);
        List<ConfigSensorPO> configSensorPOs = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(configSensors)) {
            configSensors.forEach((sensorType, configSensorVOs) -> {

                if (ObjectUtil.isNotNull(configSensorVOs)) {
                    configSensorVOs.forEach(vo -> {
                        ConfigSensorPO po = new ConfigSensorPO();
                        ObjectUtil.voToPo(vo, po);
                        po.setId(StringUtil.getRandomUUID());
                        // 子表外键
                        po.setConfigId(configPO.getId());
                        po.setCreateUserId(currentUserId);
                        po.setCreateTime(currentTime);
                        po.setModifyUserId(currentUserId);
                        po.setModifyTime(currentTime);
                        po.setIsDeleted(DictConstants.NO);
                        String sensorId = "";
                        if (DictConstants.SENSOR_CAMERA.equals(sensorType)) {
                            CameraParam cameraParam = new CameraParam();
                            cameraParam.setId(vo.getSensorId());
                            CameraVO cameraVO = cameraService.getCameraInfo(cameraParam);
                            CameraPO cameraPO = new CameraPO();
                            ObjectUtil.voToPo(cameraVO, cameraPO);
                            CameraPO publicCamera = cameraService.shareCamera(cameraPO);
                            sensorId = publicCamera.getId();
                        } else if (DictConstants.SENSOR_LIDAR.equals(sensorType)) {
                            LidarParam lidarParam = new LidarParam();
                            lidarParam.setId(vo.getSensorId());
                            LidarVO lidarVO = lidarService.getLidarInfo(lidarParam);
                            LidarPO lidarPO = new LidarPO();
                            ObjectUtil.voToPo(lidarVO, lidarPO);
                            LidarPO publicLidar = lidarService.shareLidar(lidarPO);
                            sensorId = publicLidar.getId();
                        } else if (DictConstants.SENSOR_OGT.equals(sensorType)) {
                            OgtParam ogtParam = new OgtParam();
                            ogtParam.setId(vo.getSensorId());
                            OgtVO ogtVO = ogtService.getOgtInfo(ogtParam);
                            OgtPO ogtPO = new OgtPO();
                            ObjectUtil.voToPo(ogtVO, ogtPO);
                            OgtPO publicOgt = ogtService.shareOgt(ogtPO);
                            sensorId = publicOgt.getId();
                        } else if (DictConstants.SENSOR_GPS.equals(sensorType)) {
                            GpsParam gpsParam = new GpsParam();
                            gpsParam.setId(vo.getSensorId());
                            GpsVO gpsVO = gpsService.getGpsInfo(gpsParam);
                            GpsPO gpsPO = new GpsPO();
                            ObjectUtil.voToPo(gpsVO, gpsPO);
                            GpsPO publicGps = gpsService.shareGps(gpsPO);
                            sensorId = publicGps.getId();
                        } else {
                            throw new RuntimeException("传感器类型错误。");
                        }
                        po.setSensorId(sensorId);
                        configSensorPOs.add(po);
                    });
                }
            });
        }

        final String publicConfigId;

        List<ConfigVO> list = configMapper.checkConfigName(configPO);   // 查询公有车辆配置是否有重名
        if (ObjectUtil.isNotNull(list)) {   // 不为空说明有重名，则将参数覆盖
            configPO.setVehicleId(vehicleId);   // 关联车辆id修改成公有车辆id
            ConfigVO configVO2 = list.get(0);
            publicConfigId = configVO2.getId();
            configPO.setId(publicConfigId);
            configPO.setModifyUserId(currentUserId);
            configPO.setModifyTime(currentTime);
            configPO.setIsDeleted(DictConstants.NO);
            //新增公私有展示
            if (ObjectUtil.isNotNull(configVO.getVehicleArrayS())) {
                configPO.setVehicleArray(StringUtils.join(Arrays.asList(configVO.getVehicleArrayS()), ','));
            }
            configMapper.updateConfig(configPO);
            LogUtil.update();
        } else {    // 为空说明是新增
            configPO.setVehicleId(vehicleId);   // 关联车辆id修改成公有车辆id
            configPO.setCreateUserId(currentUserId);
            configPO.setCreateTime(currentTime);
            configPO.setModifyUserId(currentUserId);
            configPO.setModifyTime(currentTime);
            configPO.setIsDeleted(DictConstants.NO);
            //新增公私有展示
            if (ObjectUtil.isNotNull(configVO.getVehicleArrayS())) {
                configPO.setVehicleArray(StringUtils.join(Arrays.asList(configVO.getVehicleArrayS()), ','));
            }
            // 单独处理配置描述
            configPO.setDescription(configVO.getConfigDescription());
            // 主表主键
            publicConfigId = StringUtil.getRandomUUID();
            configPO.setId(publicConfigId);
            configPO.setConfigCode(StringUtil.getRandomCode());
            configMapper.insertConfig(configPO);
        }

        if (CollectionUtil.isNotEmpty(configSensorPOs)) {
            configSensorPOs.forEach(configSensorPO -> configSensorPO.setConfigId(publicConfigId));
            log.debug("即将保存的传感器信息为：" + configSensorPOs);
            relationConfigSensorMapper.deleteByConfigId(configPO.getId());  // 删除配置与传感器关联关系，方便后面重新添加
            configMapper.insertConfigSensors(configSensorPOs);
        }
        return configPO;
    }

    public ConfigPO shareConfigById(ConfigVO configVO) {
        configVO = getConfigInfo(configVO);
        ConfigPO configPO = shareConfigByInfo(configVO);
        LogUtil.share();
        return configPO;
    }

    public int getConfigTotal() {
        return configMapper.getConfigTotal(AuthUtil.getCurrentUserId());
    }
}
