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

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.hmc.HmcHEADriver;
import com.bocloud.cmp.model.hmc.HmcHostEthernetAdapterModel;
import com.bocloud.cmp.model.hmc.sdk.module.HostEthernetAdapterEntry;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.OperateResult.OperateCategory;
import com.bocloud.common.model.RequestContext;
import com.bocloud.common.utils.MapTools;
import com.bocloud.ims.common.enums.ServerAction;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.ResourceEvent;
import com.bocloud.ims.entity.resource.hmc.HmcHeaLogicalPort;
import com.bocloud.ims.entity.resource.hmc.HmcHeaPhysicalPort;
import com.bocloud.ims.entity.resource.hmc.HmcHostEthernetAdapter;
import com.bocloud.ims.entity.resource.hmc.HmcServer;
import com.bocloud.ims.entity.resource.hmc.params.ServerIdParams;
import com.bocloud.ims.interfaces.resource.hmc.HmcHEAService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ResourceEventRepository;
import com.bocloud.ims.repository.resource.hmc.HmcHeaLogicalPortRepository;
import com.bocloud.ims.repository.resource.hmc.HmcHeaPhysicalPortRepository;
import com.bocloud.ims.repository.resource.hmc.HmcHostEthernetAdapterRepository;
import com.bocloud.ims.repository.resource.hmc.HmcServerRepository;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import com.bocloud.service.lock.LockFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service("hmcHEAService")
public class HmcHEAServiceImpl implements HmcHEAService {
	private static final Logger logger = LoggerFactory.getLogger(HmcHEAServiceImpl.class);
	private static OperateCategory operateCategory = OperateCategory.ResourceEvent;

	@Autowired
	private HmcHEADriver hmcHEADriver;
	@Autowired
	private HmcHostEthernetAdapterRepository hmcHostEthernetAdapterRepository;
	@Autowired
	private HmcHeaPhysicalPortRepository hmcHeaPhysicalPortRepository;
	@Autowired
	private HmcHeaLogicalPortRepository hmcHeaLogicalPortRepository;
	@Autowired
	private HmcServerRepository hmcServerRepository;
	@Autowired
	private CloudVendorRepository cloudVendorRepository;
	@Autowired
	private ResourceEventRepository resourceEventRepository;
	@Autowired
	private ResourceEventPublisher resourceEventPublisher;
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private HmcDatabaseHelper hmcDatabaseHelper;
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;

	@Override
	public BocloudResult<List<HmcHostEthernetAdapter>> listPhysicalPorts(Long serverId) {
		if (null == serverId) {
			return new BocloudResult(false, "缺少服务Id");
		}
		try {
			HmcServer server = hmcServerRepository.getServerById(serverId);
			if (null == server) {
				logger.error("get hmc server failure!");
				return new BocloudResult(false, "服务器不存在!");
			}

			List<HmcHostEthernetAdapter> heas = hmcHostEthernetAdapterRepository.listByServerId(serverId);
			if (null != heas && !heas.isEmpty()) {
				for (HmcHostEthernetAdapter hea : heas) {
					List<HmcHeaPhysicalPort> physicalPorts = hmcHeaPhysicalPortRepository.queryByHeaId(hea.getId());
					hea.setHmcHeaPhysicalPorts(physicalPorts);
					List<HmcHeaLogicalPort> logicalPorts = hmcHeaLogicalPortRepository.queryByHeaId(hea.getId());
					hea.setHmcHeaLogicalPorts(logicalPorts);
				}
			}
			return new BocloudResult(true, heas, "查询成功");
		} catch (Exception e) {
			logger.error("Query partition list fail:", e);
			return new BocloudResult(false, "查询失败");
		}
	}

