package com.ho.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.ho.business.entity.ModelTypeCol;
import com.ho.business.entity.*;
import com.ho.business.mapper.DeviceTypeColMapper;
import com.ho.business.mapper.ModelDeviceColMapper;
import com.ho.business.service.*;
import com.ho.business.vo.req.DeviceReqVO;
import com.ho.business.vo.req.colCount.ColCountReq;
import com.ho.business.vo.req.deviceModel.*;
import com.ho.business.vo.resp.DeviceRespVO;
import com.ho.business.vo.resp.colCount.ColCountResp;
import com.ho.business.vo.resp.deviceModel.DeviceModelRespVo;
import com.ho.business.vo.resp.deviceModel.ModelDeviceColRespVo;
import com.ho.business.vo.resp.modelType.ModelColData;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author gyan
 * @desc: 设备模型关联表实现类
 * @DateTime: 2023/3/7 17:46
 */
@Service
@Slf4j
public class ModelDeviceColServiceImpl implements ModelDeviceColService {

    @Autowired
    ModelDeviceColMapper modelDeviceColMapper;

    @Autowired
    DeviceModelService deviceModelService;

    @Autowired
    ModelTypeService modelTypeService;

    @Autowired
    ModelDeviceService modelDeviceService;

    @Autowired
    ModelDeviceColService modelDeviceColService;

    @Autowired
    DeviceService deviceService;

    @Autowired
    RedisService redisService;

    @Override
    public void addBatch(ModelDeviceColAddReqVo vo) {
        //判断是否有重复
        List<ModelDeviceIds> colIdList = vo.getColIdList();
        List<Integer> deviceColIdList = colIdList.stream().map(ModelDeviceIds::getDeviceColId)
                .collect(Collectors.toList());
        List<Integer> modelColIdList = colIdList.stream().map(ModelDeviceIds::getModelColId)
                .collect(Collectors.toList());
        long colCount = colIdList.stream().distinct().count();
        if (deviceColIdList.size() != colCount || modelColIdList.size() != colCount) {
            throw new BusinessException(BaseResponseCode.EXISTS_DUPLICATE_DATA);
        }


        //修改时判断col是否在关联表中使用
        List<Integer> updateColIdList = new ArrayList<>();
        List<ModelDeviceIds> updateList = new ArrayList<>();
        List<ModelDeviceIds> addColList = new ArrayList<>();
        for (ModelDeviceIds deviceIds : colIdList) {
            if (deviceIds.getId() != null) {
                updateColIdList.add(deviceIds.getId());
                updateList.add(deviceIds);
            } else {
                addColList.add(deviceIds);
            }
        }
        List<Integer> collect = addColList.stream().map(ModelDeviceIds::getDeviceColId)
                .collect(Collectors.toList());
        if (!collect.isEmpty()) {
            //查看表中是否有（根据 device_col_id device_type）
            List<ModelDeviceCol> cols = modelDeviceColMapper.selectByDeviceIds(collect, vo.getDeviceType());
            if (!cols.isEmpty()) {
                throw new BusinessException(BaseResponseCode.THE_SAME_DATA_EXISTS_DATABASE_PLEASE_CHECK);
            }
        }

        if (!updateColIdList.isEmpty()) {
            List<ModelDeviceCol> modelDeviceCols = new ArrayList<>();
            for (ModelDeviceIds modelDeviceIds : updateList) {
                ModelDeviceCol modelDeviceCol = new ModelDeviceCol();
                modelDeviceCol.setDeviceType(vo.getDeviceType());
                modelDeviceCol.setModelType(vo.getModelType());
                modelDeviceCol.setDeviceColId(modelDeviceIds.getDeviceColId());
                modelDeviceCol.setModelColId(modelDeviceIds.getModelColId());
                modelDeviceCols.add(modelDeviceCol);
            }
            for (ModelDeviceCol modelDeviceCol : modelDeviceCols) {
                modelDeviceColMapper.updateByPrimaryKeySelective(modelDeviceCol);

            }
        }

        if (!addColList.isEmpty()) {
            List<ModelDeviceCol> modelDeviceCols = new ArrayList<>();
            for (ModelDeviceIds modelDeviceIds : addColList) {
                ModelDeviceCol modelDeviceCol = new ModelDeviceCol();
                modelDeviceCol.setDeviceType(vo.getDeviceType());
                modelDeviceCol.setModelType(vo.getModelType());
                modelDeviceCol.setDeviceColId(modelDeviceIds.getDeviceColId());
                modelDeviceCol.setModelColId(modelDeviceIds.getModelColId());
                modelDeviceCols.add(modelDeviceCol);
            }
            modelDeviceColMapper.addBatch(modelDeviceCols);
        }

    }

