package com.yifu.cloud.plus.v1.yifu.admin.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.*;
import com.yifu.cloud.plus.v1.yifu.admin.api.util.TreeUtil;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.BusinessRoleMenuVo;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.BusinessUserVo;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.MenuTreeForVue;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.RoleMenuR;
import com.yifu.cloud.plus.v1.yifu.admin.service.*;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CacheConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ClientNameConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.ServiceNameConstants;
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.core.util.RedisUtil;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ArchivesDaprUtil;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: master
 * @description: b端用户权限控制器
 * @author: fxj
 * @create: 2022-09-25 11:12
 **/
@RestController
@AllArgsConstructor
@RequestMapping("/customerBusiness/user")
@Tag(name = "b端用户权限控制器")
@Slf4j
public class BusinessUserController {

    private final SysUserService userService;
    private final SysMenuService sysMenuService;
    @Autowired
    protected RemoteTokenServices remoteTokenServices;
    @Autowired
    protected ArchivesDaprUtil remoteBasicArchivesService;

    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

    private final SysRoleService roleService;

    private final SysUserRoleService userRoleService;

    // 字典
    private final SysDictService sysDictService;

    private final RedisUtil redisUtil;


    /**
     * 获取b端用户分页
     *
     * @param page
     * @return
     * @Author fxj
     * @Date 2020-08-25 11:25
     **/
    @GetMapping("/page")
    @Operation(description = "B端用户分页")
    public R<Page<BusinessUserVo>> getBusinessUserPage(Page<BusinessUserVo> page, BusinessUserVo user) {
        user.setDeptId(CommonConstants.HR_B_ORG_ID);
		user.setType(CommonConstants.TWO_STRING);
        Page<BusinessUserVo> businessUserVoPage = userService.getBusinessUserVoPage(page, user);
        //获取客户信息
        if(Common.isNotNull(businessUserVoPage.getRecords())){
            List<String> userList = new ArrayList<>();
            // 封装查询条件
            for(BusinessUserVo vo:businessUserVoPage.getRecords()){
                userList.add(vo.getUserId());
            }
			Map<String, String> customerUserMap = null;
			// 查询条件客户名
			R<Map<String, String>> resR = remoteBasicArchivesService.getCustomerUserMap(userList);
			if (Common.isNotNull(resR) && Common.isNotNull(resR.getData())){
				customerUserMap = resR.getData();
			}
			//信息封装
            if(Common.isNotNull(customerUserMap)){
                for(BusinessUserVo vo:businessUserVoPage.getRecords()){
                    vo.setCustomerName(customerUserMap.get(vo.getUserId().toString()));
                }
            }
        }
        return new R<>(businessUserVoPage);
    }
    /**
     * 新建b端用户
     *
     * @return
     * @Author fxj
     * @Date 2020-08-25 11:25
     **/
    @PostMapping("/saveBusinessUser")
    @Operation(description = "新建b端用户")
    public R<SysUser> saveBusinessUser(@RequestBody SysUser user) {
        //数据验证
        if(Common.isEmpty(user.getNickname())){
            return R.failed("姓名不能为空");
        }
        //数据填充
        user.setUsername(user.getUsername());
        user.setLockFlag(CommonConstants.ZERO_STRING);
        user.setDelFlag(CommonConstants.ZERO_STRING);
        user.setCreateTime(LocalDateTime.now());
        user.setDeptName("客户单位");
		user.setType(CommonConstants.TWO_STRING);
        //使用根节点
        user.setDeptId(CommonConstants.HR_B_ORG_ID);
        if (Common.isNotNull(user.getPassword())){
            user.setPassword(ENCODER.encode(user.getPassword()));
        }
        //系统规定检查
        SysUser  sysUser = null;
        SysUser  userTemp = null;
        if (null != user && null != user.getUserId()){
            sysUser = userService.getOne(Wrappers.<SysUser>lambdaQuery()
					.eq(SysUser::getUsername,user.getUsername())
					.ne(SysUser::getUserId,user.getUserId())
                    .last(CommonConstants.LAST_ONE_SQL));
            if (Common.isNotNull(user.getPhone())){
                userTemp = userService.getOne(Wrappers.<SysUser>lambdaQuery()
						.eq(SysUser::getPhone, user.getPhone())
						.ne(SysUser::getUserId,user.getUserId())
						.eq(SysUser::getType,CommonConstants.TWO_STRING)
                        .last(CommonConstants.LAST_ONE_SQL));
            }
        }else {
            sysUser = userService.getOne(Wrappers.<SysUser>lambdaQuery()
					.eq(SysUser::getUsername,user.getUsername())
					.last(CommonConstants.LAST_ONE_SQL));
            if (Common.isNotNull(user.getPhone())){
                userTemp = userService.getOne(Wrappers.<SysUser>lambdaQuery()
						.eq(SysUser::getPhone, user.getPhone())
						.eq(SysUser::getType,CommonConstants.TWO_STRING)
						.last(CommonConstants.LAST_ONE_SQL));
            }
        }
        if(null != sysUser){
            return R.failed("操作失败，该账号已存在！");
        }
        if(null != userTemp){
            return R.failed("操作失败，该手机号已存在！");
        }
        //存储并返回数据
        boolean res;
        if (Common.isNotNull(user.getUserId())){
            res = userService.updateById(user);
        }else {
            res = userService.save(user);
        }
        if(res){
            return new R<>(user);
        }else{
            return R.failed("插入失败请联系管理员！");
        }
    }

