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

import com.bocloud.cmp.driver.storage.FabricDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.model.SanFabricModel;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.OperateResult;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.RequestContext;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.SanFabric;
import com.bocloud.ims.interfaces.resource.powervc.SanFabricService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.SanFabricRepository;
import com.bocloud.ims.service.transportor.PowervcTransportor;
import com.bocloud.ims.service.utils.ResourceEventPublisher;
import org.apache.commons.lang3.StringEscapeUtils;
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.List;
import java.util.Map;

/**
 * @author luyanchao
 * @since 2019/2/22 15:34
 */
@Service("powervcSanFabricService")
public class PowervcSanFabricServiceImpl implements SanFabricService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ResourceEventPublisher resourceEventPublisher;
    @Autowired
    private CloudVendorRepository cloudVendorRepository;
    @Autowired
    private SanFabricRepository sanFabricRepository;
    @Autowired
    private PowervcTransportor powervcTransportor;
    @Autowired
    private FabricDriver fabricDriver;

    @Override
    public BocloudResult list(int page, int rows, List<Param> params, Map<String, String> sorter, RequestContext context) {
        try {
            List<SanFabric> list = sanFabricRepository.list(page, rows, params, sorter);
            int total = sanFabricRepository.count(params);
            GridBean gridBean = new GridBean(page, rows, total, list);
            return new BocloudResult(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    @Override
    public BocloudResult detail(long id) {
        try {
            SanFabric sanFabric = sanFabricRepository.get(id);
            return new BocloudResult(true, sanFabric, "查询成功");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult(false, "查询失败");
        }
    }

    @Override
    public BocloudResult create(SanFabric sanFabric, RequestContext context) {
        try {
            CloudVendor cloudVendor = cloudVendorRepository.query(sanFabric.getVendorId());
            if (cloudVendor == null) {
                return new BocloudResult(false, "未找到平台");
            }
            sanFabric.setCreatorId(context.getTarget());
            sanFabric.setMenderId(context.getTarget());
            sanFabric.setStatus(BocloudStatus.Server.BUILDING.name());
            sanFabricRepository.save(sanFabric);
            taskExecutor.submit(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.createSanFabrics", null, OperateResult.OperateCategory.ResourceEvent, context);
                try {
                    SanFabricModel sanFabricModel = new SanFabricModel();
                    sanFabricModel.setNickName(sanFabric.getName());
                    sanFabricModel.setIp(sanFabric.getIp());
                    sanFabricModel.setUsername(sanFabric.getUsername());
                    AESEncrptor aesEncrptor = new AESEncrptor();
                    try {
                        sanFabricModel.setPassword(aesEncrptor.decrypt(sanFabric.getPassword(), null));
                    } catch (Exception e) {
                        sanFabricModel.setPassword(sanFabric.getPassword());
                    }
                    sanFabricModel.setType(sanFabric.getType());
                    sanFabricModel.setPolicy(sanFabric.getPolicy());
                    sanFabricModel.setAddKey(true);
                    BocloudResult bocloudResult = fabricDriver.create(cloudVendor.getUuid(), sanFabricModel);
                    if (bocloudResult.isFailed()) {
                        sanFabricRepository.remove(sanFabric.getId());

                        result.setSuccess(false);
                        result.setMessage("光纤网[" + sanFabric.getName() + "]创建失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    sanFabricModel = (SanFabricModel) bocloudResult.getData();
                    sanFabric.setStatus(BocloudStatus.Server.RUNNING.name());
                    sanFabric.setUuid(sanFabricModel.getName());
                    sanFabricRepository.update(sanFabric);
                    powervcTransportor.insertOrUpdate(cloudVendor, sanFabricModel, context.getTarget());

                    result.setSuccess(true);
                    result.setMessage("光纤网[" + sanFabric.getName() + "]创建成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("光纤网[" + sanFabric.getName() + "]创建失败", e);
                    result.setSuccess(false);
                    result.setMessage("光纤网[" + sanFabric.getName() + "]创建失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                }
            });
            return new BocloudResult(true, sanFabric, "任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult(false, "创建失败");
        }
    }

    @Override
    public BocloudResult modify(SanFabric sanFabric, RequestContext context) {
        try {
            SanFabric sanFabricOld = sanFabricRepository.get(sanFabric.getId());
            if (sanFabricOld == null || sanFabricOld.getDeleted()) {
                return new BocloudResult(false, "未找到数据");
            }
            CloudVendor cloudVendor = cloudVendorRepository.query(sanFabricOld.getVendorId());
            if (cloudVendor == null) {
                return new BocloudResult(false, "未找到平台");
            }
            sanFabric.setId(sanFabricOld.getId());
            sanFabric.setUuid(sanFabricOld.getUuid());
            sanFabric.setType(sanFabricOld.getType());  // 光纤网的类型不允许修改
            sanFabric.setPolicy(sanFabricOld.getPolicy()); // 光纤网的分区策略不允许修改
            taskExecutor.submit(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.modifySanFabrics", null, OperateResult.OperateCategory.ResourceEvent, context);
                try {
                    SanFabricModel sanFabricModel = new SanFabricModel();
                    sanFabricModel.setName(sanFabric.getUuid());
                    sanFabricModel.setNickName(sanFabric.getName());
                    sanFabricModel.setIp(sanFabric.getIp());
                    sanFabricModel.setUsername(sanFabric.getUsername());
                    AESEncrptor aesEncrptor = new AESEncrptor();
                    try {
                        sanFabricModel.setPassword(aesEncrptor.decrypt(sanFabric.getPassword(), null));
                    } catch (Exception e) {
                        sanFabricModel.setPassword(sanFabric.getPassword());
                    }
                    sanFabricModel.setAddKey(false);
                    BocloudResult modifyResult = fabricDriver.modify(cloudVendor.getUuid(), sanFabricModel);
                    if (modifyResult.isFailed()) {
                        logger.error("光纤网[" + sanFabric.getName() + "]修改失败：" + StringEscapeUtils.unescapeJava(modifyResult.getMessage()));
                        result.setSuccess(false);
                        result.setMessage("光纤网[" + sanFabric.getName() + "]修改失败：" + StringEscapeUtils.unescapeJava(modifyResult.getMessage()));
                        resourceEventPublisher.send(result);
                        return;
                    }
                    sanFabricModel = (SanFabricModel) modifyResult.getData();
                    // 执行完修改后返回的光纤网详情信息不全，所以需要重新调用下detail接口进行更新
                    BocloudResult detailResult = fabricDriver.detail(cloudVendor.getUuid(), sanFabricModel.getName());
                    if (detailResult.isFailed()) {
                        logger.error("光纤网[" + sanFabric.getName() + "]修改成功但重新获取详情失败：" + StringEscapeUtils.unescapeJava(detailResult.getMessage()));
                        result.setSuccess(false);
                        result.setMessage("光纤网[" + sanFabric.getName() + "]修改成功但重新获取详情失败：" + StringEscapeUtils.unescapeJava(detailResult.getMessage()));
                        resourceEventPublisher.send(result);
                        return;
                    }
                    sanFabricModel = (SanFabricModel) detailResult.getData();
                    powervcTransportor.insertOrUpdate(cloudVendor, sanFabricModel, context.getTarget());

                    result.setSuccess(true);
                    result.setMessage("光纤网[" + sanFabric.getName() + "]修改成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("光纤网[" + sanFabric.getName() + "]修改失败", e);
                    result.setSuccess(false);
                    result.setMessage("光纤网[" + sanFabric.getName() + "]修改失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                }
            });
            return new BocloudResult(true, sanFabric, "任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult(false, "修改失败");
        }
    }

    @Override
    public BocloudResult remove(long id, RequestContext context) {
        try {
            SanFabric sanFabric = sanFabricRepository.get(id);
            if (sanFabric == null || sanFabric.getDeleted()) {
                return new BocloudResult(false, "未找到数据");
            }
            CloudVendor cloudVendor = cloudVendorRepository.query(sanFabric.getVendorId());
            if (cloudVendor == null) {
                return new BocloudResult(false, "未找到平台");
            }
            taskExecutor.submit(() -> {
                OperateResult result = new OperateResult(true, "", "powervc.removeSanFabrics", null, OperateResult.OperateCategory.ResourceEvent, context);
                try {
                    BocloudResult bocloudResult = fabricDriver.remove(cloudVendor.getUuid(), sanFabric.getUuid());
                    if (bocloudResult.isFailed()) {
                        result.setSuccess(false);
                        result.setMessage("光纤网[" + sanFabric.getName() + "]删除失败：" + bocloudResult.getMessage());
                        resourceEventPublisher.send(result);
                        return;
                    }
                    sanFabricRepository.remove(sanFabric.getId());

                    result.setSuccess(true);
                    result.setMessage("光纤网[" + sanFabric.getName() + "]删除成功");
                    resourceEventPublisher.send(result);
                } catch (Exception e) {
                    logger.error("光纤网[" + sanFabric.getName() + "]删除失败", e);
                    result.setSuccess(false);
                    result.setMessage("光纤网[" + sanFabric.getName() + "]删除失败：" + e.getMessage());
                    resourceEventPublisher.send(result);
                }
            });
            return new BocloudResult(true, sanFabric, "任务已经下发，正在执行……");
        } catch (Exception e) {
            logger.error("Get error message：", e);
            return new BocloudResult(false, "删除失败");
        }
    }
}
