package com.bocloud.ims.service.internal;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.model.common.DurationModel;
import com.bocloud.cmp.model.common.DurationModel.Mode;
import com.bocloud.cmp.model.common.ElementModel;
import com.bocloud.cmp.model.common.OrderItem;
import com.bocloud.cmp.model.common.ResourceModel;
import com.bocloud.cmp.model.common.ServiceOrder;
import com.bocloud.cmp.model.common.SpecModel;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.ims.entity.common.User;
import com.bocloud.ims.entity.resource.CloudServer;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ElasticIp;
import com.bocloud.ims.entity.resource.FloatingIp;
import com.bocloud.ims.entity.resource.LoadBalancer;
import com.bocloud.ims.entity.resource.Volume;
import com.bocloud.ims.entity.resource.Vpc;
import com.bocloud.ims.repository.resource.VolumeRepository;
import com.bocloud.nms.enums.ChargeCommon;
import com.bocloud.nms.enums.ChargeCommon.ChargeMode;
import com.bocloud.nms.enums.ChargeCommon.Type;
import com.bocloud.nms.enums.OrderItemStatus;

/**
 * 订单相关处理
 *
 * @author wangyu
 * @Date 2020-7-20 19:45:08
 */
@Component
public class ResourceOrderService {

	private static final Logger logger = LoggerFactory.getLogger(ResourceOrderService.class);
	@Autowired
	private CosInternalService cosInternalService;
	@Autowired
	private VolumeRepository volumeRepository;

	/**
	 * 创建订单
	 *
	 * @param vendorId
	 * @param serviceCode
	 * @param user
	 * @param slaAgreed
	 * @param projectId
	 * @return
	 */
	public BocloudResult createOrder(Long vendorId, String serviceCode, Long tenantId, Long userId, Boolean slaAgreed,
			Long projectId) {
		// 下单
		ServiceOrder order = new ServiceOrder();
		order.setServiceCode(serviceCode);
		order.setChargeMode(ChargeMode.PostCharge);
		order.setSlaAgreed(true);
		order.setResourceStatus(ChargeCommon.ResourceStatus.creating);
		order.setOrderStatus(ChargeCommon.OrderStatus.paid);
		order.setAutoRenew(false);
		order.setUserId(userId);
		order.setProjectId(projectId);
		order.setTenantId(tenantId);
		order.setVendorId(vendorId);
		order.setType(Type.apply);
		return cosInternalService.createOrder(order);
	}

	/**
	 * 创建订单明细
	 *
	 * @param orderId
	 * @param serviceCode
	 * @param server
	 * @return
	 */
	public BocloudResult<OrderItem> createServerItem(Long orderId, String serviceCode, CloudServer server,
			CloudVendor vendor) {
		OrderItem item = new OrderItem();
		DurationModel duration = new DurationModel();
		item.setOrderId(orderId);
		item.setCatalog(OrderItem.Catalog.single);
		item.setStatus(OrderItemStatus.Opening);
		item.setServiceCode(serviceCode);
		duration.setMode(Mode.Hour);
		item.setDuration(JSONObject.toJSONString(duration));
		List<ResourceModel> resources = new ArrayList<>();
		resources.add(new ResourceModel(server.getName(), server.getInstanceId(), serviceCode, server.getInstanceId(), server.getUuid()));
		item.setResources(JSONObject.toJSONString(resources));
		List<ElementModel> elements = new ArrayList<>();
		ElementModel vmElement = new ElementModel();
		vmElement.setCount(1);
		vmElement.setServiceCode(serviceCode);
		List<SpecModel> specModels = new ArrayList<>();
		specModels.add(new SpecModel(server.getCpu(), null, null));
		specModels.add(new SpecModel(null, server.getMemory(), null));

		vmElement.setSpecs(specModels);
		vmElement.setUuid(server.getInstanceId());
		elements.add(vmElement);
		item.setElements(JSONObject.toJSONString(elements));
		item = cosInternalService.createOrderItem(item);
		if (null == item) {
			return new BocloudResult<>(false, "创建订单明细失败");
		}
		logger.info("云主机{}分配创建的订单明细：{}", server.getName(), JSONObject.toJSON(item));
		return new BocloudResult<>(true, item, "创建成功");
	}

	/**
	 * 云硬盘服务类型
	 * 
	 * @param vendor
	 * @return
	 */
	private String getVolumeServiceCode(CloudVendor vendor) {
		String serviceCode = "";
		switch (CloudProvider.valueOf(vendor.getType())) {
		case OPENSTACK:
		case EASYSTACK:
		case MANAGEONE:
		case AZURE:
			serviceCode = vendor.getType().toLowerCase() + ".standard.volume";
			break;
		case TCE:
		case ALIYUN:
			serviceCode = vendor.getType().toLowerCase() + ".standard.cbs";
			break;
		default:
			return serviceCode;
		}
		return serviceCode;
	}

