package com.crunii.micro.service.sysmgr.jdbc;

import cn.hutool.core.util.ObjectUtil;
import com.crunii.micro.common.constants.CommonConstants;
import com.crunii.micro.common.dto.PageReq;
import com.crunii.micro.common.dto.PageRsp;
import com.crunii.micro.common.utils.SqlUtil;
import com.crunii.micro.common.utils.StreamUtils;
import com.crunii.micro.domain.common.jdbc.BaseJdbcTemplate;
import com.crunii.micro.domain.common.jdbc.BaseNPJdbcTemplate;
import com.crunii.micro.domain.dto.TsmRoleDto;
import com.crunii.micro.domain.dto.Worker;
import com.crunii.micro.domain.entity.main.*;
import com.crunii.micro.domain.repo.main.TsmRoleRepo;
import com.crunii.micro.domain.repo.main.TsmWorkerRoleRepo;
import com.crunii.micro.domain.util.CurrWorkerUtil;
import com.crunii.micro.service.sysmgr.RoleOrg;
import com.crunii.micro.service.sysmgr.constants.SysmgrConstants;
import com.crunii.micro.service.sysmgr.dto.sysmgr.RoleC;
import com.crunii.micro.service.sysmgr.dto.sysmgr.RoleReq;
import com.crunii.micro.service.sysmgr.dto.sysmgr.RoleResp;
import com.crunii.micro.service.sysmgr.dto.sysmgr.RoleU;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 田平 create 2017年8月11日下午12:44:04
 */
@Repository
public class RoleJdbcDao {
	public static final int SUPER_MANAGER = 9999;
	@Resource(name = "mainJT")
	protected BaseJdbcTemplate jdbcTemplate;

	@Resource(name = "mainNPJT")
	protected BaseNPJdbcTemplate baseNpJdbcTemplate;
	@Autowired
	private OrgJdbcDao orgJdbcDao;

	@Autowired
	private TsmRoleRepo tsmRoleRepo;

	@Autowired
	private TsmWorkerRoleRepo workerRoleRepo;

	private static final String PAGE_ROLE_BASE_SQL = "select * from tsm_role a where 1 = 1 ";

	private static final String PAGE_ROLE_COUNT_SQL = "select count(*) from tsm_role a where 1 = 1 ";

	private static final String GET_URL_GROUP_OF_ROLE_SQL = "select * from tsm_url_group where group_id in(select group_id from tsm_role_url_group where role_id=?) and state=1";

	public PageRsp<RoleResp> pageRole(PageReq<RoleReq> req) {
		PageRsp<RoleResp> page = new PageRsp<>();
		StringBuilder sb = new StringBuilder(PAGE_ROLE_BASE_SQL);
		StringBuilder sbCount = new StringBuilder(PAGE_ROLE_COUNT_SQL);
		Map<String, Object> params = new HashMap<>(16);
		// 获取当前登录用户
		Worker currWorker = CurrWorkerUtil.getCurrWorker();
		if (!CommonConstants.SUPER_LOGIN_IDS.contains(currWorker.getLoginId())) {
			List<TsmWorkerRole> userRoles = workerRoleRepo.findByLoginId(Integer.valueOf(currWorker.getLoginId()).longValue());
			List<Integer> userRoleIds = StreamUtils.toList(userRoles, TsmWorkerRole::getRoleId);
			// 2024-01-18更改:超级管理员的角色可以查看所有的角色
			if (!userRoleIds.contains(SysmgrConstants.SUPER_ADMIN_ROLE_ID)) {
				// 非超级管理员只看自己拥有的角色
				sb.append("and a.role_id in (:userRoleIds)");
				sbCount.append("and a.role_id in (:userRoleIds)");
				params.put("userRoleIds", userRoleIds);
			}
		}
		if (StringUtils.hasText(req.getQuery().getRoleName())) {
			sb.append(" and a.role_name like concat('%',:roleName,'%') ");
			sbCount.append(" and a.role_name like concat('%',:roleName,'%') ");
			params.put("roleName", req.getQuery().getRoleName());
		}
		if (Objects.nonNull(req.getQuery().getState())) {
			sb.append(" and a.state = :state ");
			sbCount.append(" and a.state = :state ");
			params.put("state", req.getQuery().getState());
		}
		int total = baseNpJdbcTemplate.queryForInt(sbCount.toString(), params);
		List<RoleResp> result;
		String dbType = baseNpJdbcTemplate.getDbType();
		if (total > 0) {
			//根据数据库类型设置limit
			SqlUtil.appendLimit(dbType, params, sb, req);
			result = baseNpJdbcTemplate.queryForBeans(RoleResp.class, sb.toString(), params);
		} else {
			result = new ArrayList<>(0);
		}
		if (!CollectionUtils.isEmpty(result)) {
			List<Long> roleIds = StreamUtils.toList(result, RoleResp::getRoleId);
			String sql = "select b.role_id, a.org_id, a.org_code, a.org_name " +
					"from TSM_ORG a left join TSM_ROLE_ORG b on a.org_id = b.org_id " +
					"where b.role_id in (:roleIds)";
			Map<String, Object> orgParams = new HashMap<>(16);
			orgParams.put("roleIds", roleIds);
			List<RoleOrg> roleOrgList = baseNpJdbcTemplate.queryForBeans(RoleOrg.class, sql, orgParams);
			Map<Long, List<RoleOrg>> roleOrgListMap = StreamUtils.groupByKey(roleOrgList, RoleOrg::getRoleId);

			Map<String, Object> appParams = new HashMap<>(16);
			appParams.put("roleIds", roleIds);
			sql = "select * from TSM_ROLE_APP where role_id in (:roleIds)";
			List<TsmRoleApp> appList = baseNpJdbcTemplate.queryForBeans(TsmRoleApp.class, sql, appParams);
			Map<Long, List<TsmRoleApp>> appListMap = StreamUtils.groupByKey(appList, TsmRoleApp::getRoleId);

			for (RoleResp item : result) {
				item.setOrgs(Optional.ofNullable(roleOrgListMap.get(item.getRoleId())).orElse(Collections.emptyList()));
				item.setApps(Optional.ofNullable(appListMap.get(item.getRoleId())).orElse(Collections.emptyList()));
			}
		}
		page.setPageNo(req.getPageNo());
		page.setPageSize(req.getPageSize());
		page.setTotalNum(total);
		page.setResult(result);
		// 为手机计算是否由下一页
		page.next();
		return page;
	}