    /**
     * 获取b端角色信息和菜单
     *
     * @return
     * @Author fxj
     * @Date 2020-08-25 11:25
     **/
    @GetMapping("/getRoleAndMenu")
    @Operation(description = "获取b端角色信息和菜单,TYPE:类型 0：菜单 1：按钮 2：菜单加按钮（默认查菜单）,userId:用户id")
    public R<RoleMenuR> getRoleAndMenu(String type, String userId) {
        //结果声明
        RoleMenuR result = new RoleMenuR();
        //结果初始化
        Map<String,String> roleNameMap = new HashMap<>();
        Map<String, List<BusinessRoleMenuVo>> roleMenuMap = new HashMap<>();


        //默认获取菜单
        if(Common.isEmpty(type)){
            type = CommonConstants.ZERO_STRING;
        }else if(CommonConstants.dingleDigitStrArray[2].equals(type)){
            type = null;
        }
        List<BusinessRoleMenuVo> list = roleService.getRoleAndMenu(type);
        //组装结果
        if(Common.isNotNull(list)){
            //临时变量
            List<BusinessRoleMenuVo> businessRoleMenuVo = null;
           for(BusinessRoleMenuVo vo:list){
                 //不是第一次出现的角色把菜单放入对应map的对应集合即可
                 if(roleMenuMap.containsKey(vo.getRoleId())){
                     businessRoleMenuVo = roleMenuMap.get(vo.getRoleId());
                 }else{
                     //第一次出现的角色创建一个集合把菜单放进去，并把角色信息放进roleNameMap做权限组展示
                     businessRoleMenuVo = new ArrayList<>();
                     roleMenuMap.put(vo.getRoleId(),businessRoleMenuVo);
                     roleNameMap.put(vo.getRoleId(),vo.getRoleName());
                 }
               businessRoleMenuVo.add(vo);
           }
           //获取用户已有权限
            if(null != userId){
                result.setHavaRole(roleService.getRoleByUserIdAndClient(userId, ServiceNameConstants.CLIENT_ID_HR_B));
            }
        }
		result.setRoleNameMap(roleNameMap);
		result.setRoleMenuMap(roleMenuMap);
        return new R<>(result);
    }
    /**
     * 返回当前用户的树形菜单集合
     *
     * @return 当前用户的树形菜单
     */
    @Operation(description = "返回当前用户的树形菜单集合")
    @GetMapping("/menu")
    public R<List<MenuTreeForVue>> getUserMenuForVue(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader, String type) {
        // 获取符合条件的菜单
        Set<SysMenu> all = new HashSet<>();
        SecurityUtils.getRolesByClient(ClientNameConstants.CLIENT_B)
                .forEach(roleId -> all.addAll(sysMenuService.findMenuByRoleId(roleId)));
        List<MenuTreeForVue> menuTreeList;
        if (Common.isNotNull(type)) {
            menuTreeList = all.stream()
                    .filter(menuVo -> type.equals(menuVo.getType()))
                    .map(MenuTreeForVue::new)
                    .sorted(Comparator.comparingInt(MenuTreeForVue::getSort))
                    .collect(Collectors.toList());
        } else {
            menuTreeList = all.stream()
                    .map(MenuTreeForVue::new)
                    .sorted(Comparator.comparingInt(MenuTreeForVue::getSort))
                    .collect(Collectors.toList());
        }
        return new R<>(TreeUtil.bulid(menuTreeList, -1));
    }
    /**
     * 获取b端角色信息和菜单
     *
     * @return
     * @Author fxj
     * @Date 2020-08-25 11:25
	 * name = "roleList", value = "角色（权限组）id集合"
	 * name = "userId", value = "用户id"
     **/
    @PostMapping("/saveRoleM")
    @Operation(description = "b端用户角色关系保存")
    public R<String> saveRoleM(@RequestBody List<Long> roleList, String userId) {
        if(null == userId){
            return R.failed("用户id不能为空！");
        }
        if(Common.isEmpty(roleList)){
            return R.failed("权限组不能为空！");
        }
        List<SysUserRole> list = new ArrayList<>();
        SysUserRole userRole = null;
        for(Long role:roleList){
            if( null != role ){
                userRole = new SysUserRole();
                userRole.setRoleId(role);
                userRole.setUserId(Common.isBlankToNullString(userId));
                list.add(userRole);
            }
        }
        if(Common.isNotNull(list)){
            userRoleService.removeByUserAndClientId(userId, ServiceNameConstants.CLIENT_ID_HR_B);
            userRoleService.saveBatch(list);
            //清除用户缓存
            SysUser user = userService.getById(userId);
            if(null != user){
                redisUtil.remove(CacheConstants.USER_DETAILS +"::"+ user.getUsername());
                if( Common.isNotNull(user.getPhone())){
                    redisUtil.remove(CacheConstants.USER_DETAILS + "_phone::"+ user.getPhone());
                }
            }
            return R.ok(CommonConstants.RESULT_DATA_SUCESS);
        }else{
            return R.failed("保存失败，用户角色数据错误！");
        }
    }