    @Override
    public void add(ModelDeviceColAddVo vo) {
        List<Integer> collect = new ArrayList<>();
        if (vo.getDeviceColId() != null) {
            collect.add(vo.getDeviceColId());
            //查看表中是否有（根据 device_col_id device_type）
            List<ModelDeviceCol> modelDeviceCols =
                    modelDeviceColMapper.selectByType(vo.getDeviceType(), vo.getModelType(), vo.getDeviceColId(), vo.getModelColId());
            if (!modelDeviceCols.isEmpty()) {
                throw new BusinessException(BaseResponseCode.SAME_DATA_ASSOCIATION_EXISTS);
            }
        }
        if (vo.getId() == null) {
            ModelDeviceCol modelDeviceCol = new ModelDeviceCol();
            modelDeviceCol.setDeviceType(vo.getDeviceType());
            modelDeviceCol.setModelType(vo.getModelType());
            modelDeviceCol.setDeviceColId(vo.getDeviceColId());
            modelDeviceCol.setModelColId(vo.getModelColId());
            modelDeviceColMapper.insertSelective(modelDeviceCol);
        } else {
            ModelDeviceCol modelDeviceCol = new ModelDeviceCol();
            modelDeviceCol.setDeviceType(vo.getDeviceType());
            modelDeviceCol.setModelType(vo.getModelType());
            modelDeviceCol.setDeviceColId(vo.getDeviceColId());
            modelDeviceCol.setModelColId(vo.getModelColId());
            modelDeviceColMapper.updateByPrimaryKeySelective(modelDeviceCol);
        }

    }


    @Override
    public List<ModelDeviceColRespVo> page(DeviceColSelectReqVo vo) {
        List<ModelDeviceColRespVo> modelDeviceColRespVos = new ArrayList<>();
        List<ModelDeviceCol> list = modelDeviceColMapper.selectByDeviceType(vo.getType());

        List<ModelDeviceColComp> compListByType = modelDeviceService.getCompListByType("device", vo.getType(), null);
        for (ModelDeviceCol model : list) {
            for (ModelDeviceColComp comp : compListByType) {
                if (model.getModelColId() != null && comp.getModelColId() != null) {
                    if (model.getDeviceColId().equals(comp.getDeviceColId()) && model.getModelColId().equals(comp.getModelColId())) {
                        ModelDeviceColRespVo modelDeviceColRespVo = new ModelDeviceColRespVo();
                        modelDeviceColRespVo.setDeviceColIdName(comp.getDeviceColName());
                        modelDeviceColRespVo.setModelColIdName(comp.getModelColName());
                        modelDeviceColRespVo.setModelCol(comp.getModelCol());
                        modelDeviceColRespVo.setDeviceCol(comp.getDeviceCol());
                        modelDeviceColRespVo.setId(model.getId());
                        modelDeviceColRespVo.setDeviceType(model.getDeviceType());
                        modelDeviceColRespVo.setDeviceColId(model.getDeviceColId());
                        modelDeviceColRespVo.setModelType(model.getModelType());
                        modelDeviceColRespVo.setModelColId(model.getModelColId());
                        modelDeviceColRespVos.add(modelDeviceColRespVo);
                    }
                }

            }
        }
        return modelDeviceColRespVos;
    }

    @Override
    public List<ModelDeviceCol> selectList(DeviceColSelectReqVo vo) {
        List<ModelDeviceCol> list = modelDeviceColMapper.selectByDeviceType(vo.getType());
        return list;
    }

    @Override
    public void deleteBatch(DeviceModelDeleteReqVo vo) {
        clearRedisData(vo.getIds());
        modelDeviceColMapper.deleteBatchDevice(vo.getIds());
    }


    @Override
    public List<ModelDeviceCol> selectByDeviceIds(List<Integer> ids, String deviceType) {
        List<ModelDeviceCol> colList = modelDeviceColMapper.selectByDeviceIds(ids, deviceType);
        return colList;
    }


    @Override
    public List<ModelDeviceCol> selectByModelIds(List<Integer> ids, String deviceType) {
        List<ModelDeviceCol> colList = modelDeviceColMapper.selectByModelIds(ids, deviceType);
        return colList;
    }

