package com.bocloud.ims.repository.resource;

import com.bocloud.common.model.Pager;
import com.bocloud.common.model.Param;
import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.database.utils.PageHelper;
import com.bocloud.database.utils.QueryBuilder;
import com.bocloud.ims.entity.resource.StorageGroup;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

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

@Repository("storageGroupRepository")
public class StorageGroupRepository extends BasicGenericDao<StorageGroup, Long> {

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

	public List<StorageGroup> list(int page, int rows, List<Param> params, Map<String, String> sorter)
			throws Exception {
		String sql = "select a.* from "
				+ " (select aa.*, bb.name as storage_name, bb.vendor_id, ifnull(cc.member_count,0) as member_count "
				+ "  from storage_group aa "
				+ "  left join storage bb on aa.storage_id = bb.id "
				+ "  left join (select group_id, count(member_id) as member_count from storage_group_member group by group_id) cc on aa.id = cc.group_id"
				+ "  where aa.is_deleted = 0) a " + "where 1=1 ";
		sql = QueryBuilder.buildRaw(sql, new Pager(page, rows, params, sorter), "a");
		return this.list(StorageGroup.class, sql);
	}

	public int count(List<Param> params) {
		String sql = "select count(1) from " + " (select aa.*, bb.vendor_id from storage_group aa "
				+ "  left join storage bb on aa.storage_id = bb.id " + "  where aa.is_deleted = 0) a " + "where 1=1 ";
		sql = QueryBuilder.buildRaw(sql, params, null, "a");
		Map<String, Object> param = QueryBuilder.getParam(params);
		return this.countQuery(sql, param).intValue();
	}

	public void remove(long id) {
		String sql = "update storage_group set is_deleted = 1 where id = :id ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("id", id);
		execute(sql, params);
	}

	public void removeByStorage(long storageId, String type) {
		String sql = "update storage_group set is_deleted = 1 where storage_id = :storageId and type =:type ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("storageId", storageId);
		params.put("type", type);
		execute(sql, params);
	}

	public List<StorageGroup> listByStorage(long storageId, String type) {
		String sql = "select a.* from storage_group a where is_deleted = 0 and storage_id = :storageId and type =:type ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("storageId", storageId);
		params.put("type", type);
		return this.list(StorageGroup.class, sql, params);
	}

	public StorageGroup get(long id) {
		String sql = "select a.*, b.name as storage_name from storage_group a "
				+ "left join storage b on a.storage_id = b.id " + "where a.id = :id ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("id", id);
		List<StorageGroup> list = this.list(StorageGroup.class, sql, params);
		return list == null || list.size() == 0 ? null : list.get(0);
	}

	public StorageGroup getByUuidAndStorage(String uuid, long storageId) {
		String sql = "select a.* from storage_group a where is_deleted = 0 and group_uuid = :uuid and storage_id = :storageId ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("uuid", uuid);
		params.put("storageId", storageId);
		List<StorageGroup> list = this.list(StorageGroup.class, sql, params);
		return list == null || list.size() == 0 ? null : list.get(0);
	}

	public StorageGroup getByNameAndStorage(String name, String type, long storageId) {
		String sql = "select a.* from storage_group a where is_deleted = 0 and name = :name and type =:type and storage_id = :storageId ";
		Map<String, Object> params = new HashMap<>(8);
		params.put("name", name);
		params.put("storageId", storageId);
		params.put("type", type);
		List<StorageGroup> list = this.list(StorageGroup.class, sql, params);
		return list == null || list.size() == 0 ? null : list.get(0);
	}

