package top.continew.admin.system.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import top.continew.admin.common.config.mybatis.DataPermissionMapper;
import top.continew.admin.system.model.entity.UserDO;
import top.continew.admin.system.model.resp.UserDetailResp;
import top.continew.admin.system.model.resp.UserTreeResp;
import top.continew.starter.data.mp.datapermission.DataPermission;
import top.continew.starter.security.crypto.annotation.FieldEncrypt;

import java.util.List;

/**
 * 用户 Mapper
 *
 * @author Charles7c
 * @since 2022/12/22 21:47
 */
public interface UserMapper extends DataPermissionMapper<UserDO> {

    /**
     * 分页查询列表
     *
     * @param page         分页条件
     * @param queryWrapper 查询条件
     * @return 分页列表信息
     */
    @DataPermission(tableAlias = "t1")
    IPage<UserDetailResp> selectUserPage(@Param("page") IPage<UserDO> page,
                                         @Param(Constants.WRAPPER) QueryWrapper<UserDO> queryWrapper);

    /**
     * 查询列表
     *
     * @param queryWrapper 查询条件
     * @return 列表信息
     */
    @DataPermission(tableAlias = "t1")
    List<UserDetailResp> selectUserList(@Param(Constants.WRAPPER) QueryWrapper<UserDO> queryWrapper);

    /**
     * 根据用户名查询
     *
     * @param username 用户名
     * @return 用户信息
     */
    @Select("SELECT * FROM sys_user WHERE username = #{username}")
    UserDO selectByUsername(@Param("username") String username);

    /**
     * 根据手机号查询
     *
     * @param phone 手机号
     * @return 用户信息
     */
    @Select("SELECT * FROM sys_user WHERE phone = #{phone}")
    UserDO selectByPhone(@FieldEncrypt @Param("phone") String phone);

    /**
     * 根据邮箱查询
     *
     * @param email 邮箱
     * @return 用户信息
     */
    @Select("SELECT * FROM sys_user WHERE email = #{email}")
    UserDO selectByEmail(@FieldEncrypt @Param("email") String email);

    /**
     * 根据 ID 查询昵称
     *
     * @param id ID
     * @return 昵称
     */
    @Select("SELECT nickname FROM sys_user WHERE id = #{id}")
    String selectNicknameById(@Param("id") Long id);

    /**
     * 根据邮箱查询数量
     *
     * @param email 邮箱
     * @return 用户数量
     */
    Long selectCountByEmail(@FieldEncrypt @Param("email") String email, @Param("id") Long id);

    /**
     * 根据手机号查询数量
     *
     * @param phone 手机号
     * @return 用户数量
     */
    Long selectCountByPhone(@FieldEncrypt @Param("phone") String phone, @Param("id") Long id);

    List<UserTreeResp> selectTeacherById(@FieldEncrypt @Param("deptId") Long deptId);

    /**
     * 扣减消费余额
     *
     * @param id ID
     */
    @Update("update sys_user set sys_beans = sys_beans - #{chargePoints} WHERE id = #{id}")
    int updateSysBeansById(@Param("id") Long id, @Param("chargePoints") Long chargePoints);

    /**
     * 增加预扣减金额（任务开始前）
     *
     * @param id              ID
     * @param preDeductAmount 预扣减金额
     */
    @Update("update sys_user set pre_deduct_beans = pre_deduct_beans + #{preDeductAmount} WHERE id = #{id}")
    int addPreDeductBeansById(@Param("id") Long id, @Param("preDeductAmount") Long preDeductAmount);

    /**
     * 减少预扣减金额并扣减实际余额（任务完成后）
     *
     * @param id              ID
     * @param preDeductAmount 预扣减金额（分）
     * @param actualAmount    实际扣减金额（分）
     */
    @Update("update sys_user set pre_deduct_beans = pre_deduct_beans - #{preDeductAmount}, sys_beans = sys_beans - #{actualAmount} WHERE id = #{id}")
    int deductActualAndClearPreDeduct(@Param("id") Long id,
                                      @Param("preDeductAmount") Long preDeductAmount,
                                      @Param("actualAmount") Long actualAmount);

    /**
     * 清零预扣减金额（任务失败或取消时）
     *
     * @param id              ID
     * @param preDeductAmount 预扣减金额（分）
     */
    @Update("update sys_user set pre_deduct_beans = pre_deduct_beans - #{preDeductAmount} WHERE id = #{id}")
    int clearPreDeductBeansById(@Param("id") Long id, @Param("preDeductAmount") Long preDeductAmount);
}
