package com.gci.boot.aspect;

import cn.hutool.core.util.StrUtil;
import com.gci.boot.annotation.permission.DataPermission;
import com.gci.boot.common.util.SpringContextUtil;
import com.gci.boot.constant.DataPermissionConstant;
import com.gci.boot.modules.basedata.entity.TbRepairShopArchives;
import com.gci.boot.modules.basedata.service.ITbRepairShopArchivesService;
import com.gci.boot.modules.projects.service.IProjectsService;
import com.gci.boot.modules.system.entity.SysRole;
import com.gci.boot.modules.system.service.ISysRoleService;
import com.gci.boot.modules.system.vo.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;

/**
  * 数据权限切面处理类
  *  当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息
 * @Date 2019年4月10日
 * @Version: 1.0
 */
@Aspect
@Component
@Slf4j
public class DataPermissionAspect {

	@Autowired
	private IProjectsService projectsService;
	@Autowired
	private ISysRoleService sysRoleService;
	@Autowired
	private ITbRepairShopArchivesService tbRepairShopArchivesService;

	@Pointcut("@annotation(com.gci.boot.annotation.permission.DataPermission)")
	public void pointCut() {
		
	}
	
	@Around("pointCut()")
	public Object arround(ProceedingJoinPoint point) throws Throwable{
		HttpServletRequest request = SpringContextUtil.getHttpServletRequest();
		String requestPath = request.getRequestURI().substring(request.getContextPath().length());
		String requestMethod = request.getMethod();
		requestPath = filterUrl(requestPath);
		log.info("DataPermissionAspect拦截请求 >> "+requestPath+";请求类型 >> "+requestMethod);
		MethodSignature signature = (MethodSignature) point.getSignature();
		Method method = signature.getMethod();
		DataPermission pd = method.getAnnotation(DataPermission.class);
		String item = pd.item();
		//处理特定的数据权限：按照项目projectId列表过滤
		LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
		if(sysUser==null || StringUtils.isEmpty(sysUser.getId())){
			throw new RuntimeException("用户未登录");
		}
		//获取角色：为判断超级管理员准备
		List<SysRole> listRole = sysRoleService.getRoleByUserId(sysUser.getId());
		if(CollectionUtils.isEmpty(listRole)){
			//角色配置为空
			throw new RuntimeException("角色配置为空");
		}
		StringBuilder sbRole = new StringBuilder();
		listRole.forEach(lRole -> {
			sbRole.append(","+lRole.getRoleCode());
		});
		String strRole = sbRole.toString();

		String sqlConditon = null;
		if(item.contains("projectId")){
			//判断用户身份：1_普通部门,2_维修厂,3_司机，4_客户公司其他人员，0、其他身份，并根据身份获取授权的项目列表
			List<String> listProjectIds = projectsService.queryProjectListOfUser();
			//超级管理员角色需放通
			if(strRole.contains("PM0000")){
				return point.proceed();
			}
			if(CollectionUtils.isEmpty(listProjectIds)){
				//项目清单为空，说明没有任何项目权限，禁止查看视频监控、司机管理等项目类列表
				sqlConditon = "1 != 1";
			}else{
				//组装项目id条件
				sqlConditon = buildProjectIds(item,listProjectIds,pd.stringIn());
			}
			request.setAttribute(DataPermissionConstant.DATA_PERMISSION_CONDITION, sqlConditon);
			request.setAttribute(DataPermissionConstant.DATA_PERMISSION_SQL_ID, pd.sqlIds());
		}
		return point.proceed();
	}

	private String buildProjectIds(String item, List<String> listProjectIds, boolean stringIn){

		String tableName = item.substring(0,item.lastIndexOf("."));

		StringBuilder sb = new StringBuilder();
		if (stringIn) {
			sb.append("string_to_array(").append(tableName).append(".project_id,',') &&");
			sb.append("string_to_array('").append(StrUtil.join(StrUtil.COMMA, listProjectIds)).append("',',')");
			return sb.toString();
		} else {
			sb.append(tableName+".project_id in (");
			listProjectIds.forEach(id -> {
				sb.append("'"+id+"',");
			});
			String res = sb.substring(0, sb.length() - 1);

			return res+")";
		}
	}

	private String buildCreateBy(String item,String username){
		String tableName = item.substring(0,item.lastIndexOf("."));
		StringBuilder sb = new StringBuilder();
		sb.append(tableName+".create_by='").append(username).append("'");
		return sb.toString();
	}

	private String buildRepairShop(String item,String userId){
		String res = null;
		String tableName = item.substring(0,item.lastIndexOf("."));
		List<TbRepairShopArchives> list = tbRepairShopArchivesService.getRepairShopByUserId(userId);
		if(CollectionUtils.isEmpty(list)){
			return "1 != 1";
		}
		StringBuilder sb = new StringBuilder();
		sb.append(tableName+".repair_shop in (");
		list.forEach(shop -> {
			sb.append("'"+shop.getId()+"',");
		});
		res = sb.substring(0, sb.length() - 1);
		return res+")";
	}

	/**
	 * 过滤url
	 * @param requestPath
	 * @return
	 */
	private String filterUrl(String requestPath){
		String url = "";
		if(requestPath != null && !requestPath.equals("") && !requestPath.equals("null")){
			url = requestPath.replace("\\", "/");
			url = requestPath.replace("//", "/");
			if(url.indexOf("//")>=0){
				url = filterUrl(url);
			}
			/*if(url.startsWith("/")){
				url=url.substring(1);
			}*/
		}
		return url;
	}

}
