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.Vpc;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

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

/**
 * vpc Repository实现
 *
 * @author wangyu
 * @version 1.0
 * @since 2018年2月2日
 */
@Repository("vpcRepository")
public class VpcRepository extends BasicGenericDao<Vpc, Long> {

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

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

    public Vpc query(Long id) {
        String sql =
                "SELECT v.* , r.name region_name, t.name tenant_name, project.visibility project_visibility, rg.name resource_group_name FROM vpc v "
                        + " left join region r on r.vendor_id = v.vendor_id and r.region_id = v.region_id "
                        + " left join project project on v.project_id = project.id "
                        + " left join resource_group rg on v.resource_group_uuid = rg.resource_group_uuid and v.vendor_id = rg.vendor_id "
                        + " left join tenant t on v.tenant_id = t.id  WHERE v.id = :id AND v.is_deleted = 0  ";
        Map<String, Object> params = MapTools.simpleMap(Common.ID, id);
        List<Vpc> list = this.list(Vpc.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public boolean delete(Long id, Long userId) {
        String sql = "update vpc 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 delete(Long id) {
        String sql = "update vpc set is_deleted = 1, gmt_modify = :gmtModify where id = :id";
        Map<String, Object> params = MapTools.simpleMap("id", id);
        params.put("gmtModify", new Date());
        return this.execute(sql, params) > 0;
    }

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

    public List<Vpc> list(int page, int rows, List<Param> params, Map<String, String> sorter) {
        String sql =
                "select a.*,v.type vendor_type, v.name vendor_name, r.name region_name, project.visibility project_visibility, rg.name resource_group_name, t.name tenant_name from vpc a"
                        + " left join region r on a.region_id = r.region_id and a.vendor_id = r.vendor_id "
                        + " left join resource_group rg on a.resource_group_uuid = rg.resource_group_uuid and a.vendor_id = rg.vendor_id "
                        + " left join project project on a.project_id = project.id left join tenant t on a.tenant_id = t.id "
                        + " left join cloud_vendor v on a.vendor_id = v.id where a.is_deleted = 0";
        sql = QueryBuilder.build(sql, new Pager(page, rows, params, sorter), "a");
        Map<String, Object> param = QueryBuilder.getParam(params);
        return this.list(Vpc.class, sql, param);
    }

    public List<SimpleBean> list(List<Param> params, Map<String, String> sorter, String labelContent) {
        String sql = "select a.id,a.name,a.vpc_id from vpc a where a.is_deleted = 0";
        sql = appendLabelSearch(labelContent, sql);
        sql = QueryBuilder.build(sql, new Pager(1, Integer.MAX_VALUE, params, sorter), "a");
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        List<Vpc> list = this.list(Vpc.class, sql, paramMap);
        List<SimpleBean> beans = new ArrayList<>();
        for (Vpc vpc : list) {
            SimpleBean simpleBean = new SimpleBean(vpc.getId(), vpc.getName(), vpc.getVpcId());
            beans.add(simpleBean);
        }
        return beans;
    }

    public int count(List<Param> params) {
        String sql = "select count(1) from vpc a where a.is_deleted = 0";
        sql = QueryBuilder.build(sql, params, null, "a");
        Map<String, Object> param = QueryBuilder.getParam(params);
        return this.countQuery(sql, param).intValue();
    }

    /**
     * @param labelContent
     * @return int
     * @Author: lxy
     * @Description: 带有标签的数量统计
     * @Date 2021/9/9 10:41
     * @Param params
     * @throws:
     **/
    public int countByLabel(List<Param> params, String labelContent) {
        String sql = "select count(1) from vpc a where a.is_deleted = 0";
        sql = appendLabelSearch(labelContent, sql);
        sql = QueryBuilder.build(sql, params, null, "a");
        Map<String, Object> param = QueryBuilder.getParam(params);
        return this.countQuery(sql, param).intValue();
    }

    public int count(List<Param> params, Long tenantId, List<Long> projectIds) {
        String sql = " select count(a.id) from vpc a where a.is_deleted = 0 ";
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (null != tenantId && 0L != tenantId) {
            sql += " and a.tenant_id = :tenantId";
            paramMap.put("tenantId", tenantId);
        }
        if (!ListTool.isEmpty(projectIds)) {
            sql += " and a.project_id in (:projectIds) ";
            paramMap.put("projectIds", projectIds);
        }
        sql = QueryBuilder.buildRaw(sql, params, null, "a");
        return this.countQuery(sql, paramMap).intValue();
    }

    public List<Vpc> list(int page, int rows, List<Param> params, Map<String, String> sorter, Long tenantId,
                          List<Long> projectIds) {
        String sql =
                "select a.*,v.name vendor_name,v.type vendor_type, r.name region_name,t.name tenant_name,ob.expired_time, rg.name resource_group_name from vpc a left join object_relation ob on a.id = ob.res_id and ob.category = 'Vpc'"
                        + " left join region r on a.vendor_id = r.vendor_id and a.region_id = r.region_id "
                        + " left join resource_group rg on a.resource_group_uuid = rg.resource_group_uuid and a.vendor_id = rg.vendor_id "
                        + " left join tenant t on a.tenant_id = t.id left join cloud_vendor v on a.vendor_id = v.id"
                        + " left join project project on a.project_id = project.id  where a.is_deleted = 0 ";
        Map<String, Object> paramMap = QueryBuilder.getParam(params);
        if (null != tenantId && 0L != tenantId) {
            sql += " and a.tenant_id = :tenantId";
            paramMap.put("tenantId", tenantId);
        }
        if (!ListTool.isEmpty(projectIds)) {
            sql += " and a.project_id in (:projectIds) ";
            paramMap.put("projectIds", projectIds);
        }
        sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
        return this.list(Vpc.class, sql, paramMap);
    }

    public List<Vpc> list(Long vendorId, String regionId) {
        String sql = "select * from vpc where vendor_id = :vendorId and is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        if (!StringUtils.isEmpty(regionId)) {
            sql += " and region_id = :regionId ";
            params.put(Common.REGIONID, regionId);
        }
        return this.list(Vpc.class, sql, params);
    }

    public List<Vpc> listByNetworkId(Long networkId) {
        String sql = "select * from vpc where network_id = :networkId and is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("networkId", networkId);
        return this.list(Vpc.class, sql, params);
    }

    public List<Vpc> listByRouterId(Long routerId, Long vendorId) {
        String sql = "select * from vpc where router_id = :routerId and is_deleted = 0 and vendor_id = :vendorId";
        Map<String, Object> params = MapTools.simpleMap("routerId", routerId);
        params.put("vendorId", vendorId);
        return this.list(Vpc.class, sql, params);
    }

    public List<Vpc> listByProjectId(Long projectId) {
        String sql = "select * from vpc where project_id = :projectId and is_deleted = 0";
        Map<String, Object> params = MapTools.simpleMap("projectId", projectId);
        return this.list(Vpc.class, sql, params);
    }

    public Vpc getByName(Long vendorId, String name) {
        String sql = "select a.* from vpc a where a.is_deleted = 0 and a.vendor_id = :vendorId and a.name = :name";
        Map<String, Object> paramMap = MapTools.simpleMap("vendorId", vendorId);
        paramMap.put("name", name);
        List<Vpc> list = this.list(Vpc.class, sql, paramMap);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public Vpc getByName(Long vendorId, String name, String regionId) {
        String sql =
                "select a.* from vpc a where a.is_deleted = 0 and a.vendor_id = :vendorId and a.name = :name and a.region_id = :regionId ";
        Map<String, Object> paramMap = MapTools.simpleMap("vendorId", vendorId);
        paramMap.put("name", name);
        paramMap.put("regionId", regionId);
        List<Vpc> list = this.list(Vpc.class, sql, paramMap);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public Vpc getByUuid(String uuid) {
        String sql = "select a.* from vpc a where a.is_deleted = 0 and a.uuid = :uuid";
        Map<String, Object> paramMap = MapTools.simpleMap("uuid", uuid);
        List<Vpc> list = this.list(Vpc.class, sql, paramMap);
        return ListTool.isEmpty(list) ? null : list.get(0);
    }

    public List<Vpc> list(Long vendorId, String regionId, Long tenantId) {
        String sql = "select * from vpc where vendor_id = :vendorId and is_deleted = 0" + " and region_id = :regionId ";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put(Common.REGIONID, regionId);
        if (null != tenantId && tenantId > 0) {
            sql += " and tenant_id= :tenantId ";
            params.put("tenantId", tenantId);
        }
        return this.list(Vpc.class, sql, params);
    }

    public boolean deleteByVid(Long vendorId, String regionId, Long userId) {
        String sql =
                "update vpc set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId"
                        + " and region_id = :regionId ";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put(Common.REGIONID, regionId);
        params.put("gmtModify", new Date());
        params.put("menderId", userId);
        return this.execute(sql, params) > 0;
    }

    public boolean deleteByNetworkId(Long networkId, Long menderId) {
        String sql =
                "update vpc set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where network_id = :networkId";
        Map<String, Object> params = MapTools.simpleMap("networkId", networkId);
        params.put("gmtModify", new Date());
        params.put("menderId", menderId);
        return this.execute(sql, params) > 0;
    }

    public Vpc query(String vpcUuid, Long vendorId) {
        String sql = " select v.* from vpc v where v.is_deleted = 0 and v.vendor_id = :vendorId and v.vpc_id = :vpcId";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put("vpcId", vpcUuid);
        List<Vpc> list = this.list(Vpc.class, sql, params);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    public boolean deleteByRouterId(Long routerId, Long vendorId, Long userId) {
        String sql =
                "update vpc set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId"
                        + " and router_id = :routerId ";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put("routerId", routerId);
        params.put("gmtModify", new Date());
        params.put("menderId", userId);
        return this.execute(sql, params) > 0;
    }

    public Vpc getByUuid(String vpcUuid, Long vendorId) {
        String sql =
                "select a.* from vpc a where a.is_deleted = 0 and a.vpc_id = :vpcUuid and a.vendor_id = :vendorId ";
        Map<String, Object> paramMap = MapTools.simpleMap("vpcUuid", vpcUuid);
        paramMap.put("vendorId", vendorId);
        List<Vpc> list = this.list(Vpc.class, sql, paramMap);
        return ListTool.isEmpty(list) ? null : list.get(0);
    }

    public boolean removeByGroupName(Long vendorId, Long userId, String resourceGroupName) {
        String sql =
                "update vpc set is_deleted = 1, gmt_modify = :gmtModify, mender_id = :menderId where vendor_id = :vendorId and azure_resource_group_name = :resourceGroupName ";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put("gmtModify", new Date());
        params.put("resourceGroupName", resourceGroupName);
        params.put("menderId", userId);
        return this.execute(sql, params) > 0;
    }

    public List<Vpc> listByGroupId(Long vendorId, Long resourceGroupId) {
        String sql =
                "select * from vpc where vendor_id = :vendorId and is_deleted = 0 and resource_group_id = :resourceGroupId";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put("resourceGroupId", resourceGroupId);
        return this.list(Vpc.class, sql, params);
    }

    public List<Vpc> list(int page, int rows, List<Param> params, Map<String, String> sorter, Boolean hasEip,
                          Boolean hasIpv6, Boolean notGateWay, String labelContent) {
        String sql =
                "select a.*,v.type vendor_type, v.name vendor_name, r.name region_name, rg.display_name resource_group_name from vpc a"
                        + " left join region r on a.region_id = r.region_id and a.vendor_id = r.vendor_id "
                        + " left join resource_group rg on a.resource_group_uuid = rg.resource_group_uuid and a.vendor_id = rg.vendor_id and rg.is_deleted = 0 "
                        + " left join cloud_vendor v on a.vendor_id = v.id and v.is_deleted = 0 where a.is_deleted = 0";
        if (notGateWay) {
            sql =
                    "select a.*,v.type vendor_type, v.name vendor_name, r.name region_name, rg.display_name resource_group_name from vpc a"
                            + " left join region r on a.region_id = r.region_id and a.vendor_id = r.vendor_id "
                            + " left join resource_group rg on a.resource_group_uuid = rg.resource_group_uuid and a.vendor_id = rg.vendor_id and rg.is_deleted = 0 "
                            + " left join cloud_vendor v on a.vendor_id = v.id and v.is_deleted = 0 left join internet_gateway g on a.vpc_id=g.vpc_id and g.is_deleted=0  and a.region_id=g.region_id and a.vendor_id=g.vendor_id"
                            + " where a.is_deleted = 0 and g.vpc_id is null";
        }
        if (hasEip) {
            sql =
                    "select a.*,v.type vendor_type, v.name vendor_name, r.name region_name, rg.display_name resource_group_name from vpc a"
                            + " left join region r on a.region_id = r.region_id and a.vendor_id = r.vendor_id "
                            + " left join resource_group rg on a.resource_group_uuid = rg.resource_group_uuid and a.vendor_id = rg.vendor_id and rg.is_deleted = 0"
                            + " left join cloud_vendor v on a.vendor_id = v.id and v.is_deleted = 0 left join internet_gateway g on a.vpc_id=g.vpc_id and g.is_deleted=0  and a.region_id=g.region_id and a.vendor_id=g.vendor_id"
                            + " where a.is_deleted = 0 and g.vpc_id is not null";
        }
        if (hasIpv6) {
            sql += " and a.ipv6_cidr is not null";
        }
        sql = appendLabelSearch(labelContent, sql);
        sql = QueryBuilder.build(sql, new Pager(page, rows, params, sorter), "a");
        Map<String, Object> param = QueryBuilder.getParam(params);
        return this.list(Vpc.class, sql, param);
    }

    public List<Vpc> listByPlanUuid(Long vendorId, String regionId, String ddosPlanUuid) {
        String sql =
                "select * from vpc where vendor_id = :vendorId and is_deleted = 0 and region_id = :regionId and ddos_plan_uuid = :ddosPlanUuid";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put("regionId", regionId);
        params.put("ddosPlanUuid", ddosPlanUuid);
        return this.list(Vpc.class, sql, params);
    }

    public List<Vpc> listByRsg(Long vendorId, String regionId, Long tenantId, String resourceGroupName) {
        String sql = "select * from vpc where vendor_id = :vendorId and is_deleted = 0"
                + " and region_id = :regionId and azure_resource_group_name = :resourceGroupName ";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put(Common.REGIONID, regionId);
        params.put("resourceGroupName", resourceGroupName);
        if (null != tenantId && tenantId > 0) {
            sql += " and tenant_id= :tenantId ";
            params.put("tenantId", tenantId);
        }
        return this.list(Vpc.class, sql, params);
    }

    public List<Vpc> listByResourceGroupUuid(Long vendorId, String regionId, String resourceGroupUuid) {
        String sql =
                "select * from vpc where vendor_id = :vendorId and is_deleted = 0 and region_id = :regionId and resource_group_uuid = :resourceGroupUuid";
        Map<String, Object> params = MapTools.simpleMap("vendorId", vendorId);
        params.put(Common.REGIONID, regionId);
        params.put("resourceGroupUuid", resourceGroupUuid);
        return this.list(Vpc.class, sql, params);
    }

    public int count(List<Param> params, String vendorType, String labelContent) {
        String sql = "select count(1) from vpc a left join cloud_vendor c on a.vendor_id = c.id where a.is_deleted = 0";
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and c.type = '" + vendorType + "'  ";
        }
        sql = appendLabelSearch(labelContent, sql);
        sql = QueryBuilder.build(sql, params, null, "a");
        Map<String, Object> param = QueryBuilder.getParam(params);
        return this.countQuery(sql, param).intValue();
    }

    public List<Vpc> list(int page, int rows, List<Param> params, Map<String, String> sorter, String vendorType, String labelContent) {
        String sql =
                "select a.*,v.type vendor_type, v.name vendor_name, r.name region_name, project.visibility project_visibility, rg.name resource_group_name, t.name tenant_name from vpc a"
                        + " left join region r on a.region_id = r.region_id and a.vendor_id = r.vendor_id "
                        + " left join resource_group rg on a.resource_group_uuid = rg.resource_group_uuid and a.vendor_id = rg.vendor_id "
                        + " left join project project on a.project_id = project.id left join tenant t on a.tenant_id = t.id "
                        + " left join cloud_vendor v on a.vendor_id = v.id where a.is_deleted = 0";
        if (!StringUtils.isEmpty(vendorType)) {
            sql += " and v.type = '" + vendorType + "'  ";
        }
        sql = appendLabelSearch(labelContent, sql);
        sql = QueryBuilder.build(sql, new Pager(page, rows, params, sorter), "a");
        Map<String, Object> param = QueryBuilder.getParam(params);
        List<Vpc> list = this.list(Vpc.class, sql, param);
        return list;
    }

    /**
     * @param sql
     * @return java.lang.String
     * @Author: lxy
     * @Description: 拼接标签查询
     * @Date 2021/9/7 14:36
     * @Param labelContent
     * @throws:
     **/
    private String appendLabelSearch(String labelContent, String sql) {
        if (!StringUtils.isEmpty(labelContent)) {
            String[] split = labelContent.split(":");
            sql += " and a.resource_label like '%\"key\":\""
                    + split[0] + "\"%' and a.resource_label like '%\"value\":\"" + split[1] + "\"%'  ";
        }
        return sql;
    }

}
