/**
 * Copyright &copy; 2021-2026 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.jeeplus.sys.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeeplus.common.SecurityUtils;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.common.constant.CacheNames;
import com.jeeplus.common.constant.CommonConstants;
import com.jeeplus.common.redis.RedisUtils;
import com.jeeplus.sys.domain.Cert;
import com.jeeplus.sys.domain.Office;
import com.jeeplus.sys.domain.SysConfig;
import com.jeeplus.sys.domain.User;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.mapper.OfficeMapper;
import com.jeeplus.sys.mapper.UserMapper;
import com.jeeplus.sys.service.dto.CertDTO;
import com.jeeplus.sys.service.dto.OfficeDTO;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.sys.service.mapstruct.CertWrapper;
import com.jeeplus.sys.service.mapstruct.UserWrapper;
import com.jeeplus.sys.utils.UserUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 用户管理
 *
 * @author jeeplus
 * @version 2021-09-05
 */
@Service
@Transactional
public class UserService extends ServiceImpl <UserMapper, User> {

    // 通过 -?[0-9]+(\\\\.[0-9]+)? 进行匹配是否为数字
    private static Pattern pattern = Pattern.compile("-?[0-9]+(\\\\.[0-9]+)?");

    @Autowired
    private UserWrapper userWrapper;

    @Resource
    private UserMapper userMapper;

    @Autowired
    private OfficeService officeService;

    @Autowired
    private OfficeMapper officeMapper;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private CertService certService;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 根据用户id 查询该用户会计报告的签字注师被选择次数
     * @param userId
     * @return
     */
    public Integer getAccountantUserCount(String userId) {
        return userMapper.getAccountantUserCount (userId);
    }

    public List<CertDTO> getCertListByUserId(){
        return userMapper.getCertListByUserId();
    }

