package com.cico.nest.lcdp.boot.core.qxsd.application.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.web.vo.tunnelEquipment.TunnelEquipmentExcelVO;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.web.vo.tunnelEquipment.TunnelEquipmentPageReqVO;
import com.cico.nest.lcdp.boot.core.qxsd.adapter.web.vo.tunnelEquipment.TunnelEquipmentSaveReqVO;
import com.cico.nest.lcdp.boot.core.qxsd.application.service.TunnelEquipmentService;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.database.TunnelEquipmentMapper;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.database.TunnelFacilityMapper;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.database.dataobject.TunnelEquipmentDO;
import com.cico.nest.lcdp.boot.core.qxsd.infrastructure.gatewayimpl.database.dataobject.TunnelFacilityDO;
import com.cico.nest.lcdp.framework.common.context.LcdpGlobalContext;
import com.cico.nest.lcdp.framework.common.exception.ServiceException;
import com.cico.nest.lcdp.framework.common.pojo.PageResult;
import com.cico.nest.lcdp.framework.common.util.object.BeanUtils;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;


import static com.cico.nest.lcdp.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR;
import static com.cico.nest.lcdp.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 隧道设备 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class TunnelEquipmentServiceImpl implements TunnelEquipmentService {

    @Resource
    private TunnelEquipmentMapper tunnelEquipmentMapper;
    @Resource
    private TunnelFacilityMapper tunnelFacilityMapper;

    public static BiMap<String,String> associateMappingSubclassMap = HashBiMap.create();

    static {
        associateMappingSubclassMap.put("x0","摄像机");
        associateMappingSubclassMap.put("x1","亮度检测器");
        associateMappingSubclassMap.put("x2","能见度检测器");
        associateMappingSubclassMap.put("x3","CO检测器");
        associateMappingSubclassMap.put("x4","风速风向检测器");
        associateMappingSubclassMap.put("x5","车辆检测器");
        associateMappingSubclassMap.put("x6","可变信息屏");
    }

    @Override
    public String createTunnelEquipment(TunnelEquipmentSaveReqVO createReqVO) {
        // 插入
        TunnelEquipmentDO tunnelEquipment = BeanUtils.toBean(createReqVO, TunnelEquipmentDO.class);
        tunnelEquipmentMapper.insert(tunnelEquipment);
        // 返回
        return tunnelEquipment.getId();
    }

    @Override
    public void updateTunnelEquipment(TunnelEquipmentSaveReqVO updateReqVO) {
        // 校验存在
        validateTunnelEquipmentExists(updateReqVO.getId());
        // 更新
        TunnelEquipmentDO updateObj = BeanUtils.toBean(updateReqVO, TunnelEquipmentDO.class);
        tunnelEquipmentMapper.updateById(updateObj);
    }

    @Override
    public void deleteTunnelEquipment(String id) {
        // 校验存在
        validateTunnelEquipmentExists(id);
        // 删除
        tunnelEquipmentMapper.deleteById(id);
    }

    private void validateTunnelEquipmentExists(String id) {
        if (tunnelEquipmentMapper.selectById(id) == null) {
            throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(), "隧道设备不存在");
        }
    }

    @Override
    public TunnelEquipmentDO getTunnelEquipment(String id) {
        return tunnelEquipmentMapper.selectById(id);
    }

    @Override
    public PageResult<TunnelEquipmentDO> getTunnelEquipmentPage(TunnelEquipmentPageReqVO pageReqVO) {
        return tunnelEquipmentMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importExcel(List<TunnelEquipmentExcelVO> list, Boolean updateSupport) {
        if (CollUtil.isEmpty(list)) {
            throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"导入数据不能为空请检查导入模板");
        }
        Map<String,String> facilityMap = new HashMap<>();
        List<TunnelEquipmentDO> addList = new ArrayList<>();
        for(TunnelEquipmentExcelVO tunnelEquipmentExcelVO : list){
            TunnelEquipmentDO tunnelEquipmentDO = new TunnelEquipmentDO();
            org.springframework.beans.BeanUtils.copyProperties(tunnelEquipmentExcelVO,tunnelEquipmentDO);
            tunnelEquipmentDO.setCreateBy(LcdpGlobalContext.getLoginUserId());
            tunnelEquipmentDO.setCreateTime(new Date());

            String equipmentEncode = tunnelEquipmentExcelVO.getEquipmentEncode();
            if(StrUtil.isEmpty(equipmentEncode)){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"编码不能为空");
            }
            if(tunnelEquipmentMapper.existsEncode(equipmentEncode)){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),equipmentEncode + "编码重复");
            }
            if(StrUtil.isEmpty(tunnelEquipmentExcelVO.getFacilityName())){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"设备名称不能为空");
            }
            if(StrUtil.isEmpty(tunnelEquipmentExcelVO.getEquipmentUuid())){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"UUID不能为空");
            }
            if(StrUtil.isEmpty(tunnelEquipmentExcelVO.getManagementCenter())){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"管理中心不能为空");
            }
            if(StrUtil.isEmpty(tunnelEquipmentExcelVO.getTunnelDept())){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"隧道站/所不能为空");
            }
            if(Objects.isNull(tunnelEquipmentExcelVO.getEquipmentStation())){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"桩号不能为空");
            }
            if(Objects.isNull(tunnelEquipmentExcelVO.getIpAddress())){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"IP不能为空");
            }

            if(StrUtil.isEmpty(tunnelEquipmentExcelVO.getAssociateMappingSubclass())){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"设备小类不能为空");
            }
            String associateMappingSubclass = associateMappingSubclassMap.inverse().get(tunnelEquipmentExcelVO.getAssociateMappingSubclass());
            if(StrUtil.isEmpty(associateMappingSubclass)){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),tunnelEquipmentExcelVO.getAssociateMappingSubclass() + " 设备小类不存在");
            }
            tunnelEquipmentDO.setAssociateMappingSubclass(associateMappingSubclass);


            String facilityName = tunnelEquipmentExcelVO.getFacilityName();
            String facilityId  = facilityMap.get(facilityName);
            if(StrUtil.isEmpty(facilityId)){
                if(StrUtil.isEmpty(facilityName)){
                    throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"所属设施不能为空");
                }
                List<TunnelFacilityDO> tunnelFacilityDOList = tunnelFacilityMapper.selectByFacilityName(facilityName);
                if(CollUtil.isEmpty(tunnelFacilityDOList)){
                    throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),facilityName + " 所属设施不存在");
                }
                if(tunnelFacilityDOList.size() > 1){
                    throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),facilityName + " 设施名称存在多个");
                }
                facilityId = tunnelFacilityDOList.get(0).getId();
                facilityMap.put(facilityName,facilityId);
            }
            tunnelEquipmentDO.setBelongFacilityId(facilityId);
            String uplinkDownlinkRoad = tunnelEquipmentExcelVO.getUplinkDownlinkRoad();
            if(StrUtil.isEmpty(uplinkDownlinkRoad)){
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"隧道方向不能为空");
            }
            if("上行".equals(uplinkDownlinkRoad)){
                tunnelEquipmentDO.setUplinkDownlinkRoad(0);
            }else if("下行".equals(uplinkDownlinkRoad)){
                tunnelEquipmentDO.setUplinkDownlinkRoad(1);
            }else{
                throw new ServiceException(INTERNAL_SERVER_ERROR.getCode(),"隧道方向取值范围为['上行','下行']");
            }
            addList.add(tunnelEquipmentDO);
        }
        tunnelEquipmentMapper.insertBatch(addList);
    }

}