    @Override
    public ModelDeviceCol selectByModelId(String deviceType, Integer modelColId) {
        ModelDeviceCol modelDeviceCol = modelDeviceColMapper.selectByModelId(deviceType, modelColId);
        return modelDeviceCol;
    }

    @Override
    public List<ModelDeviceCol> selectByModelType(List<Integer> collect, String type) {
        List<ModelDeviceCol> colList = modelDeviceColMapper.selectByModelType(type, collect);
        return colList;
    }

    @Override
    public int insertList(List<ModelDeviceCol> list) {
        int count = modelDeviceColMapper.insertList(list);
        return count;
    }

    @Override
    public List<ModelDeviceCol> selectByDeviceTypeList(List<String> list) {
        return modelDeviceColMapper.selectByDeviceTypeList(list);
    }

    @Override
    public List<DeviceModelRespVo> selectDevice(DeviceColSelectReqVo vo) {
        List<DeviceModelRespVo> list = new ArrayList<>();
        //先查询到设备全量字段
        List<DeviceTypeCol> deviceTypeCols = deviceModelService.deviceColPage(vo);
        if (deviceTypeCols.isEmpty()) {
            return new ArrayList<>();
        }
        List<Integer> colIdList = deviceTypeCols.stream().map(s -> {
                    return s.getId();
                }
        ).collect(Collectors.toList());
        //关联表中所使用的数据
        List<ModelDeviceCol> modelDeviceCols = modelDeviceColMapper.selectByDeviceIds(colIdList, vo.getType());
        Map<Integer, List<ModelDeviceCol>> collect = modelDeviceCols.stream().collect(Collectors.groupingBy(ModelDeviceCol::getDeviceColId));
        deviceTypeCols.removeIf(s -> {
            return collect.get(s.getId()) != null;
        });
        for (DeviceTypeCol deviceTypeCol : deviceTypeCols) {
            DeviceModelRespVo deviceModelRespVo = new DeviceModelRespVo();
            deviceModelRespVo.setId(deviceTypeCol.getId());
            deviceModelRespVo.setCol(deviceTypeCol.getCol());
            deviceModelRespVo.setColName(deviceTypeCol.getColName());
            list.add(deviceModelRespVo);
        }
        return list;
    }


    @Override
    public List<DeviceModelRespVo> selectModel(String deviceType, String modelType) {
        List<DeviceModelRespVo> deviceModelRespVos = new ArrayList<>();
        //先查询到模型的全量字段
        DeviceColSelectReqVo vo = new DeviceColSelectReqVo();
        vo.setType(modelType);
        List<ModelTypeCol> modelCols = deviceModelService.ModelColPage(vo);
        if (modelCols.isEmpty()) {
            return new ArrayList<>();
        }
        //查询已经使用过的模型字段
        List<ModelDeviceCol> modelDeviceCols = modelDeviceColMapper.selectByType(deviceType, modelType, null, null);

        Map<Integer, List<ModelDeviceCol>> collect = modelDeviceCols.stream().collect(Collectors.groupingBy(ModelDeviceCol::getModelColId));
        modelCols.removeIf(s -> {
            return collect.get(s.getId()) != null;
        });
        for (ModelTypeCol modelCol : modelCols) {
            DeviceModelRespVo deviceModelRespVo = new DeviceModelRespVo();
            deviceModelRespVo.setId(modelCol.getId());
            deviceModelRespVo.setCol(modelCol.getCol());
            deviceModelRespVo.setColName(modelCol.getColName());
            deviceModelRespVos.add(deviceModelRespVo);
        }

        return deviceModelRespVos;
    }

    @Override
    public List<ModelType> getModelType() {
        List<ModelType> list = modelTypeService.getModelType();
        return list;
    }

    @Override
    public List<ModelDevice> getDeviceType(String modelType) {
        List<ModelDevice> list = modelTypeService.getDeviceType(modelType);
        return list;
    }

