package org.dromara.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.config.BoManConfig;
import org.dromara.common.core.enums.UserType;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.domain.staffManage.StaffManage;
import org.dromara.domain.staffManage.bo.StaffManageBo;
import org.dromara.domain.staffManage.vo.StaffManageVo;
import org.dromara.mapper.StaffManageMapper;
import org.dromara.service.IStaffManageService;
import org.dromara.system.domain.SysRole;
import org.dromara.system.domain.SysUser;
import org.dromara.system.domain.SysUserRole;
import org.dromara.system.domain.SysUserTenant;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysRoleVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.SysRoleMapper;
import org.dromara.system.mapper.SysUserMapper;
import org.dromara.system.mapper.SysUserRoleMapper;
import org.dromara.system.mapper.SysUserTenantMapper;
import org.dromara.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import static org.dromara.common.core.constant.Constants.*;

/**
 * 员工管理Service业务层处理
 *
 * @author boman
 * @date 2025-04-10
 */
@RequiredArgsConstructor
@Service
public class StaffManageServiceImpl implements IStaffManageService {

    private final StaffManageMapper baseMapper;
    private final SysUserTenantMapper sysUserTenantMapper;
    private final SysRoleMapper sysRoleMapper;
    private final ISysUserService userService;
    private final SysUserMapper userMapper;
    private final SysUserRoleMapper userRoleMapper;

    /**
     * 查询员工管理
     *
     * @param staffId 主键
     * @return 员工管理
     */
    @Override
    public StaffManageVo queryById(Long staffId) {
        return baseMapper.selectVoById(staffId);
    }

    /**
     * 获取员工管理详细信息 过滤租户
     *
     * @param staffId 主键
     */
    @Override
    public StaffManageVo getAuthenticationInfo(Long staffId) {

        return TenantHelper.ignore(() -> {
            return
                baseMapper.selectVoById(staffId);
        });
    }