	/**
	 * 创建云硬盘订单
	 *
	 * @param orderId
	 * @param serviceCode
	 * @param volume
	 * @param vendor
	 * @return
	 */
	public BocloudResult<OrderItem> createVolumeItem(Long orderId, String serviceCode, Volume volume,
			CloudVendor vendor) {
		OrderItem item = new OrderItem();
		DurationModel duration = new DurationModel();
		item.setOrderId(orderId);
		item.setCatalog(OrderItem.Catalog.single);
		item.setStatus(OrderItemStatus.Opening);
		item.setServiceCode(serviceCode);
		duration.setMode(Mode.Hour);
		item.setDuration(JSONObject.toJSONString(duration));
		List<ResourceModel> resources = new ArrayList<>();
		resources.add(new ResourceModel(volume.getName(), volume.getVolumeUuid(), serviceCode, volume.getVolumeUuid(), volume.getUuid()));
		item.setResources(JSONObject.toJSONString(resources));
		List<ElementModel> elements = new ArrayList<>();
		ElementModel element = new ElementModel();
		element.setCount(1);
		element.setServiceCode(serviceCode);
		List<SpecModel> specModels = new ArrayList<>();
		specModels.add(new SpecModel(null, null, volume.getSize()));
		element.setSpecs(specModels);
		element.setUuid(volume.getVolumeUuid());
		elements.add(element);
		item.setElements(JSONObject.toJSONString(elements));
		item = cosInternalService.createOrderItem(item);
		if (null == item) {
			return new BocloudResult<>(false, "创建订单明细失败");
		}
		logger.info("云硬盘{}分配创建的订单明细：{}", volume.getName(), JSONObject.toJSON(item));
		return new BocloudResult<>(true, item, "创建成功");
	}

	/**
	 * 创建公网IP订单
	 *
	 * @param orderId
	 * @param serviceCode
	 * @param floatingIp
	 * @param vendor
	 * @return
	 */
	public BocloudResult<OrderItem> createFipItem(Long orderId, String serviceCode, FloatingIp floatingIp,
			CloudVendor vendor) {
		OrderItem item = new OrderItem();
		DurationModel duration = new DurationModel();
		item.setOrderId(orderId);
		item.setCatalog(OrderItem.Catalog.single);
		item.setStatus(OrderItemStatus.Opening);
		item.setServiceCode(serviceCode);
		duration.setMode(Mode.Hour);
		item.setDuration(JSONObject.toJSONString(duration));
		List<ResourceModel> resources = new ArrayList<>();
		resources
				.add(new ResourceModel(floatingIp.getFloatingIpAddress(), floatingIp.getFloatingIpUuid(), serviceCode, floatingIp.getFloatingIpUuid(), floatingIp.getUuid()));
		item.setResources(JSONObject.toJSONString(resources));
		List<ElementModel> elements = new ArrayList<>();
		ElementModel element = new ElementModel();
		element.setCount(1);
		element.setServiceCode(serviceCode);
		List<SpecModel> specModels = new ArrayList<>();
		element.setSpecs(specModels);
		element.setUuid(floatingIp.getFloatingIpUuid());
		elements.add(element);
		item.setElements(JSONObject.toJSONString(elements));
		item = cosInternalService.createOrderItem(item);
		if (null == item) {
			return new BocloudResult<>(false, "创建订单明细失败");
		}
		logger.info("公网IP{}分配创建的订单明细：{}", floatingIp.getFloatingIpAddress(), JSONObject.toJSON(item));
		return new BocloudResult<>(true, item, "创建成功");
	}

	/**
	 * 创建公网IP订单
	 *
	 * @param orderId
	 * @param serviceCode
	 * @param floatingIp
	 * @param vendor
	 * @return
	 */
	public BocloudResult<OrderItem> createElasticIpItem(Long orderId, String serviceCode, ElasticIp elasticIp,
			CloudVendor vendor) {
		OrderItem item = new OrderItem();
		DurationModel duration = new DurationModel();
		item.setOrderId(orderId);
		item.setCatalog(OrderItem.Catalog.single);
		item.setStatus(OrderItemStatus.Opening);
		item.setServiceCode(serviceCode);
		duration.setMode(Mode.Hour);
		item.setDuration(JSONObject.toJSONString(duration));
		List<ResourceModel> resources = new ArrayList<>();
		resources.add(new ResourceModel(elasticIp.getPrivateIpAddress(), elasticIp.getElasticIpUuid(), serviceCode, elasticIp.getElasticIpUuid(), elasticIp.getUuid()));
		item.setResources(JSONObject.toJSONString(resources));
		List<ElementModel> elements = new ArrayList<>();
		ElementModel element = new ElementModel();
		element.setCount(1);
		element.setServiceCode(serviceCode);
		List<SpecModel> specModels = new ArrayList<>();
		element.setSpecs(specModels);
		element.setUuid(elasticIp.getElasticIpUuid());
		elements.add(element);
		item.setElements(JSONObject.toJSONString(elements));
		item = cosInternalService.createOrderItem(item);
		if (null == item) {
			return new BocloudResult<>(false, "创建订单明细失败");
		}
		logger.info("公网IP{}分配创建的订单明细：{}", elasticIp.getPrivateIpAddress(), JSONObject.toJSON(item));
		return new BocloudResult<>(true, item, "创建成功");
	}

