package com.bocloud.ims.service.resource.f5;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.f5.F5IRulesDriver;
import com.bocloud.cmp.model.f5.RuleModel;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.ims.entity.middleware.Kvs;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.f5.BiIRules;
import com.bocloud.ims.entity.resource.f5.BiPartition;
import com.bocloud.ims.interfaces.resource.f5.F5BiIRulesService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.f5.F5BiIRulesRepository;
import com.bocloud.ims.repository.resource.f5.F5BiPartitionRepository;
import com.bocloud.ims.service.utils.BigIpHelper;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
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.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service("f5BiIRulesService")
public class F5BiIRulesServiceImpl implements F5BiIRulesService {
	private static final Logger logger = LoggerFactory.getLogger(F5BiIRulesServiceImpl.class);
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private F5BiIRulesRepository f5BiIRulesRepository;
	@Autowired
	private F5IRulesDriver f5IRulesDriver;
	@Autowired
	private F5BiPartitionRepository f5BiPartitionRepository;

	@Override
	public BocloudResult<GridBean<BiIRules>> list(Pager pager) {
		GridBean gridBean = null;
		try {
			int page = pager.getPage();
			int rows = pager.getRows();
			List<Param> params = pager.getParams();
			Map<String, String> sorter = pager.getSorter();
			boolean simple = pager.getSimple();

			if (null == params) {
				params = Lists.newArrayList();
			}
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			for (Param param : params) {
				Map<String, Object> dataMap = param.getParam();
				if (dataMap.containsKey("partitionId")) {
					Long partitionId = Long.valueOf(dataMap.get("partitionId").toString());
					BiPartition partition = f5BiPartitionRepository.query(partitionId);
					if (0 == partitionId) {
						dataMap.remove("partitionId");
					} else if (!partition.getName().equals(BigIpHelper.EnumHelper.Common.name())) {
						BiPartition commonPartition = f5BiPartitionRepository
								.queryByName(BigIpHelper.EnumHelper.Common.name(), partition.getVendorId());
						dataMap.remove("partitionId");
						HashMap<String, Object> queryDataMap = Maps.newHashMap();
						queryDataMap.put("partitionId",
								new StringBuilder().append(partitionId).append(",").append(commonPartition.getId()));
						Param paramData = new Param();
						paramData.setParam(queryDataMap);
						paramData.setSign(Sign.IN);
						params.add(paramData);
					}
					break;
				}
			}
			int total = this.f5BiIRulesRepository.count(params);
			if (simple) {
				List<SimpleBean> beans = this.f5BiIRulesRepository.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				List<BiIRules> biNodes = this.f5BiIRulesRepository.list(page, rows, params, sorter);
				gridBean = GridHelper.getBean(page, rows, total, biNodes);
			}
			return new BocloudResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("Query BiIRules list fail:", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	@Override
	public BocloudResult create(BiIRules biIRules, Long userId) {
		String path = Kvs.class.getSimpleName() + "_" + biIRules.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			Long vendorId = biIRules.getVendorId();
			boolean isExists = f5BiIRulesRepository.existName(biIRules.getName(), vendorId, biIRules.getPartitionId());
			if (isExists) {
				return new BocloudResult(false, "添加失败：该名称已存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(vendorId);
			if (null == vendor) {
				logger.error("get cloudVendor failure!");
				return new BocloudResult(false, "云平台不存在!");
			}
			biIRules.setCreatorId(userId);
			biIRules.setMenderId(userId);
			biIRules.setGmtCreate(new Date());
			biIRules.setReserved(false);
			BiPartition partition = f5BiPartitionRepository.query(biIRules.getPartitionId());
			logger.info("create irule start...");
			// 数据转换
			BocloudResult<RuleModel> BocloudResult = convertData(biIRules, partition);
			if (BocloudResult.isFailed()) {
				logger.error(BocloudResult.getMessage());
				return new BocloudResult(false, null, BocloudResult.getMessage());
			}
			RuleModel ruleModel = BocloudResult.getData();
			BocloudResult bocloudResult = f5IRulesDriver.create(vendor.getUuid(), ruleModel);
			if (bocloudResult.isSuccess()) {
				try {
					JSONObject resultData = JSONObject.parseObject(String.valueOf(bocloudResult.getData()));
					if (null != resultData.getJSONObject("apiRawValues")) {
						JSONObject apiRawValues = resultData.getJSONObject("apiRawValues");
						String verificationStatus = apiRawValues.getString("verificationStatus");
						switch (verificationStatus) {
						case "signature-not-verified":
							biIRules.setVerificationStatus("Signature Not Verified");
							break;
						case "signature-verified":
							biIRules.setVerificationStatus("F5 Verified");
							break;
						default:
							break;
						}
					} else {
						biIRules.setVerificationStatus("None");
					}
					f5BiIRulesRepository.save(biIRules);
				} catch (Exception e) {
					logger.error(e.getMessage());
					return new BocloudResult(false, null, e.getMessage());
				}
				return new BocloudResult(true, "添加成功");
			} else {
				logger.error(bocloudResult.getMessage());
				return new BocloudResult(false, null, bocloudResult.getMessage());
			}
		} catch (Exception e) {
			logger.error("create IRules error", e);
			return new BocloudResult(false, e.getMessage());
		}
	}

	private BocloudResult<RuleModel> convertData(BiIRules biIRules, BiPartition partition) {
		RuleModel ruleModel = new RuleModel();
		ruleModel.setPartition(partition.getName());
		ruleModel.setName(biIRules.getName());
		ruleModel.setApiAnonymous(biIRules.getApiAnonymous());
		ruleModel.setIgnoreVerification(String.valueOf(biIRules.getIgnoreVerification()));
		return new BocloudResult<RuleModel>(true, ruleModel, "");
	}

	@Override
	public BocloudResult modify(BiIRules biIRules, Long userId) {
		String path = Kvs.class.getSimpleName() + "_" + biIRules.getId();
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			CloudVendor vendor = cloudVendorRepository.query(biIRules.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure");
				return new BocloudResult(false, "云平台不存在，修改失败");
			}
			BiIRules object = this.f5BiIRulesRepository.query(biIRules.getId());
			if (null == object) {
				logger.warn("data does not exist!");
				return new BocloudResult(false, "数据不存在");
			}
			biIRules.setMenderId(userId);
			biIRules.setGmtModify(new Date());
			BiPartition partition = f5BiPartitionRepository.query(biIRules.getPartitionId());
			logger.info("update IRules start...");
			// 数据转换
			BocloudResult<RuleModel> BocloudResult = convertData(biIRules, partition);
			if (BocloudResult.isFailed()) {
				logger.error(BocloudResult.getMessage());
				return new BocloudResult(false, null, "更新失败：" + BocloudResult.getMessage());
			}
			RuleModel ruleModel = BocloudResult.getData();
			BocloudResult bocloudResult = f5IRulesDriver.modify(vendor.getUuid(), ruleModel);
			if (bocloudResult.isSuccess()) {
				try {
					JSONObject resultData = JSONObject.parseObject(String.valueOf(bocloudResult.getData()));
					if (null != resultData.getJSONObject("apiRawValues")) {
						JSONObject apiRawValues = resultData.getJSONObject("apiRawValues");
						String verificationStatus = apiRawValues.getString("verificationStatus");
						switch (verificationStatus) {
						case "signature-not-verified":
							biIRules.setVerificationStatus("Signature Not Verified");
							break;
						case "signature-verified":
							biIRules.setVerificationStatus("F5 Verified");
							break;
						default:
							break;
						}
					} else {
						biIRules.setVerificationStatus("None");
					}
					f5BiIRulesRepository.update(biIRules);
				} catch (Exception e) {
					logger.error(e.getMessage());
					return new BocloudResult(false, null, e.getMessage());
				}
				return new BocloudResult(true, "更新成功");
			} else {
				logger.error(bocloudResult.getMessage());
				return new BocloudResult(false, null, bocloudResult.getMessage());
			}
		} catch (Exception e) {
			logger.error("Modify IRules fail:", e);
			return new BocloudResult(false, "修改失败");
		}
	}

	@Override
	public BocloudResult remove(Long id, Long userId) {
		String path = Kvs.class.getSimpleName() + "_" + id;
		try (BocloudACLock lock = lockFactory.getACLock(path)) {
			Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
			BiIRules biIRules = this.f5BiIRulesRepository.query(id);
			;
			if (null == biIRules) {
				return new BocloudResult(false, "请求内容不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(biIRules.getVendorId());
			if (null == vendor) {
				logger.error("get cloudVendor failure!");
				return new BocloudResult(false, "删除失败：云平台不存在!");
			}
			BiPartition partition = f5BiPartitionRepository.query(biIRules.getPartitionId());
			logger.info("remove IRules start...");
			BocloudResult result = f5IRulesDriver.remove(vendor.getUuid(),
					BigIpHelper.partitionCode(partition.getName(), biIRules.getName()));
			if (result.isSuccess()) {
				try {
					f5BiIRulesRepository.remove(id, userId);
				} catch (Exception e) {
					logger.error(e.getMessage());
					return new BocloudResult(false, null, e.getMessage());
				}
				return new BocloudResult(true, "删除成功");
			} else {
				logger.error(result.getMessage());
				return new BocloudResult(false, null, result.getMessage());
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			return new BocloudResult(false, "删除失败");
		}
	}

	@Override
	public BocloudResult<BiIRules> detail(Long id) {
		try {
			BiIRules biIRules = this.f5BiIRulesRepository.query(id);
			if (null == biIRules) {
				return new BocloudResult(false, "数据不存在");
			}
			return new BocloudResult(true, biIRules, "查询数据成功");
		} catch (Exception e) {
			logger.error("Get IRules error：", e);
			return new BocloudResult(false, "查询详情失败");
		}
	}

}