    /**
     * 获取员工管理详细信息
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public StaffManageVo getInfoByUserId(Long userId) {
        return baseMapper.getInfoByUserId(userId);
    }

    /**
     * 分页查询员工管理列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 员工管理分页列表
     */
    @Override
    public TableDataInfo<StaffManageVo> queryPageList(StaffManageBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<StaffManage> lqw = buildQueryWrapper(bo);
        Page<StaffManageVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询员工管理需要认证的列表
     */
    @Override
    public TableDataInfo<StaffManageVo> listAuthentication(StaffManageBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<StaffManage> lqw = buildQueryWrapper(bo);
        Page<StaffManageVo> result = TenantHelper.ignore(() -> {
            return
                baseMapper.selectVoPage(pageQuery.build(), lqw);
        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的员工管理列表
     *
     * @param bo 查询条件
     * @return 员工管理列表
     */
    @Override
    public List<StaffManageVo> queryList(StaffManageBo bo) {
        LambdaQueryWrapper<StaffManage> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<StaffManage> buildQueryWrapper(StaffManageBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<StaffManage> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(StaffManage::getStaffId);
        lqw.eq(bo.getUserId() != null, StaffManage::getUserId, bo.getUserId());
        lqw.like(StringUtils.isNotBlank(bo.getStaffName()), StaffManage::getStaffName, bo.getStaffName());
        lqw.eq(StringUtils.isNotBlank(bo.getGender()), StaffManage::getGender, bo.getGender());
        lqw.eq(StringUtils.isNotBlank(bo.getStaffCategory()), StaffManage::getStaffCategory, bo.getStaffCategory());
        lqw.eq(StringUtils.isNotBlank(bo.getMaintenanceCategory()), StaffManage::getMaintenanceCategory, bo.getMaintenanceCategory());
        lqw.eq(StringUtils.isNotBlank(bo.getPhoneNumber()), StaffManage::getPhoneNumber, bo.getPhoneNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getAvatarPhoto()), StaffManage::getAvatarPhoto, bo.getAvatarPhoto());
        lqw.eq(StringUtils.isNotBlank(bo.getIdCard()), StaffManage::getIdCard, bo.getIdCard());
        lqw.eq(StringUtils.isNotBlank(bo.getIdCardFront()), StaffManage::getIdCardFront, bo.getIdCardFront());
        lqw.eq(StringUtils.isNotBlank(bo.getIdCardBack()), StaffManage::getIdCardBack, bo.getIdCardBack());
        lqw.eq(StringUtils.isNotBlank(bo.getCertificate()), StaffManage::getCertificate, bo.getCertificate());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), StaffManage::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getExamine()), StaffManage::getExamine, bo.getExamine());
        return lqw;
    }

    /**
     * 新增员工管理
     *
     * @param bo 员工管理
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(StaffManageBo bo) {
        StaffManage add = MapstructUtils.convert(bo, StaffManage.class);
        boolean flag = checkPhoneNumberUnique(add);
        if (!flag) {
            throw new UserException("staff.manage.error");
        } else if (flag) {
            validEntityBeforeSave(add);
            flag = baseMapper.insert(add) > 0;
/*
            SysUserBo sysUser = new SysUserBo();
            sysUser.setUserId(bo.getUserId());
            //把租户id更新到sys_user表/sys_user_tenant表中
            sysUser.setIsAuthentication(Y);
            userService.updateUserByIdNoTenantId(sysUser);
            if (flag) {
                bo.setStaffId(add.getStaffId());
            }*/
        }
/*        //往redis中插入需要认证的记录数据，给getUserInfo接口判断是否需要认证使用
        String key = STAFF_MANAGE_AUTHENTICATION + bo.getUserId();
        Object cacheObject = RedisUtils.getCacheObject(key);
        int count = 0;
        if (cacheObject != null) {
            count = Integer.parseInt(cacheObject.toString()) + 1;
            RedisUtils.setCacheObject(key, count);
        } else {
            RedisUtils.setCacheObject(key, 1);
        }*/
        return flag;
    }

    /**
     * 管理员新增员工信息默认认证
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertAuthenticationByBo(StaffManageBo bo) {
        StaffManage staffManage = MapstructUtils.convert(bo, StaffManage.class);
        //判断是否重复
        boolean flag = checkPhoneNumberUnique(staffManage);
        if (!flag) {
            throw new UserException("staff.manage.error");
        } else if (flag) {
            SysUserBo user = new SysUserBo();
            String tenantId = staffManage.getTenantId();;
            //手机号、手机验证码注册
            String username = staffManage.getPhoneNumber();
            String password = BoManConfig.getPasswordDeft();
            // 校验用户类型是否存在
            String userType = UserType.getUserType(staffManage.getUserType()).getUserType();

            user.setUserName(username);
            user.setNickName(username);
            user.setPassword(BCrypt.hashpw(password));
            user.setUserType(userType);
            user.setPhonenumber(username);
            user.setIsAuthentication(Y);
            boolean exist = TenantHelper.ignore(() -> {
                return
                    userMapper.exists(new LambdaQueryWrapper<SysUser>()
                        .eq(SysUser::getUserName, user.getUserName()));
            });
            SysUser sysUser = MapstructUtils.convert(user, SysUser.class);
            sysUser.setTenantId(tenantId);
            Long userId;
            if (!exist) {
                //sysUser新增
                user.setCreateBy(0L);
                user.setUpdateBy(0L);
                TenantHelper.ignore(() -> {
                    userMapper.insert(sysUser);
                });
                userId = sysUser.getUserId();
            } else {
                //从sysUser表中查询
                SysUserVo sysUserVo = TenantHelper.ignore(() -> {
                    return userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, username));
                });
                userId = sysUserVo.getUserId();
            }
            staffManage.setExamine(TWO);
            staffManage.setUserId(userId);
            user.setUserId(userId);
            user.setTenantId(tenantId);
            flag = baseMapper.insert(staffManage) > 0;
/*            if (flag) {
                bo.setStaffId(staffManage.getStaffId());
            }*/
            //sys_user_tenant表中
            SysUserTenant sysUserTenant = new SysUserTenant();
            sysUserTenant.setUserId(userId);
            sysUserTenant.setTenantId(staffManage.getTenantId());
            sysUserTenantMapper.insert(sysUserTenant);

            //给该userId赋予角色
            // 新增用户与角色管理
            //根据权限字符去查询角色id

            SysRoleVo sysRoleVo = TenantHelper.ignore(() -> {
                return sysRoleMapper.selectVoOne(new LambdaQueryWrapper<SysRole>()
                    .eq(SysRole::getRoleKey, staffManage.getStaffCategory())
                    .eq(SysRole::getTenantId, staffManage.getTenantId()));
            });
            if (sysRoleVo != null) {
                Long[] longArray = new Long[1];
                longArray[0] = sysRoleVo.getRoleId();
                user.setRoleIds(longArray);
            }
            userService.insertUserRole(user, false);
        }
        return flag;
    }

    /**
     * 修改员工管理
     *
     * @param bo 员工管理
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(StaffManageBo bo) {
        StaffManage update = MapstructUtils.convert(bo, StaffManage.class);
        if (bo.getIsFilter()) {
            return TenantHelper.ignore(() -> {
                return baseMapper.updateById(update) > 0;
            });
        } else {
            validEntityBeforeSave(update);
            return baseMapper.updateById(update) > 0;
        }
    }

    /**
     * 管理员修改员工管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editAuthentication(StaffManageBo bo) {
        StaffManage examineStaffManage = MapstructUtils.convert(bo, StaffManage.class);
        //判断是否修改了租户
        StaffManageVo staffManageVo = baseMapper.selectVoById(bo.getStaffId());
        //原始的tenantId
        String tenantIdOld = staffManageVo.getTenantId();
        Long userId = examineStaffManage.getUserId();
        SysUserBo sysUser = new SysUserBo();
        sysUser.setUserId(bo.getUserId());
        if (TenantHelper.isEnable()) {
            //把租户id更新到sys_user表/sys_user_tenant表中
            String tenantIdNew = examineStaffManage.getTenantId();
            sysUser.setTenantId(tenantIdNew);
            //如过两个租户id不一致，更新sys_user_tenant表
            if (!tenantIdOld.equals(tenantIdNew)) {
                sysUserTenantMapper.update(new LambdaUpdateWrapper<SysUserTenant>()
                    .set(SysUserTenant::getTenantId, tenantIdNew)
                    .eq(SysUserTenant::getUserId, userId).eq(SysUserTenant::getTenantId, tenantIdOld));

                //组装sysUser
                //给该userId赋予角色
                // 新增用户与角色管理
                //根据权限字符去查询角色id
                SysRoleVo sysRoleVo = TenantHelper.ignore(() -> {
                    return sysRoleMapper.selectVoOne(new LambdaQueryWrapper<SysRole>()
                        .eq(SysRole::getRoleKey, examineStaffManage.getStaffCategory())
                        .eq(SysRole::getTenantId, examineStaffManage.getTenantId()));
                });
                if (sysRoleVo != null) {
                    Long[] longArray = new Long[1];
                    longArray[0] = sysRoleVo.getRoleId();
                    sysUser.setRoleIds(longArray);
                }
                userService.insertUserRole(sysUser, true);
            }
        }
        sysUser.setPhonenumber(examineStaffManage.getPhoneNumber());
        userService.updateUserByIdNoTenantId(sysUser);
        return baseMapper.updateById(examineStaffManage) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(StaffManage entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除员工管理信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }


    /**
     * 员工申请审核
     *
     * @param bo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean examineStaff(StaffManageBo bo) {
        StaffManage examineStaffManage = MapstructUtils.convert(bo, StaffManage.class);
        //判断是否审核通过
        if (TWO.equals(examineStaffManage.getExamine())) {
            SysUserBo sysUser = new SysUserBo();
            sysUser.setUserId(bo.getUserId());
            if (TenantHelper.isEnable()) {
                //把租户id更新到sys_user表/sys_user_tenant表中
                sysUser.setTenantId(examineStaffManage.getTenantId());
                sysUser.setIsAuthentication(Y);
                userService.updateUserByIdNoTenantId(sysUser);
                SysUserTenant sysUserTenant = new SysUserTenant();
                sysUserTenant.setUserId(examineStaffManage.getUserId());
                sysUserTenant.setTenantId(examineStaffManage.getTenantId());
                sysUserTenantMapper.insert(sysUserTenant);
            }
            //组装sysUser
            //给该userId赋予角色
            // 新增用户与角色管理
            //根据权限字符去查询角色id
            SysRoleVo sysRoleVo = sysRoleMapper.selectVoOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleKey, examineStaffManage.getStaffCategory()));
            if (sysRoleVo != null) {
                Long[] longArray = new Long[1];
                longArray[0] = sysRoleVo.getRoleId();
                sysUser.setRoleIds(longArray);
            }
            userService.insertUserRole(sysUser, false);

/*            //往redis中插入需要认证的记录数据，给getUserInfo接口判断是否需要认证使用
            String key = STAFF_MANAGE_AUTHENTICATION + bo.getUserId();
            Object cacheObject = RedisUtils.getCacheObject(key);
            int count = 0;
            if (cacheObject != null) {
                count = Integer.parseInt(cacheObject.toString()) - 1;
                if (count > 0) {
                    RedisUtils.setCacheObject(key,count);
                }else {
                    RedisUtils.deleteObject(key);
                }
            }*/
        }
        return baseMapper.updateById(examineStaffManage) > 0;
    }

    /**
     * 删除员工信息和用户信息和权限
     *
     * @param bo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteStaffManage(StaffManageBo bo) {
        Long userId = bo.getUserId();
        Long staffId = bo.getStaffId();
        String tenantId = bo.getTenantId();
        boolean flag = baseMapper.deleteById(staffId) > 0;
        // userMapper.deleteById(userId);
        if (TenantHelper.isEnable()) {
            List<StaffManage> staffManageList = TenantHelper.ignore(() -> {
                return baseMapper.selectList(new LambdaQueryWrapper<StaffManage>().eq(StaffManage::getUserId, userId));
            });
            //查询该用户是否一个认证信息 通过的 都没有则需要把用户租户重置为000000，认证状态改为未认证
            SysUser sysUser = new SysUser();
            sysUser.setUserId(userId);
            if (staffManageList == null) {
                sysUser.setTenantId(TENANT_ID);
                sysUser.setIsAuthentication(N);
                TenantHelper.ignore(() -> {
                    userMapper.updateById(sysUser);
                });
            }
            // 删除用户与角色关联
            TenantHelper.ignore(() -> {
                userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId).eq(SysUserRole::getTenantId, tenantId));
            });
            // 删除用户与租户关联
            TenantHelper.ignore(() -> {
                sysUserTenantMapper.delete(new LambdaQueryWrapper<SysUserTenant>().eq(SysUserTenant::getUserId, userId).eq(SysUserTenant::getTenantId, tenantId));
            });
            if (staffManageList != null && staffManageList.size() > 0) {
                //判断用户的默认租户是否是被删除的那个租户，是的情况下换一个租户id给sysUser表中
                SysUserVo sysUserVo = TenantHelper.ignore(() -> {
                    return
                        userMapper.selectVoById(userId);
                });
                String tenantIdOld = sysUserVo.getTenantId();
                if (tenantId.equals(tenantIdOld)) {
                    SysUserTenant sysUserTenant = sysUserTenantMapper.selectVoOne(new LambdaQueryWrapper<SysUserTenant>().eq(SysUserTenant::getUserId, userId));
                    sysUser.setTenantId(TENANT_ID);
                    if (sysUserTenant != null) {
                        sysUser.setTenantId(sysUserTenant.getTenantId());
                    }

                }

                long count = staffManageList.stream().filter(e -> e.getExamine().equals(TWO)).count();
                if (count == 0) {
                    sysUser.setTenantId(TENANT_ID);
                    sysUser.setIsAuthentication(N);
                    TenantHelper.ignore(() -> {
                        userMapper.updateById(sysUser);
                    });
                }
            }
        } else {
            userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        }
/*        //往redis中插入需要认证的记录数据，给getUserInfo接口判断是否需要认证使用
        String key = STAFF_MANAGE_AUTHENTICATION + userId;
        Object cacheObject = RedisUtils.getCacheObject(key);
        int count = 0;
        if (cacheObject != null) {
            count = Integer.parseInt(cacheObject.toString()) - 1;
            if (count > 0) {
                RedisUtils.setCacheObject(key,count);
            }else {
                RedisUtils.deleteObject(key);
            }
        }*/
        return flag;
    }


    /**
     * 校验手机号码是否唯一
     *
     * @param add 员工信息
     * @return 结果
     */

    public boolean checkPhoneNumberUnique(StaffManage add) {
        boolean exit = TenantHelper.ignore(() -> {
            return
                baseMapper.exists(new LambdaQueryWrapper<StaffManage>()
                    .eq(StaffManage::getPhoneNumber, add.getPhoneNumber())
                    .eq(StaffManage::getTenantId, add.getTenantId())
                    .ne(ObjectUtil.isNotNull(add.getStaffId()), StaffManage::getStaffId, add.getStaffId()));
        });
        return !exit;
    }
}
