package com.bocloud.ims.service.resource;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.common.AuthDriver;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.OSTenantModel;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.common.Tenant;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.OSTenant;
import com.bocloud.ims.entity.resource.PoolGroup;
import com.bocloud.ims.interfaces.resource.SyncService;
import com.bocloud.ims.interfaces.resource.VendorProjectService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.OSTenantRepository;
import com.bocloud.ims.repository.resource.PoolGroupRepository;
import com.bocloud.ims.service.internal.SmsTenantService;
import com.bocloud.ims.service.transporter.vendor.OpenstackTransporter;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Service("vendorProjectService")
public class VendorProjectServiceImpl implements VendorProjectService {

	private Logger logger = LoggerFactory.getLogger(VendorProjectServiceImpl.class);
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private PoolGroupRepository poolGroupRepository;
	@Autowired
	private SmsTenantService smsTenantService;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private AuthDriver authDriver;
	@Autowired
	private OSTenantRepository osTenantRepository;
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;
	@Autowired
	@Lazy
	private OpenstackTransporter openstackTransporter;

	@Override
	public BocloudResult handle(Long tenantId, List<Long> poolIds, RequestContext context) {
		String path = CloudVendor.class.getSimpleName() + "_OPENSTACK_PROJECT_" + tenantId;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			if (ListTool.isEmpty(poolIds)) {
				return new BocloudResult<>(true, "");
			}
			BocloudResult<Tenant> BocloudResult = smsTenantService.detail(tenantId);
			if (BocloudResult.isFailed()) {
				return new BocloudResult<>(false, BocloudResult.getMessage());
			}
			Tenant tenant = BocloudResult.getData();
			if (null == tenant) {
				return new BocloudResult<>(false, "租户不存在");
			}
			List<PoolGroup> groups = poolGroupRepository.listByIds(poolIds);
			List<Long> vendorIds = new ArrayList<>();
			for (PoolGroup group : groups) {
				vendorIds.add(group.getVendorId());
			}
			List<CloudVendor> vendors = cloudVendorRepository.listByIds(vendorIds);
			Map<String, OSTenant> map = new HashMap<>();
			for (CloudVendor vendor : vendors) {
				if ((CloudProvider.OPENSTACK.name().equals(vendor.getType())
						|| CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
						|| CloudProvider.EASYSTACK.name().equals(vendor.getType()))
						&& !map.containsKey(vendor.getUuid())) {
					OSTenant osTenant = osTenantRepository.getByTenantId(tenantId, vendor.getId());
					if (null == osTenant) {
						osTenant = new OSTenant();
						osTenant.setTenantId(tenantId);
						osTenant.setVendorId(vendor.getId());
						osTenant.setName("TENANT_" + tenant.getAccount() + "_" + System.currentTimeMillis());
						map.put(vendor.getUuid(), osTenant);
					}
				}
			}
			List<Future<BocloudResult>> futures = new ArrayList<>();
			if (!map.isEmpty()) {
				List<OSTenant> providers = new ArrayList<>();
				for (String key : map.keySet()) {
					OSTenant osTenant = map.get(key);
					providers.add(osTenant);
					OSTenantModel osModel = new OSTenantModel();
					osModel.setName(map.get(key).getName());
					osModel.setRemark(map.get(key).getName());
					futures.add(taskExecutor.submit(() -> authDriver.createProject(key, osModel)));
				}
				for (int i = 0; i < futures.size(); i++) {
					BocloudResult result = futures.get(i).get(30, TimeUnit.MINUTES);
					if (null != result && result.isSuccess()) {
						Long vendorId = providers.get(i).getVendorId();
						// 保存项目或租户信息
						OSTenant osTenant = JSONObject.parseObject(JSONObject.toJSONString(result.getData()),
								OSTenant.class);
						osTenant.setCreatorId(context.getTarget());
						osTenant.setGmtCreate(new Date());
						osTenant.setVendorId(vendorId);
						osTenant.setTenantId(tenantId);
						osTenantRepository.save(osTenant);
						openstackTransporter.syncProjectSecurityGroups(vendorId, context.getTarget());
					}
				}
			}
			return new BocloudResult<>(true, "保存租户项目成功");
		} catch (Exception e) {
			return new BocloudResult<>(false, "保存租户项目失败");
		}
	}

	@Override
	public BocloudResult deleteByTenant(Long tenantId) {
		try {
			List<OSTenant> osTenants = osTenantRepository.listByTenant(tenantId);
			for (OSTenant osTenant : osTenants) {
				CloudVendor vendor = cloudVendorRepository.query(osTenant.getVendorId());
				if (null != vendor) {
					if (CloudProvider.OPENSTACK.name().equals(vendor.getType())
							|| CloudProvider.FUSIONCLOUD.name().equals(vendor.getType())
							|| CloudProvider.EASYSTACK.name().equals(vendor.getType())) {
						authDriver.removeProject(vendor.getUuid(), osTenant.getName());
					} else {
						authDriver.removeProject(vendor.getUuid(), vendor.getUuid());
					}
				}
			}
			osTenantRepository.removeByTenant(tenantId);
			return new BocloudResult<>(true, "删除成功");
		} catch (Exception e) {
			logger.error("Get error message：{}", e);
			return new BocloudResult<>(false, "删除失败");
		}
	}

	@Override
	public OSTenant getAncestorProject(Long vendorId, Long tenantId) {
		try {
			// 查询租户的祖先租户
			BocloudResult<Tenant> result = smsTenantService.detail(tenantId);
			if (result.isFailed()) {
				return null;
			}
			Tenant tenant = result.getData();
			if (null == tenant) {
				return null;
			}
			OSTenant osTenant = osTenantRepository.getByTenantId(tenant.getId(), vendorId);
			if (null == osTenant) {
				return null;
			}
			return osTenant;
		} catch (Exception e) {
			logger.error("Get error message：{}", e);
			return null;
		}
	}

	// 递归查询父菜单
	private Tenant getParents(Tenant tenant) {
		Long parentId = tenant.getParentId();
		if (null == parentId || 0L == parentId) {
			return tenant;
		} else {
			BocloudResult<Tenant> result = smsTenantService.detail(parentId);
			if (result.isFailed()) {
				return null;
			}
			Tenant parent = result.getData();
			if (null == parent) {
				return null;
			}
			return this.getParents(parent);
		}
	}

}
