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

import com.alibaba.fastjson.JSON;
import com.bocloud.cmp.driver.compute.HmcHostDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.model.HmcHostModel;
import com.bocloud.cmp.model.OsHosts;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.model.*;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.ims.entity.resource.powervc.PowervcHmc;
import com.bocloud.ims.entity.resource.powervc.PowervcHmcServer;
import com.bocloud.ims.interfaces.resource.powervc.PowervcHmcService;
import com.bocloud.ims.repository.powervc.PowervcHmcRepository;
import com.bocloud.ims.repository.powervc.PowervcHmcServerRepository;
import com.bocloud.ims.repository.resource.CloudServerRepository;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.ServerRepository;
import com.bocloud.ims.service.transportor.PowervcTransportor;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import org.apache.commons.lang3.StringUtils;
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 org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * powervc中hmc连接
 * @author luyanchao
 * @since 2019/1/23 10:48
 */
@Service
public class PowervcHmcServiceImpl implements PowervcHmcService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private PowervcHmcRepository hmcRepository;
    @Autowired
    private PowervcHmcServerRepository hmcServerRepository;
    @Autowired
    private CloudVendorRepository vendorRepository;
    @Autowired
    private ServerRepository serverRepository;
    @Autowired
    private CloudServerRepository cloudServerRepository;
    @Autowired
    private PowervcTransportor transportor;
    @Autowired
    private HmcHostDriver hmcHostDriver;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;

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

            int total = hmcRepository.count(params);
            List<PowervcHmc> list = hmcRepository.list(page, rows, params, sorter);
            GridBean gridBean = GridHelper.getBean(page, rows, total, list);
            return new BocloudResult(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败：", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<PowervcHmc> create(long vendorId, PowervcHmc hmc, RequestContext context, CountDownLatch countDownLatch) {
        try {
            CloudVendor vendor = vendorRepository.query(vendorId);
            if (vendor == null) {
                return new BocloudResult(false,"未找到平台");
            }
            if (StringUtils.isEmpty(hmc.getIp()) || StringUtils.isEmpty(hmc.getUsername()) ||
                    StringUtils.isEmpty(hmc.getPassword()) || StringUtils.isEmpty(hmc.getName())) {
                return new BocloudResult(false, "参数不完整");
            }
            hmc.setStatus(BocloudStatus.Server.BUILDING.name());
            hmc.setVendorId(vendorId);
            hmc.setCreatorId(context.getTarget());
            hmc.setMenderId(context.getTarget());
            hmcRepository.save(hmc);
            taskExecutor.submit(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.hmc.create", null, OperateResult.OperateCategory.ResourceEvent, context);
                try {
                    HmcHostModel model = new HmcHostModel();
                    model.setName(hmc.getName());
                    model.setIp(hmc.getIp());
                    model.setUsername(hmc.getUsername());
                    AESEncrptor aesEncrptor = new AESEncrptor();
                    try {
                        model.setPassword(aesEncrptor.decrypt(hmc.getPassword(), null));
                    } catch (Exception e) {
                        model.setPassword(hmc.getPassword());
                    }
                    model.setAddCert(true);
                    BocloudResult createResult = hmcHostDriver.create(vendor.getUuid(), model);
                    if (createResult.isFailed()) {
                        logger.error("创建HMC连接[" + hmc.getName() + "]失败：" + createResult.getMessage());
                        hmcRepository.remove(hmc.getId(), context.getTarget());
                        result.setSuccess(false);
                        result.setMessage("创建HMC连接[" + hmc.getName() + "]失败：" + createResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    String hmcUuid = JSON.parseObject(createResult.getData().toString()).
                            getJSONObject("hmc").getJSONObject("registration").getString("hmc_uuid");
                    hmc.setUuid(hmcUuid);
                    hmcRepository.update(hmc);
                    BocloudResult getResult = hmcHostDriver.get(vendor.getUuid(), hmcUuid);
                    if (getResult.isFailed()) {
                        logger.warn("创建HMC[UUID= " + hmcUuid + " ]连接成功，但重新获取该HMC信息失败：" + getResult.getMessage());
                        hmc.setStatus(BocloudStatus.Server.UNKNOWN.name());
                        hmcRepository.update(hmc);
                    } else {
                        model = (HmcHostModel) getResult.getData();
                        transportor.insertOrUpdate(vendor, model, context.getTarget());
                    }
                    result.setSuccess(true);
                    result.setMessage("创建HMC连接[" + hmc.getName() + "]成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("创建HMC连接[" + hmc.getName() + "]失败", e);
                    result.setSuccess(false);
                    result.setMessage("创建HMC连接[" + hmc.getName() + "]失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                } finally {
                    if (countDownLatch != null) {
                        countDownLatch.countDown();
                    }
                }
            });
            return new BocloudResult(true, hmc, "任务已经下发，正在执行...");
        } catch (Exception e) {
            if (countDownLatch != null) {
                countDownLatch.countDown();
            }
            logger.error("创建失败：", e);
            return new BocloudResult(false, "创建失败");
        }
    }

    @Override
    public BocloudResult<PowervcHmc> modify(long id, PowervcHmc hmc, RequestContext context, CountDownLatch countDownLatch) {
        try {
            PowervcHmc hmcOld = hmcRepository.get(id);
            if (hmcOld == null || hmcOld.getDeleted()) {
                return new BocloudResult(false, "未找到HMC连接");
            }
            CloudVendor vendor = vendorRepository.query(hmcOld.getVendorId());
            if (vendor == null || vendor.getDeleted()) {
                return new BocloudResult(false, "未找到平台");
            }
            hmcOld.setName(hmc.getName());
            hmcOld.setIp(hmc.getIp());
            hmcOld.setUsername(hmc.getUsername());
            hmcOld.setPassword(hmc.getPassword());
            taskExecutor.submit(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.hmc.modify", null, OperateResult.OperateCategory.ResourceEvent, context);
                try {
                    HmcHostModel model = new HmcHostModel();
                    model.setUuid(hmcOld.getUuid());
                    model.setName(hmc.getName());
                    model.setIp(hmc.getIp());
                    model.setUsername(hmc.getUsername());
                    AESEncrptor aesEncrptor = new AESEncrptor();
                    try {
                        model.setPassword(aesEncrptor.decrypt(hmc.getPassword(), null));
                    } catch (Exception e) {
                        model.setPassword(hmc.getPassword());
                    }
                    BocloudResult updateResult = hmcHostDriver.modify(vendor.getUuid(), model);
                    if (updateResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("修改HMC连接[" + hmc.getName() + "]失败：" + updateResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    String hmcUuid = JSON.parseObject(updateResult.getData().toString()).
                            getJSONObject("registration").getString("hmc_uuid");
                    BocloudResult getResult = hmcHostDriver.get(vendor.getUuid(), hmcUuid);
                    if (getResult.isFailed()) {
                        logger.warn("创建HMC[UUID= " + hmcUuid + " ]连接成功，但重新获取该HMC信息失败：" + getResult.getMessage());
                        hmc.setStatus(BocloudStatus.Server.UNKNOWN.name());
                        hmcRepository.update(hmc);
                    } else {
                        model = (HmcHostModel) getResult.getData();
                        transportor.insertOrUpdate(vendor, model, context.getTarget());
                    }
                    result.setSuccess(true);
                    result.setMessage("修改HMC连接[" + hmc.getName() + "]成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("修改HMC连接[" + hmc.getName() + "]失败", e);
                    result.setSuccess(false);
                    result.setMessage("修改HMC连接[" + hmc.getName() + "]失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                } finally {
                    if (countDownLatch != null) {
                        countDownLatch.countDown();
                    }
                }
            });
            return new BocloudResult(true, hmc, "任务已经下发，正在执行...");
        } catch (Exception e) {
            if (countDownLatch != null) {
                countDownLatch.countDown();
            }
            logger.error("修改失败：", e);
            return new BocloudResult(false, "修改失败");
        }
    }

    @Override
    public BocloudResult<PowervcHmc> remove(long id, RequestContext context, CountDownLatch countDownLatch) {
        try {
            PowervcHmc hmc = hmcRepository.get(id);
            if (hmc == null || hmc.getDeleted()) {
                return new BocloudResult(false, "未找到HMC连接");
            }
            CloudVendor vendor = vendorRepository.query(hmc.getVendorId());
            if (vendor == null || vendor.getDeleted()) {
                return new BocloudResult(false, "未找到平台");
            }
            taskExecutor.submit(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.hmc.remove", null, OperateResult.OperateCategory.ResourceEvent, context);
                try {
                    BocloudResult bocloudResult = hmcHostDriver.delete(vendor.getUuid(), hmc.getUuid());
                    if (bocloudResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("删除HMC连接[" + hmc.getName() + "]失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    clear(hmc.getId(), context);
                    result.setSuccess(true);
                    result.setMessage("删除HMC连接[" + hmc.getName() + "]成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("删除HMC连接[" + hmc.getName() + "]失败", e);
                    result.setSuccess(false);
                    result.setMessage("删除HMC连接[" + hmc.getName() + "]失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                } finally {
                    if (countDownLatch != null) {
                        countDownLatch.countDown();
                    }
                }
            });
            return new BocloudResult(true, hmc, "任务已经下发，正在执行...");
        } catch (Exception e) {
            if (countDownLatch != null) {
                countDownLatch.countDown();
            }
            logger.error("删除失败：", e);
            return new BocloudResult(false, "删除失败");
        }
    }

    @Override
    @Transactional
    public BocloudResult clear(long id, RequestContext context) {
        try {
            List<PowervcHmcServer> hmcServers = hmcServerRepository.listByHmcId(id);
            for (PowervcHmcServer hmcServer : hmcServers) {
                cloudServerRepository.removeByHost(hmcServer.getServerId(), context.getTarget());
                serverRepository.remove(hmcServer.getServerId(), context.getTarget());
                hmcServerRepository.delete(hmcServer);
            }
            hmcRepository.remove(id, context.getTarget());
            return new BocloudResult(true, "删除成功");
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            logger.error("删除失败：", e);
            return new BocloudResult(false, "删除失败");
        }
    }

    @Override
    public BocloudResult<PowervcHmc> detail(long id, RequestContext context) {
        try {
            PowervcHmc hmc = hmcRepository.get(id);
            return new BocloudResult(true, hmc, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败：", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    @Override
    public BocloudResult listByVendor(long vendorId) {
        try {
            List<PowervcHmc> hmcs = hmcRepository.listByVendor(vendorId);
            return new BocloudResult(true, hmcs, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败：", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<List<PowervcHmc>> listByHost(long hostId) {
        try {
            List<PowervcHmc> hmcs = hmcServerRepository.listHmcByServer(hostId);
            return new BocloudResult(true, hmcs, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败：", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    @Override
    public BocloudResult<OsHosts> listHost(long id) {
        try {
            PowervcHmc hmc = hmcRepository.get(id);
            if (hmc == null) {
                return new BocloudResult(false, "未找到HMC连接");
            }
            CloudVendor cloudVendor = vendorRepository.query(hmc.getVendorId());
            if (cloudVendor == null) {
                return new BocloudResult(false, "未找到平台");
            }
            BocloudResult bocloudResult = hmcHostDriver.getHosts(cloudVendor.getUuid(), hmc.getUuid());
            if (bocloudResult.isFailed()) {
                return bocloudResult;
            }
            OsHosts osHosts = (OsHosts) bocloudResult.getData();
            List<Server> servers = hmcServerRepository.listServerByHmc(id);
            osHosts.getHosts().removeIf(osHost -> {
                for (Server server : servers) {
                    if (osHost.getName().equals(server.getHostname())) {
                        return true;
                    }
                }
                return false;
            });

            return new BocloudResult(true, osHosts, "查询成功");
        } catch (Exception e) {
            logger.error("查询失败：", e);
            return new BocloudResult(false, "查询失败");
        }
    }
}
