package com.bocloud.ims.repository.resource;

import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.database.utils.QueryBuilder;
import com.bocloud.ims.entity.resource.PoolGroup;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 资源池数据访问
 *
 * @author wangyu
 * @version 1.0
 * @since 2020年5月15日
 */
@Repository("poolGroupRepository") public class PoolGroupRepository extends BasicGenericDao<PoolGroup, Long> {

    public PoolGroupRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate) {
        super(jdbcTemplate, npJdbcTemplate);
    }

    public List<PoolGroup> list(int page, int rows, List<Param> params, Map<String, String> sorter) throws Exception {
        String sql =
            "select a.*,b.name vendor_name,b.type vendor_type, r.name region_name,z.name az_name from pool_group a "
                + " left join cloud_vendor b on b.id = a.vendor_id "
                + " left join region r on a.region = r.region_id and a.vendor_id = r.vendor_id "
                + " left join zone z on a.availablitiy_zone = z.zone_id and a.vendor_id = z.vendor_id "
                + " where a.is_deleted = 0";
        sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        return this.list(PoolGroup.class, sql, paramMap);
    }

    public List<SimpleBean> list(List<Param> params, Map<String, String> sorter) throws Exception {
        String sql = "select a.id,a.name from pool_group a where 1 = 1 ";
        sql = QueryBuilder.build(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        List<PoolGroup> groups = this.list(PoolGroup.class, sql, paramMap);
        List<SimpleBean> beans = new ArrayList<>();
        for (PoolGroup group : groups) {
            beans.add(new SimpleBean(group.getId(), group.getName()));
        }
        return beans;
    }

    public int count(List<Param> params) throws Exception {
        String sql = "select count(a.id) from pool_group a " + " left join cloud_vendor b on b.id = a.vendor_id "
            + " left join region r on a.region = r.region_id and a.vendor_id = r.vendor_id "
            + " left join zone z on a.availablitiy_zone = z.zone_id and a.vendor_id = z.vendor_id "
            + " where a.is_deleted = 0";
        sql = QueryBuilder.buildRaw(sql, params, new HashMap<>(8), "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        return this.countQuery(sql, paramMap).intValue();
    }

    public List<PoolGroup> list(Long parentId, String category) throws Exception {
        String sql =
            "select a.*,b.name vendor_name,b.type vendor_type from pool_group a left join cloud_vendor b on b.id = a.vendor_id where a.is_deleted = 0 and a.parent_id = :parentId ";
        Map<String, Object> params = MapTools.simpleMap("parentId", parentId);
        if (!StringUtils.isEmpty(category)) {
            sql += "  and a.category = :category";
            params.put("category", category);
        }
        return this.list(PoolGroup.class, sql, params);
    }

    public List<PoolGroup> listByCategory(String category) throws Exception {
        String sql =
            "select a.*,b.name vendor_name,b.type vendor_type from pool_group a left join cloud_vendor b on b.id = a.vendor_id where a.is_deleted = 0 and a.category = :category ";
        Map<String, Object> params = MapTools.simpleMap("category", category);
        return this.list(PoolGroup.class, sql, params);
    }

    public boolean delete(Long id, Long userId) throws Exception {
        String sql =
            "update pool_group set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        params.put("gmtModify", new Date());
        params.put("menderId", userId);
        return this.execute(sql, params) > 0;
    }

    public boolean updateStatus(Long id, String status, Long menderId) throws Exception {
        String sql =
            "update pool_group set status = :status, gmt_modify = :gmtModify, mender_id = :menderId where id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        params.put("gmtModify", new Date());
        params.put("status", status);
        params.put("menderId", menderId);
        return this.execute(sql, params) > 0;
    }

    public List<PoolGroup> listAll() throws Exception {
        String sql =
            "select a.*,b.name vendor_name,b.type vendor_type from pool_group a left join cloud_vendor b on b.id = a.vendor_id where a.is_deleted = 0";
        return this.list(PoolGroup.class, sql);
    }

    public PoolGroup query(Long id) throws Exception {
        String sql =
            "select a.*,b.name vendor_name,b.type vendor_type from pool_group a left join cloud_vendor b on b.id = a.vendor_id where a.is_deleted = 0 and a.id = :id";
        Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
        List<PoolGroup> list = this.list(PoolGroup.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public List<PoolGroup> getByRegion(String region, String az, String vendorType, List<Long> poolGroupIds) {
        String sql =
            " select a.*, b.`name` vendor_name,r.`name` region_name, r.id reg_id from pool_group a left join cloud_vendor b on b.id = a.vendor_id "
                + " left join region r on a.region = r.region_id and a.vendor_id = r.vendor_id "
                + " where  a.is_deleted = 0 and a.status = 'NORMAL' ";
        Map<String, Object> params = new HashMap<>();
        if (!StringUtils.isEmpty(region)) {
            sql += " and a.region = :region ";
            params.put("region", region);
        }
        if (!StringUtils.isEmpty(az)) {
            sql += " and a.availablitiy_zone = :az ";
            params.put("az", az);
        }
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and b.type = :vendorType ";
            params.put("vendorType", vendorType);
        }
        if (!ListTool.isEmpty(poolGroupIds)) {
            sql += " and a.id in (:poolGroupIds) ";
            params.put("poolGroupIds", poolGroupIds);
        }
        return this.list(PoolGroup.class, sql, params);
    }

    public PoolGroup getByRegion(String region, String az, String vendorType) throws Exception {
        String sql =
            "select a.* from pool_group a left join cloud_vendor b on b.id = a.vendor_id where a.region = :region and a.availablitiy_zone = :az and b.type = :vendorType and a.is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("region", region);
        params.put("az", az);
        params.put("vendorType", vendorType);
        List<PoolGroup> list = this.list(PoolGroup.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public PoolGroup getByRegion(String region, Long vendorId) throws Exception {
        String sql =
            "select a.* from pool_group a where a.region = :region and a.vendor_id = :vendorId and a.is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("region", region);
        params.put("vendorId", vendorId);
        List<PoolGroup> list = this.list(PoolGroup.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public String getGroupNameByResourceTarget(Long targetId, String category, String catalog) throws Exception {
        String sql = "select pg.name from pool_group pg left join resource r on r.group_id = pg.id "
            + "where pg.is_deleted = 0 and r.is_deleted = 0 and r.target = :targetId "
            + "and r.category = :category and r.catalog = :catalog";
        Map<String, Object> params = MapTools.simpleMap("targetId", targetId);
        params.put("category", category);
        params.put("catalog", catalog);
        List<PoolGroup> list = this.list(PoolGroup.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0).getName();
    }

    public PoolGroup exists(String name, String category) throws Exception {
        String sql = "select * from pool_group where is_deleted = 0 and name = :name ";
        Map<String, Object> params = MapTools.simpleMap("name", name);
        if (null != category) {
            sql += " and category = :category ";
            params.put("category", category);
        }
        List<PoolGroup> list = this.list(PoolGroup.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 查询业务绑定的资源池列表
     *
     * @param category
     * @param businessId
     * @param envId
     * @param labelIds
     * @return
     * @throws Exception
     */

    public List<PoolGroup> list(String category, Long businessId, Long envId, List<Long> labelIds) throws Exception {
        String sql =
            "select a.*,v.name vendor_name,v.type vendor_type from pool_group a left join pool_group_label b on a.id = b.pool_group_id left join cloud_vendor v on v.id = a.vendor_id where a.is_deleted = 0 and a.category = :category and a.id in (select pool_group_id from business_pool where business_id = :businessId)";
        Map<String, Object> params = MapTools.simpleMap("category", category);
        params.put("businessId", businessId);
        if (null != envId && 0L != envId) {
            sql += " and v.env_id = :envId";
            params.put("envId", envId);
        }
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and b.label_id in (:labelIds)";
            params.put("labelIds", labelIds);
        }
        return this.list(PoolGroup.class, sql, params);
    }

    public List<PoolGroup> list(Long tenantId, Long vendorId, String category) throws Exception {
        String sql =
            "select DISTINCT a.* from pool_group a left join tenant_pool b on b.pool_group_id = a.id where a.vendor_id = :vendorId";
        Map<String, Object> params = MapTools.simpleMap(Common.VENDORID, vendorId);
        if (null != tenantId && 0 != tenantId) {
            sql += " and b.tenant_id = :tenantId";
            params.put("tenantId", tenantId);
        }
        if (null != category && !"".equals(category)) {
            sql += " and a.category = :category";
            params.put("category", category);
        }
        return this.list(PoolGroup.class, sql, params);
    }

	public boolean removeByVid(Long vendorId, Long userId) throws Exception {
		String sql = "update pool_group set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId";
		Map<String, Object> params = MapTools.simpleMap(Common.VENDORID, vendorId);
		params.put("gmtModify", new Date());
		params.put("menderId", userId);
		return this.execute(sql, params) > 0;
	}
    
	public boolean removeByVid(Long vendorId, String region, Long userId) throws Exception {
		String sql = "update pool_group set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId and region = :region ";
		Map<String, Object> params = MapTools.simpleMap(Common.VENDORID, vendorId);
		params.put("region", region);
		params.put("gmtModify", new Date());
		params.put("menderId", userId);
		return this.execute(sql, params) > 0;
	}

    /**
     * 根据租户id查询
     *
     * @param tenantId
     * @return
     * @throws Exception
     */

    public List<PoolGroup> listByTenantId(Long tenantId, String category, List<Long> labelIds, Long envId,
        String vendorType) throws Exception {
        String sql =
            "select DISTINCT a.*,c.name vendor_name,c.type vendor_type from pool_group a left join tenant_pool b on b.pool_group_id = a.id left join cloud_vendor c on c.id = a.vendor_id left join pool_group_label d on a.id = d.pool_group_id where b.tenant_id = :tenantId and a.is_deleted = 0 ";
        Map<String, Object> params = MapTools.simpleMap("tenantId", tenantId);
        if (null != category && !"".equals(category)) {
            sql += " and a.category = :category ";
            params.put("category", category);
        }
        if (null != envId && 0L != envId) {
            sql += " and c.env_id = :envId";
            params.put("envId", envId);
        }
        if (!ListTool.isEmpty(labelIds)) {
            sql += " and d.label_id in (:labelIds)";
            params.put("labelIds", labelIds);
        }
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and c.type = :vendorType";
            params.put("vendorType", vendorType);
        }
        return this.list(PoolGroup.class, sql, params);
    }

    public List<PoolGroup> listByIds(List<Long> ids) {
        String sql = "select * from pool_group where is_deleted = 0 and id in (:ids)";
        return this.list(PoolGroup.class, sql, MapTools.simpleMap("ids", ids));
    }

    public List<PoolGroup> listByIds(List<Long> ids, String vendorType) throws Exception {
        String sql =
            "select a.* from pool_group a left join cloud_vendor c on a.vendor_id = c.id where a.is_deleted = 0 and a.id in (:ids)  ";
        Map<String, Object> simpleMap = MapTools.simpleMap("ids", ids);
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and c.type = :vendorType ";
            simpleMap.put("vendorType", vendorType);
        }
        return this.list(PoolGroup.class, sql, simpleMap);
    }

    public PoolGroup getByRegion(String region, String az, Long vendorId, String category) throws Exception {
        String sql =
            "select a.* from pool_group a where a.region = :region and a.availablitiy_zone = :az and a.vendor_id = :vendorId and a.is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("region", region);
        params.put("az", az);
        params.put("vendorId", vendorId);
        if (!StringUtils.isEmpty(category)) {
            sql += " and a.category = :category ";
            params.put("category", category);
        }
        List<PoolGroup> list = this.list(PoolGroup.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public List<PoolGroup> listByVendorId(Long vendorId) {
        String sql = "select a.* from pool_group a where a.is_deleted = 0 and a.vendor_id = :vendorId ";
        Map<String, Object> simpleMap = MapTools.simpleMap("vendorId", vendorId);
        return this.list(PoolGroup.class, sql, simpleMap);
    }

    /**
     * 查询租户独占的资源池
     *
     * @return
     */
    public List<PoolGroup> listTenantPrivate() {
        String sql =
            "select a.* from pool_group a left join tenant_pool tp on a.id = tp.pool_group_id where a.is_deleted = 0 and a.binding_policy = 'exclusive' and tp.pool_group_id is not null ";
        return this.list(PoolGroup.class, sql);
    }
}
