package com.bocloud.ims.service.resource;

import com.bocloud.common.model.*;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.ListTool;
import com.bocloud.ims.entity.resource.CloudVendor;
import com.bocloud.ims.entity.resource.Environment;
import com.bocloud.ims.interfaces.resource.EnvironmentService;
import com.bocloud.ims.repository.resource.CloudVendorRepository;
import com.bocloud.ims.repository.resource.EnvironmentRepository;
import com.bocloud.service.lock.BocloudACLock;
import com.bocloud.service.lock.LockFactory;
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.*;
import java.util.concurrent.TimeUnit;

@Service("environmentService")
public class EnvironmentServiceImpl implements EnvironmentService {

    private static final Logger logger = LoggerFactory.getLogger(EnvironmentServiceImpl.class);
    @Autowired
    private EnvironmentRepository environmentRepository;
    @Autowired
    private CloudVendorRepository vendorRepository;
    @Autowired
    private LockFactory lockFactory;

    @Override
    public BocloudResult<GridBean<Environment>> list(Pager pager, RequestContext context) {
        GridBean gridBean = null;
        try {
            List<Param> params = Optional.ofNullable(pager.getParams()).orElse(new ArrayList<>());
            Map<String, String> sorter = Optional.ofNullable(pager.getSorter()).orElse(Maps.newHashMap());
            Boolean simple = Optional.ofNullable(pager.getSimple()).orElse(false);
            sorter.put("gmtCreate", Common.ONE);
            Integer page = Optional.ofNullable(pager.getPage()).orElse(1);
            Integer rows = Optional.ofNullable(pager.getRows()).orElse(10);
            int total = this.environmentRepository.count(params);
            if (simple) {
                List<SimpleBean> beans = this.environmentRepository.list(params, sorter);
                gridBean = new GridBean(1, 1, total, beans);
            } else {
                List<Environment> beans = this.environmentRepository.list(page, rows, params, sorter);
                gridBean = GridHelper.getBean(page, rows, total, beans);
            }
            return new BocloudResult<>(true, gridBean, "查询成功");
        } catch (Exception e) {
            logger.error("Query Environment list fail:", e);
            return new BocloudResult<>(false, "查询失败");
        }

    }

    @Override
    public BocloudResult<Environment> create(Environment environment, RequestContext context) {
        try {
            if (environmentRepository.existName(environment.getName())) {
                return new BocloudResult<Environment>(false, "名称已存在");
            }
            environment.setCreatorId(context.getTarget());
            environment.setMenderId(context.getTarget());
            this.environmentRepository.save(environment);
            return new BocloudResult<Environment>(true, "添加成功");
        } catch (Exception e) {
            logger.error("creat environment error:", e);
            return new BocloudResult<Environment>(false, "添加失败");
        }
    }

    @Override
    public BocloudResult remove(Long id, RequestContext context) {
        String path = Environment.class.getSimpleName() + "_" + id;
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Environment environment = this.environmentRepository.query(id);
            if (null == environment) {
                logger.warn("Environment data not exist");
                return new BocloudResult<>(false, "数据不存在");
            }
            List<CloudVendor> vendors = vendorRepository.listByEnvId(id);
            if (!ListTool.isEmpty(vendors)) {
                return new BocloudResult<>(false, "该环境下存在正在使用的云平台，删除失败");
            }
            boolean result = this.environmentRepository.remove(id, context.getTarget());
            if (result) {
                return new BocloudResult<>(true, "删除成功");
            } else {
                return new BocloudResult<>(false, "删除失败");
            }
        } catch (Exception e) {
            logger.error("remove Environment fail:", e);
            return new BocloudResult<>(false, "删除环境失败");
        }
    }

    @Override
    public BocloudResult<Environment> detail(Long id) {
        try {
            Environment environment = this.environmentRepository.query(id);
            if (null == environment) {
                logger.warn("Environment data not exist");
                return new BocloudResult<Environment>(false, "数据不存在");
            }
            return new BocloudResult<Environment>(true, environment, "查询详情成功");
        } catch (Exception e) {
            logger.error("query Environment detail fail:", e);
            return new BocloudResult<Environment>(false, "查询详情失败");
        }
    }

    @Override
    public BocloudResult<Environment> modify(Environment bean, RequestContext context) {
        String path = Environment.class.getSimpleName() + "_" + bean.getId();
        try (BocloudACLock lock = lockFactory.getACLock(path)) {
            Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
            Environment environment = this.environmentRepository.query(bean.getId());
            if (null == environment) {
                logger.warn("Environment data not exist");
                return new BocloudResult<Environment>(false, "数据不存在");
            }
            if (!environment.getName().equals(bean.getName())) {
                if (environmentRepository.existName(bean.getName())) {
                    logger.warn("Environment already exist!");
                    return new BocloudResult<Environment>(false, "环境名称已存在");
                }
            }
            environment.setName(bean.getName());
            environment.setRemark(bean.getRemark());
            environment.setMenderId(context.getTarget());
            environment.setGmtModify(new Date());
            this.environmentRepository.update(environment);
            return new BocloudResult<Environment>(true, environment, "修改成功");
        } catch (Exception e) {
            logger.error("modify Environment fail:", e);
            return new BocloudResult<Environment>(false, "修改环境失败");
        }
    }

}
