package com.bocloud.ims.service.transporter.vendor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bocloud.cmp.driver.common.LocationDriver;
import com.bocloud.cmp.model.SangforModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.sangfor.*;
import com.bocloud.cmp.params.Sangfor.*;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.Result;
import com.bocloud.common.utils.ListTool;
import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.ims.common.enums.DiskPreallocateType;
import com.bocloud.ims.common.utils.DateUtils;
import com.bocloud.ims.common.utils.FastjsonUtils;
import com.bocloud.ims.common.utils.MapUtils;
import com.bocloud.ims.common.utils.MathUtils;
import com.bocloud.ims.entity.enums.OsType;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.internal.CosInternalService;
import com.bocloud.ims.service.transporter.ResourceTransporter;
import com.bocloud.ims.service.utils.SangforConvertUtils;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Slf4j
@Component
public class SangforV68Transporter implements ResourceTransporter {

    @Autowired
    private LocationDriver locationDriver;
    @Autowired
    ServerRepository serverRepository;
    @Autowired
    CloudServerRepository cloudServerRepository;
    @Autowired
    BasicGenericDao basicGenericDao;
    @Autowired
    DataStoreRepository dataStoreRepository;
    @Autowired
    NetworkRepository networkRepository;
    @Autowired
    SangforServerLogRepository serverLogRepository;
    @Autowired
    SnapshotRepository snapshotRepository;
    @Autowired
    SangforIfaceRepository ifaceRepository;
    @Autowired
    VolumeRepository volumeRepository;
    @Autowired
    FirewallRuleRepository firewallRuleRepository;
    @Autowired
    CosInternalService cosInternalService;
    @Autowired
    SangforServerGroupRepository serverGroupRepository;
    @Autowired
    SangforBridgeInfoRepository bridgeInfoRepository;
    @Autowired
    SangforVlanGroupRepositpry vlanGroupRepositpry;
    @Autowired
    StorageRepository storageRepository;
    @Autowired
    SangforCommunicationRepository communicationRepository;
    @Autowired
    PortGroupRepository portGroupRepository;
    @Autowired
    PortRepository portRepository;
    @Autowired
    SangforAzRepository sangforAzRepository;
    @Autowired
    SangforProjectsRepository sangforProjectsRepository;
    @Autowired
    ImageRepository imageRepository;

    @Value("${regex}")
    private String regex;
//    private final static String regex = "";
    @Override
    public Result transport(CloudVendor vendor, Long operator) {
        try {
            long begin = System.currentTimeMillis();

            BocloudResult syncResult = locationDriver.sync(vendor.getUuid());
            if (syncResult.isFailed()) {
                log.info("{}云平台同步失败", vendor.getName());
                return syncResult;
            }
            Long vendorId = vendor.getId();
            if (Objects.nonNull(syncResult.getData())) {
                SangforModel model = null;
                String modelJson = JSONObject.toJSONString(syncResult.getData());
                model = JSONObject.parseObject(modelJson, SangforModel.class);

                log.info("租户列表数据同步开始");
                syncProjects(model.getProjectsParamsList(), vendorId, operator);
                log.info("租户列表数据同步结束");

                log.info("资源池列表数据同步开始");
                syncAzList(model.getAzModels(), vendorId, operator);
                log.info("资源池列表数据同步结束");

                log.info("物理主机数据同步开始");
                syncPhysicalServer(model.getScpHostModels(), vendorId, operator);
                log.info("物理主机数据同步结束");

                List<Server> hosts = serverRepository.listByVendor(vendorId);
                Map<String, Server> hostMap = new HashMap<>();
                for (Server server : hosts) {
                    hostMap.put(server.getUuid(), server);
                }

                log.info("物理主机网络同步开始");
                syncInterfaces(model.getInterfacesModels(), vendorId, operator);
                log.info("物理主机网络同步结束");

                log.info("物理主机通信口同步开始");
                syncCommunication(model.getCommunicationModels(), vendorId, operator);
                log.info("物理主机通信口同步结束");

                log.info("物理主机系统盘同步开始");
                syncSystemStorage(model.getStorageModels(), vendorId, operator);
                log.info("物理主机系统盘同步结束");

                log.info("存储列表同步开始");
                syncStorage(model.getStorageParamsModels(), vendorId, operator);
                log.info("存储列表同步结束");

                log.info("虚拟机分组数据同步开始...");
                syncServerGroup(model.getServerGroupModels(), vendorId, operator);
                log.info("虚拟机分组数据同步结束...");

                log.info("网络列表数据同步开始...");
                syncNetWork(model.getScpNetWorkParams(), vendorId, operator);
                log.info("网络列表数据同步结束...");

                log.info("网络列表端口组数据同步开始...");
                syncDvVlanGroup(model.getVlanGroupParams(), vendorId, operator);
                log.info("网络列表端口组数据同步结束...");

                log.info("网络列表网口组数据同步开始...");
                syncPhyIf(model.getPhyIfParamsModel(), hostMap, vendorId, operator);
                log.info("网络列表网口组数据同步结束...");

                log.info("防火墙列表数据同步开始...");
                syncFireWall(model.getFirewallRuleModels(), vendorId, operator);
                log.info("防火墙列表数据同步结束...");

                List<DataStore> dataStores = dataStoreRepository.listByVendor(vendorId);
                Map<String, DataStore> dataStoreMap = Maps.newHashMap();
                for (DataStore dataStore : dataStores) {
                    dataStoreMap.put(dataStore.getGuid(), dataStore);
                }

                log.info("虚拟机数据同步开始...");
                log.info("同步虚拟机数据打印:{}",JSON.toJSONString(model.getServerModels()));
                syncServer(model.getServerModels(), vendorId, operator, hostMap, dataStoreMap);
                log.info("虚拟机数据同步结束...");

                log.info("镜像资源列表数据同步开始");
                syncImage(model.getScpImageModels(), vendorId, operator);
                log.info("镜像资源列表数据同步结束");

                log.info("同步镜像资源列表云主机模板开始");
                syncCloudServerImage(operator,vendorId,model.getServerModels());
                log.info("同步镜像资源列表云主机模板结束");
            }

            long cost = System.currentTimeMillis() - begin;
            log.info("耗时{}ms", cost);

            return new BocloudResult<>(true, "云平台【 " + vendor.getName() + " 】数据同步完成");
        } catch (Exception e) {
            log.error("云平台同步失败", e);
            return new BocloudResult(false, "云平台【 " + vendor.getName() + " 】数据同步失败:" + e.getMessage());
        }
    }