	public List<StorageGroup> listByMember(Integer page, Integer rows, Map<String, Object> paramMap,
			Map<String, String> sorter) {
		String sql = " select a.*, c.name as storage_name, b.member_count from storage_group a "
				+ " left join (select group_id, count(member_id) as member_count from storage_group_member group by group_id) b on a.id = b.group_id"
				+ " left join storage c on a.storage_id = c.id " + " where a.is_deleted = 0 ";
		Map<String, Object> sqlParams = new HashMap<>(8);
		if (paramMap.containsKey("memberId")) {
			sql += " and a.id in (select group_id from storage_group_member where member_id = :memberId)";
			sqlParams.put("memberId", paramMap.get("memberId"));
		}
		if (paramMap.containsKey("type")) {
			sql += " and a.type = :type";
			sqlParams.put("type", paramMap.get("type"));
		}
		if (paramMap.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + paramMap.get("name") + "%");
		}
		sql += PageHelper.buildPageSql(page, rows);
		return this.list(StorageGroup.class, sql, sqlParams);
	}

	public List<StorageGroup> listForMember(Integer page, Integer rows, Map<String, Object> paramMap,
			Map<String, String> sorter) {
		String sql = " select a.*, c.name as storage_name, ifnull(b.member_count,0) as member_count from storage_group a "
				+ " left join (select group_id, count(member_id) as member_count from storage_group_member group by group_id) b on a.id = b.group_id"
				+ " left join storage c on a.storage_id = c.id " + " where a.is_deleted = 0 ";
		Map<String, Object> sqlParams = new HashMap<>(8);
		if (paramMap.containsKey("memberId")) {
			sql += " and a.id not in (select group_id from storage_group_member where member_id = :memberId)";
			sqlParams.put("memberId", paramMap.get("memberId"));
		}
		if (paramMap.containsKey("type")) {
			sql += " and a.type = :type";
			if ("VG".equals(paramMap.get("type"))) {
				sql += " and a.storage_id = (select storage_id from volume where id = :memberId)";
				sqlParams.put("memberId", paramMap.get("memberId"));
			} else if ("HG".equals(paramMap.get("type"))) {
				sql += " and a.storage_id = (select storage_id from storage_host where id = :memberId)";
				sqlParams.put("memberId", paramMap.get("memberId"));
			}
			sqlParams.put("type", paramMap.get("type"));
		}
		if (paramMap.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + paramMap.get("name") + "%");
		}
		sql += PageHelper.buildPageSql(page, rows);
		return this.list(StorageGroup.class, sql, sqlParams);
	}

	public int countListByMember(Map<String, Object> paramMap) {
		String sql = " select count(1) from storage_group a "
				+ " left join (select group_id, count(member_id) as member_count from storage_group_member group by group_id) b on a.id = b.group_id"
				+ " left join storage c on a.storage_id = c.id " + " where a.is_deleted = 0 ";
		Map<String, Object> sqlParams = new HashMap<>(8);
		if (paramMap.containsKey("memberId")) {
			sql += " and a.id in (select group_id from storage_group_member where member_id = :memberId)";
			sqlParams.put("memberId", paramMap.get("memberId"));
		}
		if (paramMap.containsKey("type")) {
			sql += " and a.type = :type";
			sqlParams.put("type", paramMap.get("type"));
		}
		if (paramMap.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + paramMap.get("name") + "%");
		}
		return this.countQuery(sql, sqlParams).intValue();
	}

	public int countListForMember(Map<String, Object> paramMap) {
		String sql = " select count(1) from storage_group a "
				+ " left join (select group_id, count(member_id) as member_count from storage_group_member group by group_id) b on a.id = b.group_id"
				+ " left join storage c on a.storage_id = c.id " + " where a.is_deleted = 0 ";
		Map<String, Object> sqlParams = new HashMap<>(8);
		if (paramMap.containsKey("memberId")) {
			sql += " and a.id not in (select group_id from storage_group_member where member_id = :memberId)";
			sqlParams.put("memberId", paramMap.get("memberId"));
		}
		if (paramMap.containsKey("type")) {
			sql += " and a.type = :type";
			if ("VG".equals(paramMap.get("type"))) {
				sql += " and a.storage_id = (select storage_id from volume where id = :memberId)";
				sqlParams.put("memberId", paramMap.get("memberId"));
			} else if ("HG".equals(paramMap.get("type"))) {
				sql += " and a.storage_id = (select storage_id from storage_host where id = :memberId)";
				sqlParams.put("memberId", paramMap.get("memberId"));
			}
			sqlParams.put("type", paramMap.get("type"));
		}
		if (paramMap.containsKey("name")) {
			sql += " and a.name like :name";
			sqlParams.put("name", "%" + paramMap.get("name") + "%");
		}
		return this.countQuery(sql, sqlParams).intValue();
	}
}
