package com.bocloud.ims.service.internal;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.model.common.ElementModel;
import com.bocloud.cmp.model.common.OrderItem;
import com.bocloud.cmp.model.common.ServiceOrder;
import com.bocloud.common.enums.BoCloudMethod;
import com.bocloud.common.enums.BoCloudService;
import com.bocloud.common.enums.PostDataFormat;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.BocloudToken;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.Sign;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.entity.common.CloudService;
import com.bocloud.ims.entity.common.Recycled;
import com.bocloud.ims.entity.common.ServiceCatalog;
import com.bocloud.ims.entity.common.ServiceCategory;
import com.bocloud.ims.entity.common.ServiceSku;
import com.bocloud.ims.entity.common.ServiceTenant;
import com.bocloud.ims.entity.common.SkuPrice;
import com.bocloud.ims.entity.dto.ServiceOrderQueryDTO;
import com.bocloud.ims.entity.params.SkuParams;
import com.bocloud.ims.entity.resource.ResourceQuota;
import com.bocloud.service.core.CurrentService;
import com.bocloud.service.core.Service;
import com.bocloud.service.http.core.ServiceFactory;
import com.bocloud.service.http.model.RemoteService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * cos服务内部访问
 *
 * @author wangyu
 * @version 1.0
 * @since 2018年1月11日
 */
@Component
public class CosInternalService implements InitializingBean {

	@Autowired
	private ServiceFactory serviceFactory;
	@Autowired
	private CurrentService currentService;
	private static Service service = Service.create(BoCloudService.COS);
	private Map<String, Object> headers = new HashMap<>(4);

