package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.ZoneDriver;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.ResultTools;
import com.bocloud.ims.entity.common.Project;
import com.bocloud.ims.entity.common.TenantPool;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.PoolGroup;
import com.bocloud.ims.entity.resource.PoolGroupZone;
import com.bocloud.ims.entity.resource.Region;
import com.bocloud.ims.entity.resource.Zone;
import com.bocloud.ims.interfaces.resource.RegionService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.PoolGroupRepository;
import com.bocloud.ims.repository.resource.PoolGroupZoneRepository;
import com.bocloud.ims.repository.resource.RegionRepository;
import com.bocloud.ims.repository.resource.ZoneRepository;
import com.bocloud.ims.service.internal.SmsProjectService;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

/**
 * 区域Service接口实现(子区域为zone)
 *
 * @author dongkai
 */
@Service("regionService")
public class RegionServiceImpl implements RegionService {

	private static Logger logger = LoggerFactory.getLogger(RegionServiceImpl.class);
	@Autowired
	private RegionRepository regionRepository;
	@Autowired
	private ZoneRepository zoneRepository;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private PoolGroupRepository poolGroupRepository;
	@Autowired
	private SmsProjectService smsProjectService;
	@Autowired
	private SmsTenantService smsTenantService;
	@Autowired
	private ZoneDriver zoneDriver;
	@Autowired
	private PoolGroupZoneRepository poolGroupZoneRepository;

	@Override
	public BocloudResult<List<Region>> list(Long vendorId) {
		try {
			List<Region> list = regionRepository.list(vendorId);
			return new BocloudResult<>(true, list, "查询成功!");
		} catch (Exception e) {
			logger.error("list region failure:", e);
			return new BocloudResult<>(false, "查询失败!");
		}
	}

	@Override
	public BocloudResult<List<Zone>> listZone(Long vendorId, String regionId) {
		try {
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			Assert.notNull(vendor, "云平台不存在");
			List<Zone> list = zoneRepository.listByRegionId(regionId, vendorId);
			return new BocloudResult<>(true, list, "查询成功!");
		} catch (Exception e) {
			logger.error("list region failure:", e);
			return new BocloudResult<>(false, "查询失败!");
		}
	}

	@Override
	public BocloudResult<List<PoolGroupZone>> listRegionByGroup(JSONObject params) {
		try {
			if (null == params) {
				return new BocloudResult<>(false, "参数格式错误");
			}
			Long poolGroupId = params.getLong("poolGroupId");
			PoolGroup poolGroup = poolGroupRepository.query(poolGroupId);
			if (null == poolGroup) {
				logger.error("资源池不存在!");
				return new BocloudResult<>(false, "资源池不存在");
			}
			List<PoolGroupZone> poolGroupZones = poolGroupZoneRepository.listByGroupId(poolGroup.getVendorId(),
					poolGroup.getId(), null, null);
			return new BocloudResult<>(true, poolGroupZones, "查询成功!");
		} catch (Exception e) {
			logger.error("list region failure:", e);
			return new BocloudResult<>(false, "查询失败!");
		}
	}

