package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.utils.StringUtils;
import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.ims.common.Constant;
import com.bocloud.ims.common.utils.MapUtils;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.Resource;
import com.bocloud.ims.interfaces.resource.CloudServerAllocationService;
import com.bocloud.ims.interfaces.resource.ResourceAllocateService;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.ResourceRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 私有云虚拟机自动分配到用户
 * <p>
 * 根据云主机根据ip地址获取堡垒机的负责人信息，从而将云主机分配给相应用户
 * </p>
 *
 * @author sxp
 * @since 2022/11/23
 */
@Service
public class CloudServerAllocationServiceImpl implements CloudServerAllocationService {
    private static Logger logger = LoggerFactory.getLogger(CloudServerAllocationServiceImpl.class);

    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private ResourceAllocateService resourceAllocateService;

    @Override
    public BocloudResult assign() {
        JSONObject result = new JSONObject();
        long begin = System.currentTimeMillis();
        logger.info("私有云虚拟机自动分配到用户...");

        try {
            // 获取堡垒机中资产的ip和负责人id的对应关系
            List<Resource> jumpServerResourceList = resourceRepository.listJumpServerResource();
            int size = jumpServerResourceList.size();
            result.put("jumpServerResourceList.size", size);
            logger.info("堡垒机中资产的ip和负责人id的对应关系数据行数为{}", size);

            if (size == 0) {
                return new BocloudResult(true, result, "success");
            }

            Map<String, Long> ip2UserIdMap = new HashMap<>(MapUtils.capacity(size));
            for (Resource rc : jumpServerResourceList) {
                ip2UserIdMap.put(rc.getPrivateIps(), rc.getId());
            }

            // 堡垒机里面的机器，一般都是私有云的虚拟机
            List<String> vendorTypes = new ArrayList<>(2);
            vendorTypes.add("VMWARE");
            vendorTypes.add("SANGFOR");
            List<CloudServer> cloudServerList = cloudServerRepository.listUnassignedCloudServers(vendorTypes);
            size = (cloudServerList == null) ? 0 : cloudServerList.size();
            result.put("cloudServerList.size", size);
            logger.info("wmware、深信服云平台未分配所属用户的云主机数量为{}", size);

            if (size == 0) {
                return new BocloudResult(true, result, "success");
            }

            List<String> ipList;
            List<JSONObject> ips;
            String vendorType, privateIps;
            JSONObject ipsJson;
            Collection<Object> ipsValue;
            Set<String> ipSet;
            Integer ipValue;

            Map<String, CloudServer> ip2CloudServerMap = new HashMap<>(MapUtils.capacity(size));
            for (CloudServer vm : cloudServerList) {
                privateIps = vm.getPrivateIps();
                vendorType = vm.getVendorType();
                if (StringUtils.isEmpty(privateIps)) {
                    continue;
                }
                if ("VMWARE".equals(vendorType)) {
                    ips = JSON.parseArray(vm.getPrivateIps(), JSONObject.class);
                    ipList = ips.stream()
                            .filter(json -> (json.containsKey("address") && !StringUtils.isEmpty(json.getString("address"))))
                            .map(json -> json.getString("address"))
                            .collect(Collectors.toList());
                } else {
                    // SANGFOR
                    // {"net0":{"172.22.24.248":0},"net1":{"10.101.20.23":1}}
                    ipList = new ArrayList<>();
                    ipsJson = JSON.parseObject(privateIps, JSONObject.class);
                    ipsValue = ipsJson.values();
                    if (ipsValue == null) {
                        continue;
                    } else {
                        ips = JSON.parseArray(JSON.toJSONString(ipsValue), JSONObject.class);
                        for (JSONObject itemJson : ips) {
                            ipSet = itemJson.keySet();
                            if (ipSet == null || ipSet.isEmpty()) {
                                continue;
                            }
                            for (String itemIp : ipSet) {
                                ipValue = (Integer) itemJson.get(itemIp);
                                if (ipValue != null && ipValue.intValue() == 1) {
                                    ipList.add(itemIp);
                                }
                            }
                        }
                    }
                }
                if (ipList == null || ipList.isEmpty()) {
                    continue;
                }
                for (String ip : ipList) {
                    ip2CloudServerMap.put(ip, vm);
                }
            }
            size = ip2CloudServerMap.size();
            result.put("ip2CloudServerMap.size", size);
            logger.info("解析云主机的IP，数量为{}", size);

            if (size == 0) {
                return new BocloudResult(true, result, "success");
            }

            List<Long> tenantIds = new ArrayList<>(1);
            tenantIds.add(Constant.ZJKY_TENANT_ID);

            ResourceCategory resourceCategory = ResourceCategory.Computer;
            RequestContext context = new RequestContext(RequestContext.Catalog.Manager, 1L, Constant.ZJKY_TENANT_ID, 0L, "*");
            String ip;
            CloudServer cloudServer;
            JSONObject object;
            Long userId, count = 0L;
            List<Long> ids;
            Set<Map.Entry<String, CloudServer>> entrySet = ip2CloudServerMap.entrySet();

            for (Map.Entry<String, CloudServer> entry : entrySet) {
                ip = entry.getKey();
                cloudServer = entry.getValue();

                if (!ip2UserIdMap.containsKey(ip)) {
                    continue;
                }
                userId = ip2UserIdMap.get(ip);
                if (userId == null) {
                    continue;
                }

                object = new JSONObject();

                ids = new ArrayList<>(1);
                ids.add(cloudServer.getId());

                object.put("ids", ids);
                object.put("userId", userId);
                object.put("projectId", 0L);
                object.put("tenantId", Constant.ZJKY_TENANT_ID);
                object.put("tenantIds", tenantIds);
                object.put("resourceCategory", resourceCategory.name());
                object.put("vendorType", cloudServer.getVendorType());

                try {
                    count++;
                    resourceAllocateService.assign(object, resourceCategory, context);
                } catch (Exception e) {
                    logger.error(e.getMessage() + "，参数为:" + object.toJSONString(), e);
                }
            }

            result.put("resourceAllocateService.assign.count", count);
            logger.info("调用云主机分配接口，调用次数为{}", count);

            long cost = System.currentTimeMillis() - begin;
            result.put("cost", cost);
            logger.info("私有云虚拟机自动分配到用户，耗时{}毫秒", cost);

            return new BocloudResult(true, result, "success");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new BocloudResult(false, result, e.getMessage());
        }
    }
}