    @Override
    public void synchronousAdd(SynchronousReqVo vo) {
        if (vo.getDeviceType() == null) {
            //请选择同步的设备类型
            throw new BusinessException(BaseResponseCode.PLEASE_CHECK_DEVICE_TYPE);
        }
        if (vo.getModelType() == null) {
            //请选择同步的模型类型
            throw new BusinessException(BaseResponseCode.PLEASE_CHECK_MODEL_TYPE);
        }
        //根据 类型以及模板电站id 查询到关联关系
        DeviceColSelectReqVo deviceCol = new DeviceColSelectReqVo();
        deviceCol.setType(vo.getDeviceType());
        List<ModelDeviceColRespVo> page = page(deviceCol);
        //deviceType自己拼接的
        String newModelType = vo.getModelType() + "_" + vo.getStationId();
        //再根据类型以及到同步的电站查询到设备Id
        deviceCol.setType(newModelType);
        List<ModelDeviceCol> list = new ArrayList<>();
        List<DeviceTypeCol> deviceTypeCols = deviceModelService.deviceColPage(deviceCol);
        //再根据原本的deviceCol字段对比 set要同步的电站的关联数据（原本的modelcolid 和modelType 不变 ）
        Map<String, List<DeviceTypeCol>> modelMap = deviceTypeCols.stream().collect(Collectors.groupingBy(DeviceTypeCol::getCol));
        for (ModelDeviceColRespVo modelDeviceColRespVo : page) {
            if (modelMap.get(modelDeviceColRespVo.getDeviceCol()) != null) {
                ModelDeviceCol modelDeviceCol = new ModelDeviceCol();
                //取到Id set到（modelDeviceColRespVo）
                List<DeviceTypeCol> deviceTypeCols1 = modelMap.get(modelDeviceColRespVo.getDeviceCol());
                modelDeviceCol.setDeviceColId(deviceTypeCols1.get(0).getId());
                modelDeviceCol.setModelColId(modelDeviceColRespVo.getModelColId());
                modelDeviceCol.setModelType(modelDeviceColRespVo.getModelType());
                modelDeviceCol.setDeviceType(newModelType);
                list.add(modelDeviceCol);
            }
        }
        //先判断是否有重复数据，防止二次入库
        deviceCol.setType(newModelType);
        List<ModelDeviceColRespVo> voPage = page(deviceCol);
        log.info("voPage:{}",voPage);
        if (!voPage.isEmpty()) {
            //如果存在，全部删掉
            List<Integer> ids = list.stream().map(ModelDeviceCol::getId).collect(Collectors.toList());
            log.info("ids:{}",ids);
            if (null != ids && ids.size()>0) {
                modelDeviceColMapper.deleteBatchDevice(ids);
            }
        }
        //组对象然后批量入库
        log.info("list:{}",list);
        if (!list.isEmpty()) {
            modelDeviceColMapper.insertList(list);
        }

    }

    @Autowired
    DeviceTypeColMapper deviceTypeColMapper;

    @Autowired
    ColCountService colCountService;

    @Autowired
    PageConfigService pageConfigService;

    @Override
    public void synchronousAddNew(SynchronousReqVo vo) {
        List<ModelDeviceColRespVo> page = modelDeviceColMapper.selectByParam(CommonConstant.JOIN_STATION_ID+vo.getModelStationId());
        List<ModelDeviceCol> list = new ArrayList<>();
        String queryType = CommonConstant.JOIN_STATION_ID + vo.getStationId();
        List<DeviceTypeCol> deviceTypeCols = deviceTypeColMapper.selectDimType(queryType);
        String type = CommonConstant.JOIN + vo.getStationId();
        //再根据原本的deviceCol字段对比 set要同步的电站的关联数据（原本的modelcolid 和modelType 不变 ）
        Map<String, Integer> modelMap = deviceTypeCols.stream().collect(Collectors.toMap(s -> s.getDeviceType() + CommonConstant.JOIN + s.getCol(), t -> t.getId(), (k1, k2) -> k1));
        for (ModelDeviceColRespVo modelDeviceColRespVo : page) {
            String modelType = modelDeviceColRespVo.getDeviceType().replace(CommonConstant.JOIN+vo.getModelStationId(),type);
            Integer colId = modelMap.get(modelType + CommonConstant.JOIN + modelDeviceColRespVo.getDeviceCol());
            if (colId != null) {
                ModelDeviceCol modelDeviceCol = new ModelDeviceCol();
                //取到Id set到（modelDeviceColRespVo）
                modelDeviceCol.setDeviceColId(colId);
                modelDeviceCol.setModelColId(modelDeviceColRespVo.getModelColId());
                modelDeviceCol.setModelType(modelDeviceColRespVo.getModelType());
                modelDeviceCol.setDeviceType(modelType);
                list.add(modelDeviceCol);
            }
        }
        //组对象然后批量入库
        log.info("list:{}",list);
        if (!list.isEmpty()) {
            //先判断是否有重复数据，防止二次入库
            modelDeviceColMapper.deleteByDeviceType(type);
            modelDeviceColMapper.insertList(list);
            /*********************同步首页环控显示*****************/
            syPageConfig(vo, list);
        }
        /*********************同步偏移量**********************/
        syColCount(vo);
    }