    private void syncImage(List<SangforImage> models,Long vendorId,Long userId){
        if (ListTool.isEmpty(models)){
            imageRepository.removeByVidBak(vendorId,userId);
            return;
        }
        List<Image> imageList = imageRepository.listByVendorId(vendorId);
        Map<String, Image> imageMap = Maps.newHashMap();
        for (Image image : imageList) {
            imageMap.put(image.getImageUuid(), image);
        }
        log.info("test");
        log.info("imageMap:{}",JSON.toJSONString(imageMap));
        log.info("models:{}",JSON.toJSONString(models));
        for (SangforImage model : models) {
            Image image = new Image();
            if (imageMap.containsKey(model.getImageUuid())) {
                image = imageMap.get(model.getImageUuid());
                BeanUtils.copyProperties(model, image);
                image.setGmtCreate(image.getGmtCreate());
                image.setMenderId(userId);
                image.setGmtModify(new Date());
                image.setSize(model.getSizeMb());
                image.setStatus(model.getStatus().toUpperCase());
                String osCategory = model.getOsType();
                if (osCategory.contains("ws")){
                    osCategory="Windows";
                }else if (osCategory.contains("linux")){
                    osCategory="Linux";
                }
                image.setOsCategory(osCategory);
                //镜像转义
                image.setOsName(imageNameConvert(model.getOsType()));
                image.setCatalog("VM");
                image.setSangforImageFormat(model.getDiskFormat());
                imageRepository.update(image);
                imageMap.remove(model.getImageUuid());
                continue;
            }
            BeanUtils.copyProperties(model, image);
            image.setVendorId(vendorId);
            image.setCreatorId(userId);
            image.setGmtCreate(new Date());
            image.setDeleted(false);
            image.setSize(model.getSizeMb());
            image.setCatalog("VM");
            image.setSangforImageFormat(model.getDiskFormat());
            image.setStatus(model.getStatus().toUpperCase());
            String osCategory = model.getOsType();
            if (osCategory.contains("ws")){
                osCategory="Windows";
            }else if (osCategory.contains("linux")){
                osCategory="Linux";
            }
            image.setCatalog("VM");
            image.setOsCategory(osCategory);
            image.setOsName(imageNameConvert(model.getOsType()));
            imageRepository.save(image);
            imageMap.remove(model.getImageUuid());
        }
        for (Map.Entry<String, Image> entry : imageMap.entrySet()) {
            imageRepository.remove(entry.getValue().getId(), userId);
        }

    }