	@Override
	public BocloudResult modify(HmcHostEthernetAdapter hmcHostEthernetAdapter, RequestContext context) {
		Long heaId = hmcHostEthernetAdapter.getId();
		try {
			if (null == hmcHostEthernetAdapter.getHmcHeaPhysicalPorts()
					|| hmcHostEthernetAdapter.getHmcHeaPhysicalPorts().isEmpty()) {
				logger.warn("Requirement is incorrectly for update HEA");
				return new BocloudResult(false, "HEA更新，请求参数格式不正确");
			}

			String portLocation = null;
			// 给物理主机以太网端口加锁
			List<HmcHeaPhysicalPort> physicalPorts = hmcHeaPhysicalPortRepository.queryByHeaId(heaId);
			for (HmcHeaPhysicalPort physicalPort : physicalPorts) {
				if (physicalPort.getPortId().equals(hmcHostEthernetAdapter.getHmcHeaPhysicalPorts().get(0).getPortId())) {
					portLocation = physicalPort.getPortLocation();
				}
			}

			HmcHostEthernetAdapter oldHmcHea = hmcHostEthernetAdapterRepository.getById(heaId);
			if (null == oldHmcHea) {
				logger.error("hmc HEA {} does not exist!", heaId);
				return new BocloudResult(false, "ID为[" + heaId + "]的HMC HEA不存在");
			}
			HmcServer server = hmcServerRepository.getServerById(oldHmcHea.getServerId());
			if (null == server) {
				logger.error("hmc server {} does not exist!", oldHmcHea.getServerId());
				return new BocloudResult(false, "ID为[" + oldHmcHea.getServerId() + "]的HMC服务器不存在");
			}
			CloudVendor vendor = cloudVendorRepository.query(server.getVendorId());
			if (null == vendor) {
				logger.error("vendor {} does not exist!", server.getVendorId());
				return new BocloudResult(false, "ID为[" + server.getVendorId() + "]的云平台不存在");
			}

			// 启动一个线程从MQ上获取数据
			final String finalPortLocation = portLocation;
			taskExecutor.submit(() -> {
				String operate = vendor.getType().toLowerCase() + ".hea";
				String content = "主机以太网[" + oldHmcHea.getName() + "-" + finalPortLocation + "]修改失败";
				try {
					ResourceEvent event = null;
					BocloudResult result = hmcHEADriver.updatePhysicalPorts(vendor.getUuid(),
							JSONObject.parseObject(JSONObject.toJSONString(hmcHostEthernetAdapter),
									HmcHostEthernetAdapterModel.class),
							server.getUuid(), oldHmcHea.getUuid());
					if (result.isSuccess()) {
						HostEthernetAdapterEntry entry = (HostEthernetAdapterEntry) result.getData();
						hmcDatabaseHelper.updateHostEthernetAdapter(server.getId(),
								entry.getContent().getHostEthernetAdapter(), entry.getId());
						event = new ResourceEvent(heaId, ServerAction.UPDATE.name(), "成功", context.getTarget(),
								new Date(), "HMC", vendor.getId(), context.getCatalog());
						content = "HMC HEA[" + oldHmcHea.getName() + "-" + finalPortLocation + "]编辑成功";
					} else {
						event = new ResourceEvent(heaId, ServerAction.UPDATE.name(), "失败", context.getTarget(),
								new Date(), "HMC", vendor.getId(), context.getCatalog());
						content = "HMC HEA[" + oldHmcHea.getName() + "-" + finalPortLocation + "]编辑失败,原因:["
								+ result.getMessage() + "]";
					}
					resourceEventRepository.save(event);
					resourceEventPublisher.send(new OperateResult(result.isSuccess(), content, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				} catch (Exception e) {
					logger.error("修改主机以太网失败", e);
					resourceEventPublisher.send(new OperateResult(false, content, operate,
							MapTools.simpleMap("vendorId", vendor.getId()), operateCategory, context));
				}
			});
			return new BocloudResult(true, "修改任务已下发，正在执行...");
		} catch (Exception e) {
			logger.error("modify hmc partition profile failure:", e);
			return new BocloudResult(false, "修改主机以太网失败");
		}
	}
}