    /**
     * 同步首页环控数据
     * @param vo
     * @param list
     */
    private void syPageConfig(SynchronousReqVo vo, List<ModelDeviceCol> list) {
        Map<String, ModelDeviceCol> map = list.stream().collect(Collectors.toMap(s -> s.getDeviceType() + CommonConstant.JOIN + s.getModelColId(), t -> t, (k1, k2) -> k1));
        PageConfig pageConfig = new PageConfig();
        pageConfig.setStationId(vo.getModelStationId());
        List<PageConfig> resultList = pageConfigService.selectPage(pageConfig);
        if(!resultList.isEmpty()){
            List<PageConfig> pageConfigList = new ArrayList<>();
            PageConfig pageC = null;
            for (PageConfig c:resultList) {
                String deviceType = c.getDeviceType().replace(CommonConstant.JOIN+c.getStationId(),CommonConstant.JOIN+ vo.getStationId());
                ModelDeviceCol modelDeviceCol = map.get(deviceType + CommonConstant.JOIN + c.getModelColId());
                if(null != modelDeviceCol){
                    pageC = new PageConfig();
                    BeanUtils.copyProperties(c,pageC);
                    pageC.setStationId(vo.getStationId());
                    pageC.setDeviceType(deviceType);
                    pageC.setDeviceColId(modelDeviceCol.getDeviceColId());
                    pageC.setId(modelDeviceCol.getId());
                    pageConfigList.add(pageC);
                }
            }
            System.out.println(pageConfigList);
            if(!pageConfigList.isEmpty()){
                log.info("同步首页环控数据:{}",pageConfigList.size());
                pageConfigService.deleteStationId(vo.getStationId());
                pageConfigService.addBatch(pageConfigList);
            }
        }
    }

    /**
     * 同步偏移量
     * @param vo
     */
    private void syColCount(SynchronousReqVo vo) {
        ColCountReq colCountReq = new ColCountReq();
        colCountReq.setStationId(vo.getModelStationId());
        List<ColCountResp> resultList = colCountService.selectByParam(colCountReq);
        if(!resultList.isEmpty()){
            List<ColCount> colCountList = new ArrayList<>();
            ColCount colCount = null;
            for (ColCountResp c:resultList) {
                colCount = new ColCount();
                BeanUtils.copyProperties(c,colCount);
                colCount.setStationId(vo.getStationId());
                colCount.setOffset(BigDecimal.ZERO);
                colCount.setCountFlag(CommonConstant.ZERO);
                colCountList.add(colCount);
            }

            if(!colCountList.isEmpty()){
                log.info("同步偏移量数量:{}",colCountList.size());
                colCountService.deleteStationId(vo.getStationId());
                colCountService.insertList(colCountList);
            }
        }
    }

    @Override
    public List<ModelDeviceCol> selectDeviceColsByIds(List<Integer> modelColIdList,List<String> deviceTypeList) {
        return modelDeviceColMapper.selectDeviceColsByIds(modelColIdList,deviceTypeList);
    }

    private void clearRedisData(List<Integer> ids){
        List<ModelColData> modelColData = modelDeviceColMapper.selectModelData(ids);
        List<String> typeList = modelColData.stream().map(ModelColData::getDeviceType).collect(Collectors.toList());
        if(typeList.isEmpty()){
            return;
        }
        Map<String, List<ModelColData>> typeColMap = modelColData.stream().collect(Collectors.groupingBy(ModelColData::getDeviceType));
        DeviceReqVO deviceReqVO = new DeviceReqVO();
        deviceReqVO.setDeviceTypeList(typeList);
        List<DeviceRespVO> list = deviceService.getList(deviceReqVO);
        for (DeviceRespVO d:list) {
            String redisKey = d.getDeviceType() + ":" + d.getStationId() + ":" + d.getSrcId();
            if(redisService.hasKey(redisKey)){
                List<ModelColData> dataList = typeColMap.get(d.getDeviceType());
                if(dataList !=null && dataList.size()>0){
                    for (ModelColData m:dataList) {
                        redisService.hdel(redisKey,m.getCol());
                    }
                }
            }
        }
    }
}
