package com.yifu.cloud.plus.v1.permission.service.impl;/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the yifu4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.permission.mapper.SysMenuMapper;
import com.yifu.cloud.plus.v1.permission.mapper.SysUserInfoMapper;
import com.yifu.cloud.plus.v1.permission.mapper.SysUserPermissionMapper;
import com.yifu.cloud.plus.v1.permission.service.SysMenuService;
import com.yifu.cloud.plus.v1.permission.service.SysRoleInfoService;
import com.yifu.cloud.plus.v1.permission.service.SysUserInfoService;
import com.yifu.cloud.plus.v1.permission.service.SysUserRoleResService;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.mybatis.base.BaseEntity;
import com.yifu.cloud.plus.v1.yifu.permission.entity.SysMenu;
import com.yifu.cloud.plus.v1.yifu.permission.entity.SysUserInfo;
import com.yifu.cloud.plus.v1.yifu.permission.entity.SysUserPermission;
import com.yifu.cloud.plus.v1.yifu.permission.entity.SysUserRoleRes;
import com.yifu.cloud.plus.v1.yifu.permission.vo.SysUserInfoSaveVo;
import com.yifu.cloud.plus.v1.yifu.permission.vo.SysUserInfoSearchVo;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 新权限-账号管理表
 *
 * @author hgw
 * @date 2023-08-29 14:49:40
 */
@Log4j2
@Service
@AllArgsConstructor
public class SysUserInfoServiceImpl extends ServiceImpl<SysUserInfoMapper, SysUserInfo> implements SysUserInfoService {

	private final SysUserRoleResService sysUserRoleResService;
	private final SysRoleInfoService sysRoleInfoService;
	private final SysMenuMapper sysMenuMapper;
	private final SysUserPermissionMapper sysUserPermissionMapper;

	/**
	 * 新权限-账号管理表简单分页查询
	 *
	 * @param sysUserInfo 新权限-账号管理表
	 * @return
	 */
	@Override
	public IPage<SysUserInfo> getSysUserInfoPage(Page<SysUserInfo> page, SysUserInfoSearchVo sysUserInfo) {
		return baseMapper.getSysUserInfoPage(page, sysUserInfo);
	}

	@Override
	public List<SysUserInfo> noPageDiy(SysUserInfoSearchVo searchVo) {
		LambdaQueryWrapper<SysUserInfo> wrapper = buildQueryWrapper(searchVo);
		List<String> idList = Common.getList(searchVo.getIds());
		if (Common.isNotNull(idList)) {
			wrapper.in(SysUserInfo::getFdId, idList);
		}
		if (searchVo.getLimitStart() >= 0 && searchVo.getLimitEnd() > 0) {
			wrapper.last(" limit " + searchVo.getLimitStart() + "," + searchVo.getLimitEnd());
		}
		wrapper.orderByDesc(BaseEntity::getCreateTime);
		return baseMapper.selectList(wrapper);
	}

	private LambdaQueryWrapper buildQueryWrapper(SysUserInfoSearchVo entity) {
		LambdaQueryWrapper<SysUserInfo> wrapper = Wrappers.lambdaQuery();
		if (Common.isNotNull(entity.getFdName())) {
			wrapper.like(SysUserInfo::getFdName, entity.getFdName());
		}
		if (Common.isNotNull(entity.getFdLoginName())) {
			wrapper.eq(SysUserInfo::getFdLoginName, entity.getFdLoginName());
		}
		if (Common.isNotNull(entity.getFdDeptName())) {
			wrapper.like(SysUserInfo::getFdDeptName, entity.getFdDeptName());
		}
		if (Common.isNotNull(entity.getRoleNames())) {
			wrapper.like(SysUserInfo::getRoleNames, entity.getRoleNames());
		}
		if (Common.isNotNull(entity.getStatus())) {
			wrapper.eq(SysUserInfo::getStatus, entity.getStatus());
		}
		if (ArrayUtil.isNotEmpty(entity.getCreateTimes())) {
			wrapper.ge(SysUserInfo::getCreateTime, entity.getCreateTimes()[0])
					.le(SysUserInfo::getCreateTime,
							entity.getCreateTimes()[1]);
		}
		if (Common.isNotNull(entity.getCreateName())) {
			wrapper.eq(SysUserInfo::getCreateName, entity.getCreateName());
		}
		return wrapper;
	}

	/**
	 * @param fdId
	 * @Description: 查看详情
	 * @Author: hgw
	 * @Date: 2023/8/30 18:14
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<com.yifu.cloud.plus.v1.yifu.permission.vo.SysUserInfoSaveVo>
	 **/
	@Override
	public R<SysUserInfoSaveVo> getInfoById(String fdId) {
		SysUserInfoSaveVo vo = new SysUserInfoSaveVo();
		SysUserInfo user = this.getById(fdId);
		if (user != null && Common.isNotNull(user.getFdId())) {
			List<SysUserRoleRes> resList = baseMapper.getResAndRoleNameUserId(user.getFdLoginName());
			vo.setUser(user);
			if (resList != null && !resList.isEmpty()) {
				// 各种角色的权限融合
				String dataAuth = sysRoleInfoService.getAllRoleDataAuthByUserId(user.getFdLoginName());
				vo.setDataAuth(dataAuth);
			}
			vo.setResList(resList);
		}
		return R.ok(vo);
	}

