package com.seer.teach.user.admin.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.seer.teach.common.PageListBean;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.CommonUtils;
import com.seer.teach.common.utils.PageConverterUtils;
import com.seer.teach.user.admin.convert.AdminUserConvert;
import com.seer.teach.user.admin.request.*;
import com.seer.teach.user.admin.response.AdminUserPageResp;
import com.seer.teach.user.admin.service.AdminUserService;
import com.seer.teach.user.entity.RoleEntity;
import com.seer.teach.user.entity.UserEntity;
import com.seer.teach.user.entity.UserRoleEntity;
import com.seer.teach.user.service.IRoleService;
import com.seer.teach.user.service.IUserRoleService;
import com.seer.teach.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Captain
 * @since 2025-05-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdminUserServiceImpl implements AdminUserService {

    private final IUserService userService;

    private final IUserRoleService userRoleService;

    private final IRoleService roleService;

    /**
     * 后台登录接口
     *
     * @param params
     * @return
     */
    @Override
    public HashMap<String, Object> login(AdminUserLoginReq params) {
        UserEntity one = userService.getOneByUserName(params.getUsername());
        AssertUtils.notNull(one, ResultCodeEnum.USER_NOT_FOUND);
        if(one.getStatus() != 1){
            throw new CommonException(ResultCodeEnum.USER_IS_DISABLED);
        }
        String password = CommonUtils.encryptPassword(params.getPassword());
        //校验密码
        if (password != null && password.equals(one.getPassword())) {
            StpUtil.login(one.getId());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            AssertUtils.notNull(tokenInfo, ResultCodeEnum.EXPIRED_TOKEN);
            HashMap<String, Object> result = new HashMap<>();
            result.put("tokenName", tokenInfo.getTokenName());
            result.put("tokenValue", tokenInfo.getTokenValue());
            return result;
        }
        throw new CommonException(ResultCodeEnum.USERNAME_OR_PASSWORD_IS_ERROR);
    }

    /**
     * 添加管理员
     *
     * @param adminUserReq
     * @return
     */
    @Override
    public void register(RegisterAdminReq adminUserReq) {
        UserEntity one = userService.getOneByUserName(adminUserReq.getUserName());
        AssertUtils.isNull(one,ResultCodeEnum.USERNAME_IS_EXIST);

        UserEntity adminUserEntity = AdminUserConvert.INSTANCE.convertOne(adminUserReq);
        adminUserEntity.setPassword(CommonUtils.encryptPassword(adminUserReq.getPassword()));
        boolean saved = userService.save(adminUserEntity);
        log.info("添加用户[{}]结果[{}]",adminUserEntity.getUserName(), saved);
    }

    /**
     * 分页查询管理员列表
     *
     * @param page
     * @param size
     * @return
     */
    @Override
    public PageListBean<AdminUserPageResp> listPage(Integer page, Integer size, String keyword) {
        Page<UserEntity> pageObj = new Page<>(page, size);
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(UserEntity::getId);
        if (StringUtils.isNotBlank(keyword)) {
            wrapper.likeRight(UserEntity::getUserName, keyword)
                    .or()
                    .likeRight(UserEntity::getMobile, keyword)
                    .or()
                    .likeRight(UserEntity::getNickName, keyword)
                    .or()
                    .likeRight(UserEntity::getRealName, keyword)
                    .or()
                    .likeRight(UserEntity::getEmail, keyword);
        }
        Page<UserEntity> resultPage = userService.page(pageObj, wrapper);

        return PageConverterUtils.convertPageListBean(resultPage, AdminUserConvert.INSTANCE::toPageRespList);
    }

    /**
     * 修改管理员信息
     *
     * @param params
     * @param id
     */
    @Override
    public void updateAdminById(AdminUpdateReq params, Integer id) {
        UserEntity one = userService.getOne(new LambdaQueryWrapper<UserEntity>()
                .eq(UserEntity::getUserName, params.getUserName())
                .ne(UserEntity::getId,id)
        );
        AssertUtils.isNull(one,ResultCodeEnum.USERNAME_IS_EXIST);
        UserEntity adminUserEntity = userService.getById(id);
        AssertUtils.notNull(adminUserEntity,ResultCodeEnum.USER_NOT_FOUND);

        UserEntity userEntity = AdminUserConvert.INSTANCE.convertOne(params);
        userEntity.setId(id);
        userService.updateById(userEntity);
    }

    /**
     * 修改管理员状态
     * @param id
     * @param status
     */
    @Override
    public void updateStatus(Integer id,Integer status) {
        UserEntity adminUserEntity = userService.getById(id);
        adminUserEntity.setStatus(status);
        userService.updateById(adminUserEntity);
    }

    @Override
    public boolean resetPassword(AdminUpdateReq params, Integer id) {
        UserEntity adminUserEntity = userService.getById(id);
        AssertUtils.notNull(adminUserEntity,ResultCodeEnum.USER_NOT_FOUND);

        UserEntity userEntity = new UserEntity();
        userEntity.setPassword(CommonUtils.encryptPassword(params.getPassword()));
        userEntity.setId(id);
        boolean updated = userService.updateById(userEntity);
        log.info("用户[{}]重置密码结果[{}]",id, updated);
        return updated;
    }

    /**
     * 登出接口
     */
    @Override
    public void logout() {
        StpUtil.logout();
    }

    @Override
    public boolean removeById(Integer id) {
        return userService.removeById( id);
    }

    @Override
    public PageListBean<AdminUserPageResp> list(AdminUserSearchReq searchReq) {
        Set<Integer> roleIds = new HashSet<>();
        if(CollectionUtil.isNotEmpty(searchReq.getRoleIds())){
            roleIds.addAll(searchReq.getRoleIds());
        }
        if(Objects.nonNull(searchReq.getRoleId())){
            roleIds.add(searchReq.getRoleId());
        }
        Set<Integer> userIds = new HashSet<>();
        if(CollectionUtil.isNotEmpty(roleIds)){
            List<UserRoleEntity> userRoleEntities = userRoleService.list(new LambdaQueryWrapper<>(UserRoleEntity.class).in(UserRoleEntity::getRoleId, roleIds));
            if(CollectionUtil.isNotEmpty(userRoleEntities)){
                userIds.addAll(userRoleEntities.stream().map(UserRoleEntity::getUserId).collect(Collectors.toSet()));
            }
        }
        if(CollectionUtil.isNotEmpty(searchReq.getUserIds())){
            userIds.addAll(searchReq.getUserIds());
        }
        Page<UserEntity> page = new Page<>(searchReq.getPageNo(), searchReq.getPageSize());
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        if(CollectionUtil.isNotEmpty(userIds)){
            wrapper.in(UserEntity::getId, userIds);
        }
        if(StringUtils.isNotBlank(searchReq.getUsername())){
            wrapper.likeRight(UserEntity::getUserName, searchReq.getUsername());
        }
        if(StringUtils.isNotBlank(searchReq.getKeyword())){
            wrapper.and(wp -> wp
                    .likeRight(UserEntity::getUserName, searchReq.getKeyword())
                    .or()
                    .likeRight(UserEntity::getMobile, searchReq.getKeyword())
                    .or()
                    .likeRight(UserEntity::getNickName, searchReq.getKeyword())
                    .or()
                    .likeRight(UserEntity::getRealName, searchReq.getKeyword())
                    .or()
                    .likeRight(UserEntity::getEmail, searchReq.getKeyword()));
        }
        Page<UserEntity> resultPage = userService.page(page, wrapper);
        return PageConverterUtils.convertPageListBean(resultPage, AdminUserConvert.INSTANCE::toPageRespList);
    }

    @Override
    public PageListBean<AdminUserPageResp> listByRole(Integer pageNo, Integer size, String roleCode) {
        Optional<RoleEntity> role = roleService.getRoleByCode(roleCode);
        if (!role.isPresent()){
            return new PageListBean<>();
        }
        List<UserRoleEntity> userRoles = userRoleService.list(new LambdaQueryWrapper<>(UserRoleEntity.class).eq(UserRoleEntity::getRoleId, role.get().getId()));
        if(CollectionUtil.isEmpty(userRoles)){
            return new PageListBean<>();
        }
        List<Integer> userIds = userRoles.stream().map(UserRoleEntity::getUserId).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(userIds)){
            return new PageListBean<>();
        }
        Page<UserEntity> page = new Page<>(pageNo, size);
        Page<UserEntity> resultPage = userService.page(page, new LambdaQueryWrapper<>(UserEntity.class).in(UserEntity::getId, userIds));
        return PageConverterUtils.convertPageListBean(resultPage, AdminUserConvert.INSTANCE::toPageRespList);
    }

    @Override
    public PageListBean<AdminUserPageResp> getUserListByRoleId(AdminUserSearchReq searchReq) {
        List<UserRoleEntity> userRoles = userRoleService.list(new LambdaQueryWrapper<>(UserRoleEntity.class).eq(UserRoleEntity::getRoleId, searchReq.getRoleId()));
        if(CollectionUtil.isEmpty(userRoles)){
            return new PageListBean<>();
        }
        List<Integer> userIds = userRoles.stream().map(UserRoleEntity::getUserId).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(userIds)){
            return new PageListBean<>();
        }
        Page<UserEntity> page = new Page<>(searchReq.getPageNo(), searchReq.getPageSize());
        Page<UserEntity> resultPage = userService.page(page, new LambdaQueryWrapper<>(UserEntity.class).in(UserEntity::getId, userIds));
        return PageConverterUtils.convertPageListBean(resultPage, AdminUserConvert.INSTANCE::toPageRespList);
    }
}