    /**
     * b端获取用户信息
     *
     * @return
     * @Author fxj
     * @Date 2020-08-25 11:25
     **/
    @GetMapping("/userInfo/{userId}")
    @Operation(description = "b端获取用户信息")
    public R<SysUser> getUserInfo(@PathVariable Integer userId) {
        //获取用户信息
        return new R<>(userService.getById(userId));
    }
    /**
     * 存在的方法 复制到这 便于控制权限 通过ID更新用户锁定状态
     *
     * @param id ID
     * @return 用户信息
     */
    @Operation(description = "通过ID更新用户锁定状态")
    @GetMapping("/updateLock")
    public R<Boolean> updateLockFlag(@RequestParam("id") String id, @RequestParam("lockFlag") String lockFlag) {
        SysUser user = userService.getById(id);
        if (null == user) {
            return R.failed("操作失败，无此用户！");
        }
        if(CommonConstants.HR_B_ORG_ID != user.getDeptId()){
            return R.failed("操作失败，此客户非b端用户，不允许在此禁（启）用！");
        }
        return new R<>(userService.updateLockFlagById(user, lockFlag));
    }

	/**
	 * 通过字典类型查找字典值
	 * @param itemType 类型
	 * @return 同类型字典
	 */
	@Operation(description = "通过字典类型查找字典值")
	@GetMapping("/itemType/{itemType}")
	public R<List<SysDictItem>> getDictByType(@PathVariable String itemType) {
		return new R<>(sysDictService.findDetailsByItemType(itemType));
	}
}