	/**
	 * @param vo
	 * @Description: 新增或编辑新权限-角色表
	 * @Author: hgw
	 * @Date: 2023/8/30 15:24
	 * @return: com.yifu.cloud.plus.v1.yifu.common.core.util.R<java.lang.String>
	 **/
	@Override
	public R<String> saveOrUpdateUserInfo(SysUserInfoSaveVo vo) {
		SysUserInfo user = vo.getUser();
		List<SysUserRoleRes> resList = vo.getResList();
		if (user != null && Common.isNotNull(user.getFdName()) && resList != null && !resList.isEmpty()) {
			if (Common.isNotNull(user.getFdLoginName())) {
				sysUserRoleResService.deleteByUserId(user.getFdLoginName());
			}
			this.saveOrUpdate(user);
			for (SysUserRoleRes res : resList) {
				res.setUserId(user.getFdId());
				res.setLoginName(user.getFdLoginName());
			}
			sysUserRoleResService.saveBatch(resList);
			return R.ok("保存成功");
		}
		return R.failed("请检查信息");
	}

	/**
	 * @param
	 * @Description: 同步并更新账号信息
	 * @Author: hgw
	 * @Date: 2023/9/4 11:31
	 * @return: java.lang.String
	 **/
	@Override
	public void doRefreshEkpUser() {
		List<SysUserInfo> ekpUser = baseMapper.getEkpUser();
		this.saveOrUpdateBatch(ekpUser);
	}


	private final SysMenuService sysMenuService;

	/**
	 * @param modelId
	 * @param userId
	 * @Description: 给EKP用的，获取权限
	 * @Author: hgw
	 * @Date: 2023/9/8 16:04
	 * @return: void
	 **/
	@Override
	public String testPermission(String modelId, String userId) {
		//1：获取菜单是否已配置，是：第2步；否：结束，用EKP本身权限；
		//2：获取账号，有：第3步；无：结束，用EKP；
		//3：检测账号的角色 是否有 对应的菜单，有，第4不，无：结束，用ekp；
		//4：查询角色的数据权限，如果是全量或部分全量，检测当前菜单是否有对应维度，有，直接查全量，无，第5步；
		//5：查询用户当前菜单数据权限，拼接sql：
		//and ((客户字段 in (客户1,客户2))
		//or (商机字段 in (商机1,商机2))
		//)——最后一个括号放在最后合上，此处可以去掉
		//6：判断创建人权限；
		//or (docCreateUser = 账号id)
		//7：部门权限
		//如果有部门权限，先查部门以及下属部门的所有账号id；
		//第6步的sql要改为：
		//or (docCreateUser in (账号id,其他账号id))

		StringBuilder sql = new StringBuilder();
		// 测试权限
		SysMenu menu = sysMenuMapper.getSysMenuByModelId(modelId);
		if (menu != null) {
			// 返回0：无配置；1：全量；2：继续下一步，找数据权限配置
			int allAuth = baseMapper.getAuthByUserIdAndModelId(modelId, userId);
			if (allAuth == 0) {
				sql.append(" 1=2 ");
			} else if (allAuth == 1) {
				sql.append(" 1=1 ");
			} else {
				sql.append(" 1=2 ");
				// 继续下一步，找数据权限配置
				List<SysUserPermission> permissionList = sysUserPermissionMapper.getUserPermissionByUserId(userId);
				if (permissionList != null && !permissionList.isEmpty() ) {
					setAuthSql(sql, "1", menu.getCustomerId(), permissionList);
					setAuthSql(sql, "2", menu.getBussinessId(), permissionList);
					setAuthSql(sql, "3", menu.getQuotationId(), permissionList);
					setAuthSql(sql, "4", menu.getContractId(), permissionList);
					setAuthSql(sql, "5", menu.getDomainId(), permissionList);
					setAuthSql(sql, "6", menu.getBuId(), permissionList);
					setAuthSql(sql, "7", menu.getLineId(), permissionList);
					setAuthSql(sql, "9", menu.getIncomeId(), permissionList);
					// TODO-部门
					setAuthSqlByDept(sql, menu.getDeptId(), permissionList);
				}
			}
		}
		if (Common.isNotNull(sql) && sql.length() > 0) {
			return " or ( " + sql + " ) ";
		}
		return "";
	}

	private void setAuthSql(StringBuilder sql, String type, String shuXing, List<SysUserPermission> permissionList) {
		if (Common.isNotNull(shuXing)) {
			StringBuilder tempValue = new StringBuilder();
			for (SysUserPermission permission : permissionList) {
				if (("6".equals(type) || "7".equals(type)) && type.equals(permission.getPermissionType()) && Common.isNotNull(permission.getName())) {
					tempValue.append("'").append(permission.getName()).append("',");
				} else if (type.equals(permission.getPermissionType()) && Common.isNotNull(permission.getCode())) {
					tempValue.append("'").append(permission.getCode()).append("',");
				}
			}
			if (tempValue.length() > 0) {
				tempValue.deleteCharAt(tempValue.length() - 1);
			}
			sql.append(" or (").append(shuXing).append(" in (").append(tempValue).append("))");
		}
	}

	private void setAuthSqlByDept(StringBuilder sql, String shuXing, List<SysUserPermission> permissionList) {
		if (Common.isNotNull(shuXing)) {
			StringBuilder tempValue = new StringBuilder();
			for (SysUserPermission permission : permissionList) {
				if ("8".equals(permission.getPermissionType()) && Common.isNotNull(permission.getCode())) {
					tempValue.append("'").append(permission.getCode()).append("',");
				}
			}
			if (tempValue.length() > 0) {
				tempValue.deleteCharAt(tempValue.length() - 1);
			}
			sql.append(" or (").append(shuXing).append(" in (").append(tempValue).append("))");
		}
	}


	/**
	 * 新权限-账号管理表简单分页查询
	 *
	 * @param code
	 * @return
	 */
	@Override
	public IPage<SysUserInfo> getUserByCodeOrLoginName(Page<SysUserInfo> page, String code) {
		return baseMapper.getUserByCodeOrLoginName(page, code);
	}
}