	public List<TsmRole> selectRoleList(RoleReq req) {
		StringBuilder sb = new StringBuilder(PAGE_ROLE_BASE_SQL);
		List<Object> params = new ArrayList<>();
		if(req != null){
			if (StringUtils.hasText(req.getRoleName())) {
				sb.append(" and a.role_name like concat('%',?,'%') ");
				params.add(req.getRoleName());
			}
			if(Objects.nonNull(req.getState())){
				sb.append(" and a.state = ? ");
				params.add(req.getState());
			}
		}

		return jdbcTemplate.queryForBeans(TsmRole.class, sb.toString(), params.toArray());
	}

	public void updateRole(RoleU roleU) {
		TsmRole role = tsmRoleRepo.getOne(roleU.getRoleId());
		BeanUtils.copyProperties(roleU, role);
		tsmRoleRepo.save(role);
		tsmRoleRepo.flush();
		String deleteSql = "delete from TSM_ROLE_ORG where role_id = " + roleU.getRoleId();
		jdbcTemplate.update(deleteSql);
		for (Long id : roleU.getOrgIds()) {
			String sql = "insert into TSM_ROLE_ORG (role_id,org_id) values (?,?)";
			jdbcTemplate.update(sql, roleU.getRoleId(), id);
		}
	}

	public void createRole(RoleC roleC) {
		TsmRole role = new TsmRole();
		BeanUtils.copyProperties(roleC, role);
		role.setState(roleC.getState());
		role.setCreateTime(new Date());
		int roleId = tsmRoleRepo.save(role).getRoleId();
		for (Long id : roleC.getOrgIds()) {
			String sql = "insert into TSM_ROLE_ORG (role_id,org_id) values (?,?)";
			jdbcTemplate.update(sql, roleId, id);
		}
	}

	public List<TsmUrlGroup> getUrlGroupOfRole(int roleId) {
		return jdbcTemplate.queryForBeans(TsmUrlGroup.class, GET_URL_GROUP_OF_ROLE_SQL, roleId);
	}

	/**
	 * 获取登录用户
	 */
	private Worker getWorker() {
		Worker worker = CurrWorkerUtil.getCurrWorker();
		if (ObjectUtil.isEmpty(worker)) {
			throw new RuntimeException("获取当前登录用户失败");
		}
		return worker;
	}

	public List<YcqAppConfigUrl> findRoleApp(Worker worker) {
		String sql = " select a.app_id, a.app_code,a.system_name,a.sponsor,a.logo_url,a.app_name, " +
				" a.app_url,a.sort,to_char(a.create_time, 'yyyy-MM-dd hh24:mi:ss') as create_time,a.public_key,a.private_key, " +
				" a.must_hex,a.must_auth,a.state,a.notes,a.sponsor,a.app_type, " +
				" (case when a.app_type=1 then '自有应用' when a.app_type=2 then '外部应用' else null end) as appTypeName, " +
				" a.is_clear_local_storage " +
				" from ycq_app_config_url a left join TSM_ROLE_APP b on a.app_id = b.app_id " +
				" where a.state = 1 and b.role_id in (select role_id from TSM_WORKER_ROLE where login_id = ?) order by sort asc ";
		List<YcqAppConfigUrl> dto = jdbcTemplate.queryForBeans(YcqAppConfigUrl.class, sql,worker.getLoginId());
		if(dto.size()>0){
			List<YcqAppConfigUrl> urlDto = dto.stream()
					.distinct()
					.collect(Collectors.toList());
			return urlDto;
		}
		return dto;
	}

	public List<YcqAppConfigUrl> findRoleAppVisitor() {
		String sql = " select a.app_id, a.app_code,a.system_name,a.sponsor,a.logo_url,a.app_name, " +
				" a.app_url,a.sort,to_char(a.create_time, 'yyyy-MM-dd hh24:mi:ss') as create_time,a.public_key,a.private_key, " +
				" a.must_hex,a.must_auth,a.state,a.notes,a.sponsor,a.app_type, " +
				" (case when a.app_type=1 then '自有应用' when a.app_type=2 then '外部应用' else null end) as appTypeName, " +
				" a.is_clear_local_storage " +
				" from ycq_app_config_url a left join TSM_ROLE_APP b on a.app_id = b.app_id " +
				" where a.state = 1 and b.role_id = 9998 order by sort asc ";
		List<YcqAppConfigUrl> dto = jdbcTemplate.queryForBeans(YcqAppConfigUrl.class, sql);
		return dto;
	}
}