	@Override
	public BocloudResult<List<Region>> listByBusiness(JSONObject params, RequestContext context) {
		try {
			Long vendorId = params.getLong(Common.VENDORID);
			BocloudResult<Project> projResult = smsProjectService.detail(context.getProject());
			if (projResult.isFailed() || null == projResult.getData()) {
				return new BocloudResult<>(false, "当前用户所在项目不存在");
			}
			List<TenantPool> pools = smsTenantService.listPoolByTenant(context.getTenant());
			if (ListTool.isEmpty(pools)) {
				return new BocloudResult<>(false, "未找到任何云平台");
			}
			Map<Long, Region> regionMaps = Maps.newHashMap();
			for (TenantPool pool : pools) {
				List<Region> regions = regionRepository.listByGroup(pool.getPoolGroupId(), vendorId);
				if (null != regions && regions.size() > 0) {
					for (Region region : regions) {
						regionMaps.put(region.getId(), region);
					}
				}
			}
			return new BocloudResult<>(true, new ArrayList<>(regionMaps.values()), "查询成功");
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult<>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult condition(String params, RequestContext context) {
		JSONObject object = JSONTools.isJSONObj(params);
		if (null == object) {
			return ResultTools.formatErrResult();
		}
		String condition = object.getString("condition");
		if ("listregionbygroup".equalsIgnoreCase(condition)) {
			return this.listRegionByGroup(object);
		} else if ("listRegionByBusiness".equalsIgnoreCase(condition)) {
			return this.listByBusiness(object, context);
		} else if ("listByTenant".equalsIgnoreCase(condition)) {
			return this.listByTenant(object, context);
		} else {
			return ResultTools.formatErrResult();
		}
	}

	/**
	 * 根据租户的资源池查询公有云的区域 可用区
	 * 
	 * @param object
	 * @param context
	 * @return
	 */
	public BocloudResult<List<Region>> listByTenant(JSONObject object, RequestContext context) {
		try {
			List<TenantPool> pools = smsTenantService.listPoolByTenant(context.getTenant());
			if (ListTool.isEmpty(pools)) {
				return new BocloudResult<>(false, "当前租户未授权资源池！");
			}
			String vendorType = object.getString("vendorType");
			if (StringUtils.isEmpty(vendorType)) {
				return new BocloudResult<>(false, "平台类型参数异常！");
			}
			List<Long> ids = pools.stream().map(TenantPool::getPoolGroupId).collect(Collectors.toList());
			List<PoolGroup> poolGroups = poolGroupRepository.listByIds(ids, vendorType);

			Map<String, Region> regionMap = new HashMap<>();
			for (PoolGroup poolGroup : poolGroups) {
				String region = poolGroup.getRegion();
				String availablitiyZone = poolGroup.getAvailablitiyZone();

				Region reg = null;
				if (regionMap.containsKey(region)) {
					reg = regionMap.get(region);
				} else {
					reg = regionRepository.getByRegionId(region, poolGroup.getVendorId());
				}
				if (null == reg) {
					continue;
				}
				Set<String> zoneIds = reg.getZoneIds();
				if (null == zoneIds) {
					zoneIds = new HashSet<>();
				}
				zoneIds.add(availablitiyZone);
				reg.setZoneIds(zoneIds);
				regionMap.put(region, reg);
			}
			if (regionMap.values().isEmpty()) {
				return new BocloudResult<>(false, "当前租户暂无该服务可用区域！");
			}
			List<Region> regionList = new ArrayList<>();
			// 获取对象 并 去重
			Set<Entry<String, Region>> entrySet = regionMap.entrySet();
			for (Entry<String, Region> entry : entrySet) {
				Region region = entry.getValue();
				Set<String> zoneIds = region.getZoneIds();
				List<Zone> zones = zoneRepository.listByZoneIds(region.getRegionId(), new ArrayList<>(zoneIds),
						region.getVendorId());
				if (!ListTool.isEmpty(zones)) {
					region.setZones(zones);
				}
				regionList.add(region);
			}
			return new BocloudResult<>(true, regionList, "查询成功");
		} catch (Exception e) {
			logger.error("Get error message：", e);
			return new BocloudResult<>(false, "查询失败");
		}
	}

	@Override
	public BocloudResult zones(Long id, Long vendorId, String type) {
		try {
			if (null == type || null == vendorId) {
				return new BocloudResult(false, "参数有误");
			}
			Region region = regionRepository.query(id);
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			Assert.notNull(region, "当前区域数据不存在");
			Assert.notNull(vendor, "云平台数据不存在");
			BocloudResult result = zoneDriver.queryByRegionId(vendor.getUuid(), type, region.getRegionId());
			if (result.isFailed()) {
				logger.error("获取当前区域下可用区信息失败:", result.getMessage());
				return new BocloudResult(false, "获取当前区域下可用区信息失败");
			}
			return new BocloudResult(true, result.getData(), "查询成功");
		} catch (Exception e) {
			logger.error("list zones failure:", e);
			return new BocloudResult(false, "查询失败:" + e.getMessage());
		}
	}

}