	public Integer list(Long userId, String apiKey) {
		List<Param> params = Lists.newArrayList();
		params.add(new Param(MapTools.simpleMap("status", "UNREAD"), Sign.EQ));
		params.add(new Param(MapTools.simpleMap("ownerId", userId), Sign.EQ));
		Map<String, Object> paramMap = MapTools.simpleMap("simple", true);
		paramMap.put("page", 1);
		paramMap.put("rows", Integer.MAX_VALUE);
		paramMap.put(Common.PARAMS, JSONArray.toJSONString(params));
		this.headers.put(Common.API_KEY, apiKey);
		RemoteService remote = serviceFactory.build(service, "/v1/messages", BoCloudMethod.GET, headers, paramMap);
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return 0;
		}
		JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), JSONObject.class);
		return jsonObject.getInteger("total");
	}

	public BocloudResult updateQuotas(List<ResourceQuota> quotas, ResourceQuota.Action action, Long tenantId) {
		if(null == tenantId || 0 == tenantId) {
			return new BocloudResult<>(true, "租户为空，不调用配额接口");
		}
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("quotas", quotas);
		paramMap.put(Common.ACTION, action.name());
		paramMap.put("tenantId", tenantId);
		RemoteService remote = serviceFactory.build(service, "/v1/quotas", BoCloudMethod.PATCH, headers, paramMap);
		remote.setDataFormat(PostDataFormat.RAW);
		return remote.invoke();
	}

	public List<ServiceTenant> listTenantServices(Long tenantId) {
		RemoteService remote = serviceFactory.build(service, "/v1/services/tenants/" + tenantId + "/services/items",
				BoCloudMethod.GET, headers, null);
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		String content = JSONObject.toJSONString(result.getData());
		if (StringUtils.isEmpty(content)) {
			return null;
		}
		return JSONArray.parseArray(content, ServiceTenant.class);
	}

	public SkuPrice queryPrice(Long skuId) {
		List<Param> params = Lists.newArrayList();
		Map<String, Object> simpleMap = MapTools.simpleMap("skuId", skuId);
		simpleMap.put("period", "Hour");
		params.add(new Param(simpleMap, Sign.EQ));
		Map<String, Object> paramMap = MapTools.simpleMap("simple", false);
		paramMap.put("page", 1);
		paramMap.put("rows", 1000);
		paramMap.put(Common.PARAMS, JSONArray.toJSONString(params));
		RemoteService remote = serviceFactory.build(service, "/v1/skus/prices", BoCloudMethod.GET, headers, paramMap);
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), JSONObject.class);
		List<SkuPrice> prices = JSONArray.parseArray(jsonObject.getString("rows"), SkuPrice.class);
		return prices.get(0);
	}

	public ServiceCatalog getServiceCatalog(Long catalogId) {
		RemoteService remote = serviceFactory.build(service, "/v1/services/catalogs/" + catalogId, BoCloudMethod.GET,
				headers, null);
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		return JSONObject.parseObject(JSONObject.toJSONString(result.getData()), ServiceCatalog.class);
	}

	public ServiceSku detailSku(Long skuId) {
		RemoteService remote = serviceFactory.build(service, "/v1/services/skus/" + skuId, BoCloudMethod.GET, headers,
				null);
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		return JSONObject.parseObject(JSONObject.toJSONString(result.getData()), ServiceSku.class);
	}

	public BocloudResult<ServiceSku> querySku(String serviceCode, Integer cpu, Integer memory, Integer disk) {
		JSONObject object = new JSONObject();
		object.put(Common.CONDITION, "getByCondition");
		object.put("cpu", cpu);
		object.put("memory", memory);
		object.put("disk", disk);
		object.put("serviceCode", serviceCode);
		RemoteService remote = serviceFactory.build(service, "/v1/services/skus", BoCloudMethod.GET, headers,
				MapTools.simpleMap(Common.CONDITION, object.toJSONString()));
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return new BocloudResult<>(false, result.getMessage());
		}
		String jsonString = JSONObject.toJSONString(result.getData());
		System.out.println(jsonString);
		JSONObject parseObject = JSONObject.parseObject(JSONObject.toJSONString(result.getData()));
		if (null != parseObject) {
			List<ServiceSku> parseArray = JSONObject.parseArray(parseObject.getString("rows"), ServiceSku.class);
			if (!ListTool.isEmpty(parseArray)) {
				return new BocloudResult<>(true, parseArray.get(0), "查询成功");
			}
		}
		return new BocloudResult<>(false, "找不到合适的云主机产品规格");
	}

	public BocloudResult<ServiceCategory> getCategory(Long categoryId) {
		RemoteService remote = serviceFactory.build(service, "/v1/services/categories/" + categoryId, BoCloudMethod.GET,
				headers, null);
		BocloudResult result = remote.invoke();
		if (result.isFailed() || null == result.getData()) {
			return new BocloudResult<>(false, "服务类型查询失败");
		}
		return new BocloudResult<>(true,
				JSONObject.parseObject(JSONObject.toJSONString(result.getData()), ServiceCategory.class), "查询成功");
	}

	public BocloudResult recycle(String sn) {
		JSONObject object = new JSONObject();
		object.put("sn", sn);
		RemoteService remote = serviceFactory.build(service, "/v1/recycles/sn", BoCloudMethod.DELETE, headers, object);
		remote.setDataFormat(PostDataFormat.RAW);
		BocloudResult<?> invoke = remote.invoke();
		return invoke;
	}

	public CloudService detailService(String serviceCode) {
		JSONObject object = new JSONObject();
		object.put(Common.CONDITION, "queryByCode");
		object.put("code", serviceCode);
		RemoteService remote = serviceFactory.build(service, "/v1/cloud/services/condition", BoCloudMethod.GET, headers,
				MapTools.simpleMap(Common.CONDITION, object.toJSONString()));
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		return JSONObject.parseObject(JSONObject.toJSONString(result.getData()), CloudService.class);
	}

	public BocloudResult removeByVendorId(Long vendorId) {
		Map<String, Object> params = Maps.newHashMap();
		JSONObject object = new JSONObject();
		object.put("vendorId", vendorId);
		params.put(Common.PARAMS, object.toJSONString());
		RemoteService remote = serviceFactory.build(service, "/price/removebyvendorid", BoCloudMethod.POST, headers,
				params);
		return remote.invoke();
	}

	public BocloudResult deleteByVendor(Long vendorId) {
		RemoteService remote = serviceFactory.build(service, "/v1/vendors/records/vendors/" + vendorId,
				BoCloudMethod.DELETE, headers, null);
		BocloudResult result = remote.invoke();
		return result;
	}

	public BocloudResult joinRecycle(Recycled recycled) {
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put(Common.PARAMS, JSONObject.toJSONString(recycled));
		RemoteService remote = serviceFactory.build(service, "/v1/recycles", BoCloudMethod.POST, headers, paramMap);
		return remote.invoke();
	}

	public BocloudResult createOrder(ServiceOrder order) {
		RemoteService remote = serviceFactory.build(service, "/v1/orders", BoCloudMethod.POST, headers, order);
		remote.setDataFormat(PostDataFormat.RAW);
		return remote.invoke();
//		if (result.isFailed()) {
//			return result;
//		}
//		return JSONObject.parseObject(JSONObject.toJSONString(result.getData()), ServiceOrder.class);
	}

	public OrderItem createOrderItem(OrderItem item) {
		RemoteService remote = serviceFactory.build(service, "/v1/orders/items", BoCloudMethod.POST, headers, item);
		remote.setDataFormat(PostDataFormat.RAW);
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		return JSONObject.parseObject(JSONObject.toJSONString(result.getData()), OrderItem.class);
	}

	public BocloudResult updateStatus(Long id, String status) {
		JSONObject object = new JSONObject();
		object.put("resourceStatus", status);
		/*RemoteService remote = serviceFactory.build(service, "/v1/orders/" + id, BoCloudMethod.PATCH, headers,
				MapTools.simpleMap(Common.PARAMS, object.toJSONString()))*/;
		RemoteService remote = serviceFactory.build(service, "/v1/orders/" + id, BoCloudMethod.PATCH, headers,
				object);
		remote.setDataFormat(PostDataFormat.RAW);
		return remote.invoke();
	}

	public BocloudResult updateStatus(Long id, String status, Long tenantId, Long projectId) {
		JSONObject object = new JSONObject();
		object.put("resourceStatus", status);
		if (null != tenantId && 0 != tenantId) {
			object.put("tenantId", tenantId);
		}
		if (null != projectId && 0 != projectId) {
			object.put("projectId", projectId);
		}
		/*RemoteService remote = serviceFactory.build(service, "/v1/orders/" + id, BoCloudMethod.PATCH, headers,
				MapTools.simpleMap(Common.PARAMS, object.toJSONString()));*/
		RemoteService remote = serviceFactory.build(service, "/v1/orders/" + id, BoCloudMethod.PATCH, headers,
				object);
		remote.setDataFormat(PostDataFormat.RAW);
		return remote.invoke();
	}

	public BocloudResult updateElements(String sn, List<ElementModel> elements) {
		JSONObject object = new JSONObject();
		object.put("sn", sn);
		object.put("elements", JSONObject.toJSONString(elements));
		RemoteService remote = serviceFactory.build(service, "/v1/orders/items/elements", BoCloudMethod.PATCH, headers,
				MapTools.simpleMap(Common.PARAMS, object.toJSONString()));
		return remote.invoke();
	}

	public BocloudResult recycleBill(String orderItemSn) {
		RemoteService remote = serviceFactory.build(service, "/v1/bills", BoCloudMethod.PUT, headers,
				MapTools.simpleMap("sn", orderItemSn));
		remote.setDataFormat(PostDataFormat.RAW);
		return remote.invoke();
	}

	public BocloudResult updateItemStatus(String sn, String status) {
		JSONObject object = new JSONObject();
		object.put("sn", sn);
		object.put("status", status);
		RemoteService remote = serviceFactory.build(service, "/v1/orders/items", BoCloudMethod.PATCH, headers, object);
		remote.setDataFormat(PostDataFormat.RAW);
		return remote.invoke();
	}

	public BocloudResult queryByResourceUuid(String resourceUuid, String resourceCategory) {
		JSONObject object = new JSONObject();
		object.put(Common.CONDITION, "queryByResourceUuid");
		object.put("resourceUuid", resourceUuid);
		object.put("resourceCategory", resourceCategory);
		RemoteService remote = serviceFactory.build(service, "/v1/orders", BoCloudMethod.GET, headers,
				MapTools.simpleMap(Common.CONDITION, object.toJSONString()));
		return remote.invoke();
	}

	public BocloudResult detail(Long id) {
		RemoteService remote = serviceFactory.build(service, "/v1/orders/" + id, BoCloudMethod.GET, headers, null);
		return remote.invoke();
	}

	public BocloudResult getByOrderSn(String orderSn) {
		JSONObject object = new JSONObject();
		object.put(Common.CONDITION, "getByOrderSn");
		object.put("orderSn", orderSn);
		RemoteService remote = serviceFactory.build(service, "/v1/orders", BoCloudMethod.GET, headers,
				MapTools.simpleMap(Common.CONDITION, object.toJSONString()));
		return remote.invoke();
	}

	public ServiceOrder getServiceOrder(String itemSn) {
		JSONObject object = new JSONObject();
		object.put(Common.CONDITION, "getServiceOrder");
		object.put("itemSn", itemSn);
		RemoteService remote = serviceFactory.build(service, "/v1/orders", BoCloudMethod.GET, headers,
				MapTools.simpleMap(Common.CONDITION, object.toJSONString()));
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		String content = JSONObject.toJSONString(result.getData());
		if (org.apache.commons.lang3.StringUtils.isEmpty(content)) {
			return null;
		}
		return JSONObject.parseObject(content, ServiceOrder.class);
	}

	public OrderItem queryByItemSn(String itemSn) {
		JSONObject object = new JSONObject();
		object.put(Common.CONDITION, "queryByItemSn");
		object.put("sn", itemSn);
		RemoteService remote = serviceFactory.build(service, "/v1/orders", BoCloudMethod.GET, headers,
				MapTools.simpleMap(Common.CONDITION, object.toJSONString()));
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		String content = JSONObject.toJSONString(result.getData());
		if (org.apache.commons.lang3.StringUtils.isEmpty(content)) {
			return null;
		}
		return JSONObject.parseObject(content, OrderItem.class);
	}

	public List<ServiceCategory> listServiceCategories(String serviceCode) {
		RemoteService remote = serviceFactory.build(service, "/v1/cloud/services/"+ serviceCode +"/categories", BoCloudMethod.GET, headers, null);
		BocloudResult result = remote.invoke();
		if (result.isFailed()) {
			return null;
		}
		String content = JSONObject.toJSONString(result.getData());
		if (org.apache.commons.lang3.StringUtils.isEmpty(content)) {
			return null;
		}
		return JSONObject.parseArray(content, ServiceCategory.class);
	}

	public ServiceSku createServiceSku(SkuParams skuParams) {
		RemoteService remote = serviceFactory.build(service, "/v1/services/skus", BoCloudMethod.POST, headers, skuParams);
		remote.setDataFormat(PostDataFormat.RAW);
		BocloudResult result = remote.invoke();
		if (result.isFailed() && null == result.getData()) {
			return null;
		}
		String content = JSONObject.toJSONString(result.getData());
		if (org.apache.commons.lang3.StringUtils.isEmpty(content)) {
			return null;
		}
		return JSONObject.parseObject(content, ServiceSku.class);
	}

	/**
	 * 查询订单相关信息
	 *
	 * @author sxp
	 * @since 2023/7/24
	 */
	public BocloudResult queryServiceOrderInfo(ServiceOrderQueryDTO dto) {
		Map<String, Object> params = JSON.parseObject(JSON.toJSONString(dto));
		RemoteService remote = serviceFactory.build(service, "/v1/orders/query", BoCloudMethod.GET, headers, params);
		BocloudResult result = remote.invoke();
		return result;
	}



	@Override
	public void afterPropertiesSet() throws Exception {
		this.headers.put(BocloudToken.INTERNAL_TOKEN, currentService.getToken());
		this.headers.put("source", currentService.getService().getName());
	}

}