    private void syncCloudServerImage(Long userId,Long vendorId,List<SangforServerModel> models){
        if (ListTool.isEmpty(models)){
            imageRepository.removeByOsType(userId,vendorId);
            return;
        }
        if (regex == null){
            regex ="^mb.*";
        }
        Pattern compile = Pattern.compile(regex);
        //通过正则表达式去匹配mb开头的虚拟机作为模版
        models = models.stream()
                .filter(model -> model.getName() !=null && compile.matcher(model.getName()).matches())
                .collect(Collectors.toList());
        for (SangforServerModel model : models){
            String detail = SangforV68Transporter.getCloudServerDetail(model);
            model.setDetail(detail);
        }
        log.info("打印models：{}",JSON.toJSONString(models));

        List<Image> imageList = imageRepository.listByByOsType(vendorId);
        log.info("打印ImageList:{}",JSON.toJSONString(imageList));
        Map<String, Image> imageMap = Maps.newHashMap();
        for (Image image : imageList) {
            imageMap.put(image.getImageUuid(), image);
        }
        for (SangforServerModel model : models) {
            Image image = new Image();
            if (imageMap.containsKey(model.getInstanceId())) {
                log.info("进入update");
                image = imageMap.get(model.getInstanceId());
                image.setGmtCreate(image.getGmtCreate());
                image.setMenderId(userId);
                image.setGmtModify(new Date());
                List<SangforDiskModel> disks = model.getDisks();
                double diskGb;
                if (!CollectionUtils.isEmpty(disks)) {
                    Integer diskSize = new Integer(0);
                    for (SangforDiskModel disk : disks) {
                        diskSize += disk.getSize_mb();
                    }
                    diskGb = (1.0 * diskSize) / 1024;
                    diskGb = MathUtils.round(diskGb, 0);
                } else {
                    diskGb = 0;
                }
                image.setSize(diskGb);
                image.setStatus(sangforCloudServerTemplateConvert(model.getStatus().toUpperCase()));
                String osCategory=null;
                String osType = model.getOs_type();
                if (StringUtils.isNotEmpty(osType)) {
                    if (osType.startsWith("l")) {
                        osCategory = "Linux";
                    } else if (osType.startsWith("w")) {
                        osCategory = "Windows";
                    } else {
                        osCategory = "Linux";
                    }
                } else {
                    osCategory = "Linux";
                }
                image.setOsCategory(osCategory);
                //镜像转义
                image.setOsName(imageNameConvert(model.getOs_type()));
                image.setCatalog("VM");
                image.setDetail(model.getDetail());
                imageRepository.update(image);
                imageMap.remove(model.getInstanceId());
                continue;
            }
            log.info("进入save");
            image.setVendorId(vendorId);
            image.setName(model.getName());
            image.setStatus(sangforCloudServerTemplateConvert(model.getStatus().toUpperCase()));
            image.setCreatorId(userId);
            image.setGmtCreate(new Date());
            image.setDeleted(false);
            List<SangforDiskModel> disks = model.getDisks();
            double diskGb;
            if (!CollectionUtils.isEmpty(disks)) {
                Integer diskSize = new Integer(0);
                for (SangforDiskModel disk : disks) {
                    diskSize += disk.getSize_mb();
                }
                diskGb = (1.0 * diskSize) / 1024;
                diskGb = MathUtils.round(diskGb, 0);
            } else {
                diskGb = 0;
            }
            image.setSize(diskGb);
            image.setCatalog("VM");
            String osCategory=null;
            String osType = model.getOs_type();
            if (StringUtils.isNotEmpty(osType)) {
                if (osType.startsWith("l")) {
                    osCategory = "Linux";
                } else if (osType.startsWith("w")) {
                    osCategory = "Windows";
                } else {
                    osCategory = "Linux";
                }
            } else {
                osCategory = "Linux";
            }
            image.setCatalog("VM");
            image.setOsCategory(osCategory);
            image.setImageUuid(model.getInstanceId());
            image.setOsType("cloudServerTemplate");
            image.setOsName(imageNameConvert(model.getOs_type()));
            image.setVendorType("SANGFOR");
            image.setAzUuid(model.getAz_id());
            image.setDetail(model.getDetail());
            imageRepository.save(image);
            imageMap.remove(model.getInstanceId());
        }
        for (Map.Entry<String, Image> entry : imageMap.entrySet()) {
            imageRepository.remove(entry.getValue().getId(), userId);
        }
    }
    private String sangforCloudServerTemplateConvert(String status){
        String imageStatus;
        if (status.equals("RUNNING")){
            imageStatus= "DEACTIVETED";
        }else if(status.equals("STOPPED")){
            imageStatus = "ACTIVE";
        }else {
            imageStatus = "ERROR";
        }
        return imageStatus;
    }
    private String imageNameConvert(String osType){
        if (!osType.isEmpty()){
            OsType os = OsType.fromValue(osType);
            if (os!=null){
                osType = os.getSystemName();
            }
            return osType;
        }else {
            return null;
        }
    }