    //	保存人员执业资质
    public void saveCertList(UserDTO userDTO) {
        if (ObjectUtil.isNotEmpty(userDTO)) {
            if (CollectionUtil.isNotEmpty(userDTO.getCertDTOList())) {
                List<String> ids = userDTO.getCertDTOList().stream().filter(item -> {
                    if (StringUtils.isNotBlank(item.getId())) {
                        return true;
                    }
                    return false;
                }).map(CertDTO::getId).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(ids)) {
                    certService.remove(new QueryWrapper<Cert>().lambda().eq(Cert::getUserId,userDTO.getId()).notIn(Cert::getId,ids));
                }else{
                    certService.remove(new QueryWrapper<Cert>().lambda().eq(Cert::getUserId,userDTO.getId()));
                }
                userDTO.getCertDTOList().stream().forEach(item->{
                    Cert cert = CertWrapper.INSTANCE.toEntity(item);
                    cert.setUserId(userDTO.getId());
                    certService.saveOrUpdate(cert);
                });
            } else {
                certService.remove(new QueryWrapper<Cert>().lambda().eq(Cert::getUserId,userDTO.getId()));
            }
        }
    }


    /**
     * 根据角色英文名称查询角色下人员信息
     * @param enName 角色英文名称
     * @return
     */
    public List<UserDTO> getUserInfoByEnName(String enName){
        return userMapper.getUserInfoByEnName(enName);
    }


    /**
     * 根据登录名获取用户
     * @param name
     * @return
     */
    public UserDTO getUserByName(String name) {
        UserDTO userDTO = userMapper.getUserByName(name);
        return userDTO;
    }

    /**
     * 获取用户
     *
     * @param id
     * @return
     */
    public UserDTO get(String id) {
        QueryWrapper queryWrapper = new QueryWrapper ( );
        queryWrapper.eq ( "a.id", id );
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); // 排除已经删除
        UserDTO userDTO = baseMapper.get(queryWrapper);
        //根据用户id查询其管理部门
        if(null != userDTO && StringUtils.isNotBlank(userDTO.getId())){
            String manageOfficeIdsById = baseMapper.getManageOfficeIdsById(userDTO.getId());
            if(StringUtils.isNotBlank(manageOfficeIdsById)){
                userDTO.setManageOfficeIds(manageOfficeIdsById);
                //获取当前人管理的部门id
                List<String> manageOfficeIdList= Arrays.asList(userDTO.getManageOfficeIds().split(","));
                //查询这些部门信息
                List<String> officeNameList = officeService.getOfficeNameByIds(manageOfficeIdList);
                userDTO.setManageOfficeNameList(officeNameList);
            }
        }
        return userDTO;
    }

    /**
     * 获取用户
     *
     * @param id
     * @return
     */
    public UserDTO getFlowAbleById(String id) {
        QueryWrapper queryWrapper = new QueryWrapper ( );
        queryWrapper.eq ( "a.id", id );
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); // 排除已经删除
        return userMapper.getFlowAbleById ( queryWrapper );
    }

    /**
     * 根据登录名获取用户
     *
     * @param loginName
     * @return
     */
    public UserDTO getUserByLoginName(String loginName, String tenantId) {
        UserDTO userDTO = (UserDTO) RedisUtils.getInstance ( ).get ( CacheNames.USER_CACHE_LOGIN_NAME, tenantId + ":" + loginName );
        if ( userDTO == null ) {
            QueryWrapper queryWrapper = new QueryWrapper ( );
            //判断是否是用手机号登录
            Matcher m = pattern.matcher(loginName);
            if (m.matches()){
                queryWrapper.eq ("a.mobile", loginName);
            } else {
                queryWrapper.eq ( "a.login_name", loginName );
            }

            queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED );
            queryWrapper.eq ( "a.tenant_id", tenantId );
            userDTO = baseMapper.get ( queryWrapper );
            RedisUtils.getInstance ( ).set ( CacheNames.USER_CACHE_LOGIN_NAME, tenantId + ":" + loginName, userDTO );
        }

        return userDTO;
    }

    /**
     * 根据登录名获取用户
     *
     * @param loginName
     * @return
     */
    public UserDTO getByLoginNameNotTenantId(String loginName) {
        QueryWrapper queryWrapper = new QueryWrapper ( );
        queryWrapper.eq ( "a.login_name", loginName );
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED );
        UserDTO userDTO = baseMapper.get ( queryWrapper );
        return userDTO;
    }


    /**
     * 自定义分页检索
     *
     * @param page
     * @param queryWrapper
     * @return
     */
    public IPage <UserDTO> findPage(Page <UserDTO> page, QueryWrapper queryWrapper) {
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); // 排除已经删除
        return baseMapper.findList ( page, queryWrapper );


    }

    /**
     * 自定义分页检索
     *
     * @param page
     * @param queryWrapper
     * @return
     */
    public IPage <UserDTO> findMemberPage(Page <UserDTO> page, QueryWrapper queryWrapper) {
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); // 排除已经删除
        if (!SecurityUtils.getCurrentUserDTO ( ).isAdmin ( )){
            //根据当前人的所属公司查该公司下的所有人员信息
            UserDTO userDTO = SpringUtil.getBean(IUserApi.class).getByToken(TokenProvider.getCurrentToken());
            queryWrapper.eq ( "a.company_id", userDTO.getCompanyDTO().getId() );

        }
        return baseMapper.findList ( page, queryWrapper );


    }


    /**
     * 自定义分页检索
     *
     * @param page
     * @param queryWrapper
     * @return
     */
    public IPage <UserDTO> userFindPage(Page <UserDTO> page, QueryWrapper queryWrapper) {
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); // 排除已经删除


        return baseMapper.userFindPage ( page, queryWrapper );

    }


    public IPage <UserDTO> findPage2(Page <UserDTO> page, QueryWrapper queryWrapper) {
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); // 排除已经删除
        return baseMapper.findList2 ( page, queryWrapper );


    }

    /**
     * 查询角色下关联的用户
     *
     * @param page
     * @param queryWrapper
     * @return
     */
    public IPage <UserDTO> findPageByRole(Page <UserDTO> page, QueryWrapper queryWrapper) {
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); //排除已经删除
        return baseMapper.findListByRole ( page, queryWrapper );


    }

    /**
     * 查询角色下关联的用户
     *
     * @param roleId
     * @return
     */
    public List <UserDTO> findListByRoleId(String roleId) {
        QueryWrapper queryWrapper = new QueryWrapper ( );
        queryWrapper.eq ( "a.del_flag", CommonConstants.NOT_DELETED ); //排除已经删除
        queryWrapper.eq ( "r.id", roleId );

        Page <UserDTO> page = new Page <> ( );
        page.setSize ( -1 );
        return baseMapper.findListByRole ( page, queryWrapper ).getRecords ( );
    }

    /**
     * 查询岗位下关联的用户
     *
     * @param postId
     * @return
     */
    public List <UserDTO> findListByPostId(String postId) {
        return baseMapper.findListByPostId ( postId );
    }


    /**
     * 查询岗位下关联的用户
     *
     * @param postId
     * @return
     */
    public List <UserDTO> findListFlowAbleByPostId(String postId) {
        return baseMapper.findListFlowAbleByPostId ( postId );
    }


    /**
     * 保存或者更新用户
     *
     * @param userDTO
     */
    public void saveOrUpdate(UserDTO userDTO) {
        ArrayList<UserDTO> users = new ArrayList<>();
        User user = userWrapper.toEntity ( userDTO );
        if(StringUtils.isNotBlank(userDTO.getManageOfficeIds())){
            user.setManageOfficeIds(userDTO.getManageOfficeIds());
        }
        super.saveOrUpdate ( user );
        // 更新用户与角色关联
        baseMapper.deleteUserRole ( userDTO.getId ( ) );
        if ( userDTO.getRoleDTOList ( ) != null ) {
            userDTO.getRoleDTOList ( ).forEach ( roleDTO -> {
                baseMapper.insertUserRole ( userDTO.getId ( ), roleDTO.getId ( ) );
            } );
        } else {
            throw new RuntimeException ( userDTO.getLoginName ( ) + "没有设置角色！" );
        }
        // 更新用户与岗位联系
        baseMapper.deleteUserPost ( userDTO.getId ( ) );
        if ( userDTO.getPostDTOList ( ) != null ) {
            userDTO.getPostDTOList ( ).forEach ( postDTO -> {
                baseMapper.insertUserPost ( userDTO.getId ( ), postDTO.getId ( ) );
            } );
        }
        UserUtils.deleteCache ( userDTO );
        //判断redis中是否有这个key
        if (redisUtils.hasKey("user:cache:user:all:info")){
            //先清除redis中的数据
            redisUtils.delete(CacheNames.USER_CACHE_USER_ALL_INFO,"user:cache:user:all:info");
            //获取全部的人员信息
            List<UserDTO> allUserInfo = userMapper.getAllUserInfo();
            //再次将人员信息存入到redis中
            redisUtils.set(CacheNames.USER_CACHE_USER_ALL_INFO,"user:cache:user:all:info",allUserInfo);
        }else {
            //获取全部的人员信息
            List<UserDTO> allUserInfo = userMapper.getAllUserInfo();
            //再次将人员信息存入到redis中
            redisUtils.set(CacheNames.USER_CACHE_USER_ALL_INFO,"user:cache:user:all:info",allUserInfo);
        }

    }


    public void deleteUser(UserDTO userDTO) {
        baseMapper.deleteUserRole ( userDTO.getId ( ) );
        baseMapper.deleteUserPost ( userDTO.getId ( ) );
        super.removeById ( userDTO.getId ( ) );
        UserUtils.deleteCache ( userDTO );
    }

    /**
     * 单一登录判断，是否允许登录
     *
     * @return
     */
    public boolean isEnableLogin(String tenantId, String loginName) {
        SysConfig sysConfig = sysConfigService.getById ( "1" );
        if ( sysConfig.getMultiAccountLogin ( ).equals ( CommonConstants.NO ) ) { // 不允许一个账号多个客户端登录
            if ( sysConfig.getSingleLoginType ( ).equals ( "1" ) ) { // 后登陆踢出先登录

                UserUtils.getOnlineUsers ( ).forEach ( userDTO -> {
                    if ( tenantId.equals ( userDTO.getTenantDTO ( ).getId ( ) ) && loginName.equals ( userDTO.getLoginName ( ) ) ) {
                        RedisUtils.getInstance ( ).set ( CacheNames.USER_CACHE_TOKEN, userDTO.getToken ( ), "kickOut" );
                        RedisUtils.getInstance ( ).delete ( CacheNames.USER_CACHE_ONLINE_USERS, userDTO.getToken ( ) );
                    }
                } );

            } else { // 已经登陆禁止再登录
                int size = UserUtils.getOnlineUsers ( ).stream ( ).filter ( userDTO ->
                        tenantId.equals ( userDTO.getTenantDTO ( ).getId ( ) ) && loginName.equals ( userDTO.getLoginName ( ) )
                ).collect ( Collectors.toList ( ) ).size ( );
                if ( size > 0 ) {
                    return false;
                }
                ;
            }
        }
        return true;
    }

    /**
     * 根据部门id获取 部门 以及 子部门 下的所有用户信息
     * @param officeId
     * @return
     */
    public List<User> getUserByOfficeAll(String officeId){
        List<Office> officeList = officeMapper.selectList(new QueryWrapper<Office>().lambda().eq(Office::getParentId, officeId));
        List<String> officeIdList = officeList.stream().distinct().map(Office::getId).collect(Collectors.toList());
        while(true) {
            List<String> ids = new ArrayList<>();
            officeIdList.stream().forEach(item->{
                List<Office> officeList1 = officeMapper.selectList(new QueryWrapper<Office>().lambda().eq(Office::getParentId, item));
                officeList1.stream().forEach(i->{
                    officeList.add(i);
                    ids.add(i.getId());
                });
            });
            if (CollectionUtil.isNotEmpty(ids)) {
                officeIdList = ids;
            } else {
                break;
            }
        }
        List<String> officeIds = officeList.stream().distinct().filter(item -> {
            if (StringUtils.isNotBlank(item.getId())) {
                return true;
            }
            return false;
        }).map(Office::getId).collect(Collectors.toList());
        officeIds.add(officeId);
        return this.list(new QueryWrapper<User>().lambda().in(User::getOfficeId,officeIds));
    }

    /**
     * 根据用户name获取用户id
     * @param name
     * @return
     */
    public String getUserIdByName(String name) {
        return userMapper.getUserIdByName (name);
    }

    //根据部门查询用户信息
    public List<OfficeDTO> getUserByOffice(List<String> officeIds, String type){
        return userMapper.getUserByOffice(officeIds,type);
    }

    /**
     * 修改用户更新密码状态信息
     * @param userDTO
     */
    public void updateUserUpPassword(UserDTO userDTO) {
        baseMapper.updateUserUpPassword (userDTO);
    }

    public List<User> selectListByName(String name) {
        return userMapper.selectListByName(name);
    }

    /**
     * 签字注师查询用户权限所用
     * @param userDTO
     * @return
     */
    public IPage<UserDTO> findPage3(UserDTO userDTO) {
        Page<UserDTO> page = new Page<>();
        List <UserDTO> list1 = baseMapper.findList3(userDTO.getOfficeDTO().getId(),userDTO.getLoginName());
        page.setRecords(list1);
        return page;
    }

    /**
     * 岗位分页检索
     * @param page
     * @param
     * @return
     */
    public IPage <UserDTO> findPage1(UserDTO dto, Page <UserDTO> page) {
        OfficeDTO officeDTO = dto.getCompanyDTO();
        String companyId = "";
        if (null != officeDTO){
            companyId = officeDTO.getId();
        }
        List <UserDTO> list1 = baseMapper.findList1(dto,companyId);
        // 将List<UserDTO>数据设置到Page对象中
        page.setRecords(list1);
        return  page;
    }

    public Boolean isUpdatePassword(String userId) {
        String updatePassword = userMapper.isUpdatePassword(userId);
        if (StringUtils.isNotBlank(updatePassword)) {
            if ("1".equals(updatePassword)) {
                // 密码已经修改过
                return true;
            }
        }
        return false;
    }

    /**
     * 岗位分页检索
     * @param
     * @param
     * @return
     */
    public List<String> findOffId() {
        UserDTO dto = new UserDTO();
        OfficeDTO officeDTO = dto.getCompanyDTO();
        String companyId = "";
        if (null != officeDTO){
            companyId = officeDTO.getId();
        }
        List <UserDTO> list1 = baseMapper.findList1(dto,companyId);
        List<String> list = new ArrayList<>();
        list1.forEach(li->{
            list.add(li.getOfficeDTO().getId());
        });
        list1.forEach(li->{
            list.add(li.getCompanyDTO().getId());
        });
        return  list;
    }

    /**
     * 岗位分页检索
     * @param
     * @param
     * @return
     */
    public List<String> findAllOffId() {
        UserDTO dto = new UserDTO();
        OfficeDTO officeDTO = dto.getCompanyDTO();
        String companyId = "";
        if (null != officeDTO){
            companyId = officeDTO.getId();
        }
        List <UserDTO> list1 = baseMapper.findAllList(dto,companyId);
        List<String> list = new ArrayList<>();
        list1.forEach(li->{
            list.add(li.getOfficeDTO().getId());
        });
        list1.forEach(li->{
            list.add(li.getCompanyDTO().getId());
        });
        return  list;
    }

    /**
     * 获取所有的用户数据
     * @return
     */
    public List<UserDTO> getAllUserInfo() {
        List<UserDTO> allUserInfo = userMapper.getAllUserInfo();
        return allUserInfo;
    }

    /**
     * 查询出拥有权限的用户的部门id
     * @return
     */
    public List<String> hasUser() {
        List<String> hasUser = userMapper.getHasUser();
        List<String> hasUserFather = userMapper.getHasUserFather();
        hasUser.addAll(hasUserFather);
        return hasUser;
    }
}