	/**
	 * 创建vpc订单
	 *
	 * @param orderId
	 * @param serviceCode
	 * @param vpc
	 * @param vendor
	 * @return
	 */
	public BocloudResult<OrderItem> createVpcItem(Long orderId, String serviceCode, Vpc vpc, CloudVendor vendor) {
		OrderItem item = new OrderItem();
		DurationModel duration = new DurationModel();
		item.setOrderId(orderId);
		item.setCatalog(OrderItem.Catalog.single);
		item.setStatus(OrderItemStatus.Opening);
		item.setServiceCode(serviceCode);
		duration.setMode(Mode.Hour);
		item.setDuration(JSONObject.toJSONString(duration));
		List<ResourceModel> resources = new ArrayList<>();
		resources.add(new ResourceModel(vpc.getName(), vpc.getVpcId(), serviceCode, vpc.getVpcId(), vpc.getUuid()));
		item.setResources(JSONObject.toJSONString(resources));
		List<ElementModel> elements = new ArrayList<>();
		ElementModel element = new ElementModel();
		element.setCount(1);
		element.setServiceCode(serviceCode);
		List<SpecModel> specModels = new ArrayList<>();
		element.setSpecs(specModels);
		element.setUuid(vpc.getVpcId());
		item.setBasicPrice(BigDecimal.valueOf(0L));
		item.setFinalPrice(BigDecimal.valueOf(0L));
		elements.add(element);
		item.setElements(JSONObject.toJSONString(elements));
		item = cosInternalService.createOrderItem(item);
		if (null == item) {
			return new BocloudResult<>(false, "创建订单明细失败");
		}
		logger.info("VPC{}分配创建的订单明细：{}", vpc.getName(), JSONObject.toJSON(item));
		return new BocloudResult<>(true, item, "创建成功");
	}

	/**
	 * 处理订单明细状态
	 *
	 * @param items
	 * @param status
	 */
	public void processOrderItemStatus(List<OrderItem> items, OrderItemStatus status) {
		for (OrderItem item : items) {
			cosInternalService.updateItemStatus(item.getSn(), status.name());
		}
	}

	/**
	 * 处理订单状态
	 *
	 * @param orders
	 * @param status
	 */
	public void processOrderStatus(List<ServiceOrder> orders, ChargeCommon.ResourceStatus status) {
		for (ServiceOrder order : orders) {
			cosInternalService.updateStatus(order.getId(), status.name());
		}
	}

    public BocloudResult<OrderItem> createLoadBalancerItem(Long orderId, String slbServiceCode,
        LoadBalancer loadBalancer, CloudVendor vendor) {
        OrderItem item = new OrderItem();
        DurationModel duration = new DurationModel();
        item.setOrderId(orderId);
        item.setCatalog(OrderItem.Catalog.single);
        item.setStatus(OrderItemStatus.Opening);
        item.setServiceCode(slbServiceCode);
        duration.setMode(Mode.Hour);
        item.setDuration(JSONObject.toJSONString(duration));
        List<ResourceModel> resources = new ArrayList<>();
        resources.add(new ResourceModel(loadBalancer.getName(), loadBalancer.getLbUuid(), slbServiceCode, loadBalancer.getLbUuid(), loadBalancer.getUuid()));
        item.setResources(JSONObject.toJSONString(resources));
        List<ElementModel> elements = new ArrayList<>();
        ElementModel element = new ElementModel();
        element.setCount(1);
        element.setServiceCode(slbServiceCode);
        List<SpecModel> specModels = new ArrayList<>();
        element.setSpecs(specModels);
        element.setUuid(loadBalancer.getLbUuid());
        item.setBasicPrice(BigDecimal.valueOf(0L));
        item.setFinalPrice(BigDecimal.valueOf(0L));
        elements.add(element);
        item.setElements(JSONObject.toJSONString(elements));
        item = cosInternalService.createOrderItem(item);
        if (null == item) {
            return new BocloudResult<>(false, "创建订单明细失败");
        }
        logger.info("loadBalancer{}分配创建的订单明细：{}", loadBalancer.getName(), JSONObject.toJSON(item));
        return new BocloudResult<>(true, item, "创建成功");
    }
}