    private void syncProjects(List<SangforProjectsParams> models, Long vendorId, Long userId) {
        if (ListTool.isEmpty(models)) {
            sangforProjectsRepository.removeByVendor(vendorId, userId);
            return;
        }
        List<SangforProject> projectsList = sangforProjectsRepository.listByVendor(vendorId);
        Map<String, SangforProject> projectMap = Maps.newHashMap();
        for (SangforProject sangforProject : projectsList) {
            projectMap.put(sangforProject.getUuid(), sangforProject);
        }
        for (SangforProjectsParams model : models) {
            SangforProject project = new SangforProject();
            if (projectMap.containsKey(model.getUuid())) {
                project = projectMap.get(model.getUuid());
                BeanUtils.copyProperties(model, project);
                project.setGmtCreate(project.getGmtCreate());
                project.setMenderId(userId);
                project.setGmtModify(new Date());
                sangforProjectsRepository.update(project);
                projectMap.remove(model.getUuid());
                continue;
            }
            BeanUtils.copyProperties(model, project);
            project.setVendorId(vendorId);
            project.setCreatorId(userId);
            project.setGmtCreate(new Date());
            project.setDeleted(false);
            sangforProjectsRepository.save(project);
            projectMap.remove(model.getUuid());
        }
        for (Map.Entry<String, SangforProject> entry : projectMap.entrySet()) {
            sangforProjectsRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncAzList(List<SangforAzParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            sangforAzRepository.removeByVendor(vendorId, userId);
            return;
        }
        List<SangforAz> sangforAzs = sangforAzRepository.listByVendor(vendorId);
        Map<String, SangforAz> azMap = Maps.newHashMap();
        for (SangforAz sangforAz : sangforAzs) {
            azMap.put(sangforAz.getUuid(), sangforAz);
        }
        for (SangforAzParams model : models) {
            SangforAz az = new SangforAz();
            if (azMap.containsKey(model.getUuid())) {
                az = azMap.get(model.getUuid());
                BeanUtils.copyProperties(model, az);
                az.setGmtCreate(az.getGmtCreate());
                az.setMenderId(userId);
                az.setGmtModify(new Date());
                sangforAzRepository.update(az);
                azMap.remove(model.getUuid());
                continue;
            }
            BeanUtils.copyProperties(model, az);
            az.setVendorId(vendorId);
            az.setCreatorId(userId);
            az.setGmtCreate(new Date());
            az.setDeleted(false);
            sangforAzRepository.save(az);
        }
        for (Map.Entry<String, SangforAz> entry : azMap.entrySet()) {
            sangforAzRepository.remove(entry.getValue().getId(), userId);
        }
    }


    private void syncServer(List<SangforServerModel> models, Long vendorId, Long userId, Map<String, Server> hostMap, Map<String, DataStore> dataStoreMap) throws Exception {
        if (ListTool.isEmpty(models)) {
            cloudServerRepository.removeByVid(vendorId, userId);
            // 磁盘
            volumeRepository.removeByVid(vendorId, userId);
            // 快照
            snapshotRepository.removeByVid(vendorId, userId);
            return;
        }

        List<CloudServer> servers = cloudServerRepository.listAllByVendorId(vendorId);
        Map<String, CloudServer> serverMap = Maps.newHashMap();
        for (CloudServer server : servers) {
            serverMap.put(server.getInstanceId(), server);
        }

        for (SangforServerModel model : models) {
            if (serverMap.containsKey(model.getInstanceId())) {
                CloudServer oldServer = serverMap.get(model.getInstanceId());
                CloudServer newServer = SangforConvertUtils.convertCloudServerForV68(model, hostMap);
                com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(newServer, oldServer);
                newServer.setGmtModify(new Date());
                newServer.setMenderId(userId);
                cloudServerRepository.update(oldServer);
                serverMap.remove(model.getInstanceId());
                // 更新磁盘、快照
                saveUpdateVolume(volumeRepository, oldServer, model, userId, dataStoreMap);
                saveUpdateSnapShot(snapshotRepository, oldServer, model, userId);
                continue;
            }

            CloudServer newServer = SangforConvertUtils.convertCloudServerForV68(model, hostMap);
            newServer.setGmtCreate(new Date());
            newServer.setCreatorId(userId);
            newServer.setVendorId(vendorId);
            newServer.setRecycle(false);
            cloudServerRepository.save(newServer);
            // 更新磁盘、快照
            saveUpdateVolume(volumeRepository, newServer, model, userId, dataStoreMap);
            saveUpdateSnapShot(snapshotRepository, newServer, model, userId);
        }

        Long serverId;
        for (Map.Entry<String, CloudServer> entry : serverMap.entrySet()) {
            serverId = entry.getValue().getId();
            cloudServerRepository.remove(serverId, userId);
            // 存储
            volumeRepository.removeByServerId(serverId, userId);
            // 快照
            snapshotRepository.removeByVm(serverId, userId);
        }
    }


    /**
     * detail信息
     *
     * @author sxp
     * @since 2023/5/29
     */
    public static String getCloudServerDetail(SangforServerModel model) {
        JSONObject detailJson = new JSONObject();
        JSONObject netJson = new JSONObject();
        StringBuilder netValueSb = new StringBuilder();
        List<SangforNetwork> networks = model.getNetworks();

        JSONObject extraPropJson = model.getExtraPropJson();
        if (extraPropJson !=null){
            String locationStr = extraPropJson.getString("location");
            JSONObject locationJson = null;
            if (FastjsonUtils.isJSONObject(locationStr)) {
                locationJson = JSON.parseObject(locationStr);
                detailJson.put("location", locationJson);
            }
        }
        if (networks != null) {
            for (SangforNetwork network : networks) {
                netValueSb.setLength(0);
                netValueSb.append(network.getModel()).append('=').append(network.getMac_address())
                        .append(",bridge=xxx,port=12345678")
                        .append(",connect=").append(getConnectValue(network.getConnect()))
                        .append(",host_tso=on,bridgename=").append(network.getName())
                        .append(",ip=").append(network.getIpAddress())
                        .append(",ipv6=");
                netJson.put(network.getVif_id(), netValueSb.toString());
            }
        }
        detailJson.put("hardware_status", netJson);
        detailJson.put("host_config", model.getHost_name());

        JSONObject cpuStatus = model.getCpu_status();
        if (cpuStatus == null) {
            cpuStatus = new JSONObject(0);
        }
        Integer cores = model.getCores();
        Double mhz = model.getMhz();
        if (mhz == null) {
            mhz = 0D;
        }
        cpuStatus.put("cpus", cores);
        cpuStatus.put("mhz", mhz.intValue());
        detailJson.put("cpu_status", cpuStatus);

        JSONObject memStatus = model.getMemory_status();
        if (memStatus == null) {
            memStatus = new JSONObject(0);
        }
        String memoryMbString = model.getMemory_mb();
        Double memoryTotal;
        if (MathUtils.isNumber(memoryMbString)) {
            memoryTotal = MathUtils.parseDouble(model.getMemory_mb()) * 1024 * 1024;
            memoryTotal = MathUtils.round(memoryTotal, 0);
        } else {
            memoryTotal = 0D;
        }
        if (memoryTotal == null) {
            memoryTotal = 0D;
        }
        Long usedMb = memStatus.getLong("used_mb");
        if (usedMb == null) {
            usedMb = 0L;
        }
        long memoryUsed = usedMb * 1024 * 1024;
        if (memoryUsed > memoryTotal) {
            memoryUsed = memoryTotal.longValue();
        }
        long free = memoryTotal.longValue() - memoryUsed;
        double ratio;
        if (memoryTotal.intValue() == 0) {
            ratio = 0;
        } else {
            ratio = 1.0D * usedMb / memoryTotal;
            ratio = MathUtils.round(ratio, 2);
        }

        memStatus.put("total", memoryTotal);
        memStatus.put("auto_mem", 0);
        memStatus.put("used", memoryUsed);
        memStatus.put("free", free);
        memStatus.put("ratio", String.valueOf(ratio));
        detailJson.put("mem_status", memStatus);

        JSONObject cfgstorage = new JSONObject();
        String displayname = model.getStorage_name();
        String storageId = model.getStorage_id();
        cfgstorage.put("displayname", displayname);
        cfgstorage.put("name", displayname);
        if (storageId !=null){
            cfgstorage.put("id",storageId);
        }
        detailJson.put("cfgstorage", cfgstorage);

        Integer vtoolInstalled = model.getVtool_installed();
        if (vtoolInstalled == null) {
            vtoolInstalled = 0;
        }
        detailJson.put("vtool_installed", vtoolInstalled);

        String detail = JSON.toJSONString(detailJson);
        return detail;
    }

    private static String getConnectValue(Integer connect) {
        // connect  1:on  0:off
        if (connect == null || connect.intValue() == 0) {
            return "off";
        } else {
            return "on";
        }
    }

    /**
     * 新增或更新磁盘
     *
     * @author sxp
     * @since 2023/5/27
     */
    public static void saveUpdateVolume(VolumeRepository volumeRepository, CloudServer server, SangforServerModel model, Long userId, Map<String, DataStore> dataStoreMap) {
        List<SangforDiskModel> disks = model.getDisks();
        if (disks == null || disks.isEmpty()) {
            volumeRepository.removeByServerId(server.getId(), userId);
            return;
        }

        List<Volume> newVolumeList = diskToVolume(disks, dataStoreMap, server);

        List<Volume> oldVolumeList = volumeRepository.listByServerId(server.getId());
        Map<String, Volume> volumeMap = new HashMap<>(MapUtils.capacity(oldVolumeList.size()));
        for (Volume v : oldVolumeList) {
            volumeMap.put(v.getVolumeUuid(), v);
        }

        Volume volume;
        String key;
        for (Volume newVolume : newVolumeList) {
            key = newVolume.getVolumeUuid();
            if (volumeMap.containsKey(key)) {
                volume = volumeMap.get(key);
                com.bocloud.ims.service.utils.BeanUtils.copyPropertiesIgnoreNull(newVolume, volume);
                volume.setGmtModify(new Date());
                volume.setMenderId(userId);
                volumeRepository.update(volume);

                volumeMap.remove(key);
                continue;
            }

            newVolume.setGmtCreate(new Date());
            newVolume.setCreatorId(userId);
            volumeRepository.save(newVolume);
        }

        Set<Map.Entry<String, Volume>> entrySet = volumeMap.entrySet();
        for (Map.Entry<String, Volume> entry : entrySet) {
            volumeRepository.remove(entry.getValue().getId(), userId);
        }
    }

    /**
     * SangforDiskModel转换为Volume
     *
     * @author sxp
     * @since 2023/6/6
     */
    private static List<Volume> diskToVolume(List<SangforDiskModel> disks, Map<String, DataStore> dataStoreMap,
                                             CloudServer server) {
        List<Volume> volumeList =  new ArrayList<>(disks.size());

        DataStore dataStore;
        String id, storageFile, storageUuid;
        Long dataStoreId;
        Integer sizeMb;
        double diskGb;
        int index, pos1, pos2;
        int count = 0;

        for (SangforDiskModel diskModel : disks) {
            count++;
            id = diskModel.getId();
            if (StringUtils.isEmpty(id) || !id.startsWith("ide")) {
                continue;
            }
            // vm-disk-1.qcow2
            storageFile = diskModel.getStorage_file();
            pos1 = storageFile.indexOf("vm-disk-");
            pos2 = storageFile.indexOf(".qcow2");
            if (pos1 >= 0 && pos2 >= 0 && pos2 > pos1) {
                index = Integer.valueOf(storageFile.substring(pos1 + 8, pos2));
            } else {
                index = count;
            }

            sizeMb = diskModel.getSize_mb();
            if (sizeMb == null) {
                sizeMb = 0;
            }
            diskGb = (1.0 * sizeMb) / 1024;
            diskGb = MathUtils.round(diskGb, 0);

            dataStoreId = null;
            storageUuid = diskModel.getStorage_id();
            if (StringUtils.isNotEmpty(storageUuid) && dataStoreMap.containsKey(storageUuid)) {
                dataStore = dataStoreMap.get(storageUuid);
                if (dataStore != null) {
                    dataStoreId = dataStore.getId();
                }
            }

            Volume volume = new Volume();
            volume.setVolumeUuid(server.getInstanceId() + "-" + index);
            volume.setName("硬盘" + index);
            volume.setSize((int) diskGb);
            volume.setDataStoreUuid(storageUuid);
            volume.setDataStoreId(dataStoreId);
            volume.setDiskPolicieUuid(diskModel.getPreallocate());
            volume.setDiskPolicieName(DiskPreallocateType.valueOf(diskModel.getPreallocate()).getDesc());
            volume.setVendorId(server.getVendorId());
            volume.setServerId(server.getId());
            if (index == 1) {
                volume.setBootVolume(true);
            } else {
                volume.setBootVolume(false);
            }

            volumeList.add(volume);
        }

        return volumeList;
    }

    /**
     * 新增或更新快照
     *
     * @author sxp
     * @since 2023/5/27
     */
    public static void saveUpdateSnapShot(SnapshotRepository snapshotRepository, CloudServer server, SangforServerModel serverModel, Long userId) {
        List<SangforSnapshotModel> snapshotModels = serverModel.getSnapshotModels();
        if (snapshotModels == null || snapshotModels.isEmpty()) {
            snapshotRepository.removeByVm(server.getId(), userId);
            return;
        }

        List<Snapshot> snapshotList = snapshotRepository.listByVMid(server.getId());
        Map<String, Snapshot> snapshotMap = new HashMap<>(MapUtils.capacity(snapshotList.size()));
        for (Snapshot snapshot : snapshotList) {
            snapshotMap.put(snapshot.getSnapshotUuid(), snapshot);
        }

        Snapshot snapshot;
        Date createTime;
        JSONObject jsonObject;
        JSONArray diskArray;
        Double diskSize;
        for (SangforSnapshotModel model : snapshotModels) {
            diskSize = 0D;
            String disks = model.getDisks();
            if (FastjsonUtils.isJSONArray(disks)) {
                diskArray = JSON.parseArray(disks);
                for (int i = 0; i < diskArray.size(); i++) {
                    jsonObject = JSON.parseObject(diskArray.get(i).toString());
                    diskSize += jsonObject.getDouble("size");
                }
                diskSize = MathUtils.round(diskSize / 1024, 0);
            }

            // 时间格式"2020-12-01T03:17:42Z"
            try {
                createTime = DateUtils.utcStringToDate(model.getCreatedAt(), DateUtils.FORMAT_UTC);
            } catch (Exception e) {
                createTime = null;
                log.warn("将时间{}转化为日期是出错:{}", model.getCreatedAt(), e.getMessage());
            }

            if (snapshotMap.containsKey(model.getIdV68())) {
                snapshot = snapshotMap.get(model.getIdV68());
                snapshot.setName(model.getName());
                snapshot.setParentUuid(model.getParentId());
                snapshot.setMenderId(userId);
                snapshot.setStatus(model.getStatus());
                snapshot.setSnapshotType(model.getType());
                snapshot.setRemark(model.getDescription());
                snapshot.setIsProtected(model.getIs_protected());
                snapshot.setDisks(model.getDisks());
                snapshot.setSize(diskSize.intValue());
                snapshot.setCreateTime(createTime);
                snapshotRepository.update(snapshot);
                snapshotMap.remove(model.getIdV68());
                continue;
            }

            snapshot = new Snapshot();
            snapshot.setName(model.getName());
            snapshot.setSnapshotUuid(model.getIdV68());
            snapshot.setVmInstanceId(server.getInstanceId());
            snapshot.setParentUuid(model.getParentId());
            snapshot.setCreateTime(createTime);
            snapshot.setVmId(server.getId());
            snapshot.setVendorId(server.getVendorId());
            snapshot.setCreatorId(userId);
            snapshot.setMenderId(userId);
            snapshot.setStatus(model.getStatus());
            snapshot.setSnapshotType(model.getType());
            snapshot.setRemark(model.getDescription());
            snapshot.setIsProtected(model.getIs_protected());
            snapshot.setDisks(model.getDisks());
            snapshot.setSize(diskSize.intValue());
            snapshotRepository.save(snapshot);
        }

        Set<Map.Entry<String, Snapshot>> entrySet = snapshotMap.entrySet();
        for (Map.Entry<String, Snapshot> entry : entrySet) {
            snapshotRepository.remove(entry.getValue().getId(), userId);
        }
    }


    private void syncFireWall(List<SangforFireWallParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            firewallRuleRepository.removeByVid(vendorId, userId);
            return;
        }
        List<FirewallRule> firewallRules = firewallRuleRepository.listByVid(vendorId);
        Map<String, FirewallRule> firewallRuleMap = Maps.newHashMap();
        for (FirewallRule firewall : firewallRules) {
            firewallRuleMap.put(firewall.getSangforPolicyId(), firewall);
        }
        for (SangforFireWallParams model : models) {
            FirewallRule firewallRule = new FirewallRule();
            if (firewallRuleMap.containsKey(model.getSangforPolicyId())) {
                firewallRule = firewallRuleMap.get(model.getSangforPolicyId());
                BeanUtils.copyProperties(model, firewallRule);
                firewallRule.setGmtCreate(firewallRule.getGmtCreate());
                firewallRule.setMenderId(userId);
                firewallRule.setGmtModify(new Date());
                firewallRuleRepository.update(firewallRule);
                firewallRuleMap.remove(model.getSangforPolicyId());
                continue;
            }
            BeanUtils.copyProperties(model, firewallRule);
            firewallRule.setVendorId(vendorId);
            firewallRule.setCreatorId(userId);
            firewallRule.setGmtCreate(new Date());
            firewallRule.setIsDefault(false);
            firewallRuleRepository.save(firewallRule);
        }
        for (Map.Entry<String, FirewallRule> entry : firewallRuleMap.entrySet()) {
            firewallRuleRepository.remove(entry.getValue().getId(), userId);
        }

    }

    private void syncNetWork(List<SangforScpNetWorkParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            networkRepository.removeByVid(vendorId, userId);
            return;
        }

        List<Network> networks = networkRepository.listByVid(vendorId);
        Map<String, Network> networkMap = new HashMap<>();
        for (Network network : networks) {
            networkMap.put(network.getNetworkUuid(), network);
        }

        Network network;
        for (SangforScpNetWorkParams model : models) {
            if (networkMap.containsKey(model.getNetworkUuid())) {
                network = networkMap.get(model.getNetworkUuid());
                BeanUtils.copyProperties(model, network);
                network.setMenderId(userId);
                network.setGmtModify(new Date());
                network.setGuid(model.getNetworkUuid());
                networkRepository.update(network);
                networkMap.remove(model.getNetworkUuid());
                continue;
            }
            network = new Network();
            BeanUtils.copyProperties(model, network);
            network.setVendorId(vendorId);
            network.setCreatorId(userId);
            network.setGmtCreate(new Date());
            networkRepository.save(network);

            network.setGuid(model.getNetworkUuid());
            networkRepository.update(network);
        }

        for (Map.Entry<String, Network> entry : networkMap.entrySet()) {
            networkRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncPhyIf(List<SangforPhyIfParams> models, Map<String, Server> hostMap, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            bridgeInfoRepository.removeByVid(vendorId, userId);
            return;
        }
        List<SangforBridgeInfo> sangforBridgeInfos = bridgeInfoRepository.listByVid(vendorId);
        Map<String, SangforBridgeInfo> portMap = Maps.newHashMap();
        for (SangforBridgeInfo port : sangforBridgeInfos) {
            portMap.put(port.getAssembleUuid(), port);
        }

        Server server;
        String assembleUuid;
        for (SangforPhyIfParams model : models) {
            SangforBridgeInfo port = new SangforBridgeInfo();
            assembleUuid = model.getHostId() + "-" + model.getPortUuid() + "-" + model.getNetworkUuid();
            if (portMap.containsKey(assembleUuid)) {
                port = portMap.get(assembleUuid);
                BeanUtils.copyProperties(model, port);
                port.setGmtCreate(port.getGmtCreate());
                port.setMenderId(userId);
                port.setGmtModify(new Date());
                port.setNetworkUuid(model.getNetworkUuid());
                port.setName(model.getPortUuid());
                port.setHostid(model.getHostId());
                if (hostMap.containsKey(model.getHostId())) {
                    server = hostMap.get(model.getHostId());
                    port.setHostname(server.getName());
                }
                bridgeInfoRepository.update(port);
                portMap.remove(assembleUuid);
                continue;
            }

            BeanUtils.copyProperties(model, port);
            port.setVendorId(vendorId);
            port.setCreatorId(userId);
            port.setGmtCreate(new Date());
            port.setNetworkUuid(model.getNetworkUuid());
            port.setName(model.getPortUuid());
            port.setAssembleUuid(assembleUuid);
            port.setHostid(model.getHostId());
            if (hostMap.containsKey(model.getHostId())) {
                server = hostMap.get(model.getHostId());
                port.setHostname(server.getName());
            }
            bridgeInfoRepository.save(port);
        }
        for (Map.Entry<String, SangforBridgeInfo> entry : portMap.entrySet()) {
            bridgeInfoRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncDvVlanGroup(List<SangforVlanGroupParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            vlanGroupRepositpry.removeByVid(vendorId, userId);
            return;
        }
        List<SangforVlanGroup> sangforVlanGroups = vlanGroupRepositpry.listByVid(vendorId);
        Map<String, SangforVlanGroup> portMap = Maps.newHashMap();
        for (SangforVlanGroup group : sangforVlanGroups) {
            portMap.put(group.getAssembleUuid(), group);
        }

        String assembleUuid;
        for (SangforVlanGroupParams model : models) {
            SangforVlanGroup portGroup = new SangforVlanGroup();
            assembleUuid = model.getUuid() + "-" + model.getNetworkUuid();
            if (portMap.containsKey(assembleUuid)) {
                portGroup = portMap.get(assembleUuid);
                BeanUtils.copyProperties(model, portGroup);
                portGroup.setGmtCreate(portGroup.getGmtCreate());
                portGroup.setMenderId(userId);
                portGroup.setGmtModify(new Date());
                portGroup.setNetworkUuid(model.getNetworkUuid());
                vlanGroupRepositpry.update(portGroup);
                portMap.remove(assembleUuid);
                continue;
            }
            BeanUtils.copyProperties(model, portGroup);
            portGroup.setVendorId(vendorId);
            portGroup.setCreatorId(userId);
            portGroup.setGmtCreate(new Date());
            portGroup.setNetworkUuid(model.getNetworkUuid());
            portGroup.setAssembleUuid(assembleUuid);
            vlanGroupRepositpry.save(portGroup);
        }
        for (Map.Entry<String, SangforVlanGroup> entry : portMap.entrySet()) {
            vlanGroupRepositpry.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncServerGroup(List<SangForServerGroupModel> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            serverGroupRepository.removeByVid(vendorId, userId);
            return;
        }
        List<SangforServerGroup> groups = serverGroupRepository.listByVendor(vendorId);
        Map<String, SangforServerGroup> groupMap = Maps.newHashMap();
        for (SangforServerGroup group : groups) {
            groupMap.put(group.getUuid(), group);
        }
        for (SangForServerGroupModel model : models) {
            SangforServerGroup group = new SangforServerGroup();
            if (groupMap.containsKey(model.getId())) {
                group = groupMap.get(model.getId());
                BeanUtils.copyProperties(model, group);
                group.setGmtCreate(group.getGmtCreate());
                group.setMenderId(userId);
                group.setGmtModify(new Date());
                serverGroupRepository.update(group);
                groupMap.remove(group.getUuid());
                continue;
            }
            BeanUtils.copyProperties(model, group);
            group.setUuid(model.getId());
            group.setName(model.getName());
            group.setCloudType(model.getCloud_type());
            group.setVendorId(vendorId);
            group.setParentId(model.getParent_id());
            group.setPlatformType(model.getPlatform_type());
            group.setProjectId(model.getProject_id());
            group.setGroupType(model.getGroup_type());
            group.setAzId(model.getAz_id());
            group.setCreatorId(userId);
            group.setGmtCreate(new Date());
            serverGroupRepository.save(group);
        }
        for (Map.Entry<String, SangforServerGroup> entry : groupMap.entrySet()) {
            serverGroupRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncPhysicalServer(List<SangforHostParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            serverRepository.removeByVendor(vendorId, userId);
            return;
        }
        List<Server> hosts = serverRepository.listByVendor(vendorId);
        Map<String, Server> hostMap = Maps.newHashMap();
        for (Server server : hosts) {
            hostMap.put(server.getUuid(), server);
        }

        for (SangforHostParams model : models) {
            JSONObject body = JSON.parseObject(model.getDetail());
            Server servers = serverRepository.querybyUUid(model.getUuid());
            if(null != servers){
                List<CloudServer> cloudServers = cloudServerRepository.listByHid(servers.getId());
                Long count = cloudServers.stream().filter(o -> "RUNNING".equals(o.getStatus())).count();

                body.put("running_vms",count.intValue());
                String detail = JSONObject.toJSONString(body, SerializerFeature.WriteMapNullValue);
                model.setDetail(detail);
            }
        }

        for (SangforHostParams model : models) {
            Server server = new Server();
            if (hostMap.containsKey(model.getUuid())) {
                server = hostMap.get(model.getUuid());
                BeanUtils.copyProperties(model, server);
                server.setMenderId(userId);
                server.setGmtModify(new Date());
                server.setAzUuid(model.getSangforAzId());
                serverRepository.update(server);
                hostMap.remove(model.getUuid());
                continue;
            }
            BeanUtils.copyProperties(model, server);
            server.setVendorId(vendorId);
            server.setCreatorId(userId);
            server.setGmtCreate(new Date());
            server.setAzUuid(model.getSangforAzId());
            serverRepository.save(server);
        }
        for (Map.Entry<String, Server> entry : hostMap.entrySet()) {
            serverRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncSystemStorage(List<SangforStorageParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            storageRepository.removeByVendor(vendorId);
            return;
        }
        List<Storage> hosts = storageRepository.listByVendor(vendorId, "sangforSystem");
        Map<String, Storage> storageMap = Maps.newHashMap();
        for (Storage storage : hosts) {
            storageMap.put(storage.getUuid(), storage);
        }
        for (SangforStorageParams model : models) {
            Storage storage = new Storage();
            if (storageMap.containsKey(model.getUuid())) {
                storage = storageMap.get(model.getUuid());
                BeanUtils.copyProperties(model, storage);
                storage.setGmtCreate(storage.getGmtCreate());
                storage.setMenderId(userId);
                storage.setGmtModify(new Date());
                storageRepository.update(storage);
                storageMap.remove(model.getUuid());
                continue;
            }
            BeanUtils.copyProperties(model, storage);
            storage.setVendorId(vendorId);
            storage.setCreatorId(userId);
            storage.setGmtCreate(new Date());
            storageRepository.save(storage);
        }
        for (Map.Entry<String, Storage> entry : storageMap.entrySet()) {
            storageRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncInterfaces(List<SangforInterfacesParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            ifaceRepository.removeByVendor(vendorId);
            return;
        }
        List<SangforIface> ifaces = ifaceRepository.listByVid(vendorId);
        Map<String, SangforIface> ifaceMap = Maps.newHashMap();
        for (SangforIface iface : ifaces) {
            ifaceMap.put(iface.getUuid(), iface);
        }
        for (SangforInterfacesParams model : models) {
            SangforIface iface = new SangforIface();
            if (ifaceMap.containsKey(model.getUuid())) {
                iface = ifaceMap.get(model.getUuid());
                BeanUtils.copyProperties(model, iface);
                ifaceRepository.update(iface);
                ifaceMap.remove(model.getUuid());
                continue;
            }
            BeanUtils.copyProperties(model, iface);
            iface.setVendorId(vendorId);
            ifaceRepository.save(iface);
        }
        for (Map.Entry<String, SangforIface> entry : ifaceMap.entrySet()) {
            ifaceRepository.remove(entry.getValue().getId(), userId);
        }
    }

    private void syncCommunication(List<SangforInterfacesParams> models, Long vendorId, Long userId) throws Exception {
        communicationRepository.removeByVid(vendorId);
        for (SangforInterfacesParams model : models) {
            SangforCommunication cnt = new SangforCommunication();
            BeanUtils.copyProperties(model, cnt);
            cnt.setVendorId(vendorId);
            cnt.setCreatorId(userId);
            cnt.setGmtCreate(new Date());
            communicationRepository.save(cnt);
        }
    }

    private void syncStorage(List<SangforStorageParams> models, Long vendorId, Long userId) throws Exception {
        if (ListTool.isEmpty(models)) {
            dataStoreRepository.removeByVendor(vendorId, userId);
            return;
        }
        List<DataStore> dataStores = dataStoreRepository.listByVendor(vendorId);
        Map<String, DataStore> dataStoreMap = Maps.newHashMap();
        for (DataStore dataStore : dataStores) {
            dataStoreMap.put(dataStore.getGuid(), dataStore);
        }
        for (SangforStorageParams model : models) {
            if (dataStoreMap.containsKey(model.getUuid())) {
                DataStore dataStore = dataStoreMap.get(model.getUuid());
                BeanUtils.copyProperties(model, dataStore);
                dataStore.setGuid(model.getUuid());
                dataStore.setGmtCreate(dataStore.getGmtCreate());
                dataStore.setMenderId(userId);
                dataStore.setGmtModify(new Date());
                dataStore.setAzUuid(model.getAzId());
                dataStoreRepository.update(dataStore);
                dataStoreMap.remove(model.getUuid());
                continue;
            }

            DataStore dataStore = new DataStore();
            BeanUtils.copyProperties(model, dataStore);
            dataStore.setId(null);
            dataStore.setGuid(model.getUuid());
            dataStore.setVendorId(vendorId);
            dataStore.setCreatorId(userId);
            dataStore.setGmtCreate(new Date());
            dataStore.setAzUuid(model.getAzId());
            dataStoreRepository.save(dataStore);
        }
        for (Map.Entry<String, DataStore> entry : dataStoreMap.entrySet()) {
            dataStoreRepository.remove(entry.getValue().getId(), userId);
        }
    }
}
