package com.ruoyi.user.service.impl;

import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.clock.domain.Employee;
import com.ruoyi.clock.domain.vo.EmployeeVo;
import com.ruoyi.clock.service.IEmployeeService;
import com.ruoyi.common.constant.Constants;

import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.user.UserException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.user.domain.UserThirdIdentity;
import com.ruoyi.user.domain.bo.UserThirdIdentityBo;
import com.ruoyi.user.mapper.UserThirdIdentityMapper;
import com.ruoyi.user.service.IUserThirdIdentityService;
import com.ruoyi.weixin.domain.WxEmployeeDto;
import com.ruoyi.weixin.domain.WxUserDto;
import com.ruoyi.weixin.service.WxMsgService;
import com.ruoyi.weixin.service.WxUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.user.domain.bo.UserBo;
import com.ruoyi.user.domain.vo.UserVo;
import com.ruoyi.user.domain.User;
import com.ruoyi.user.mapper.UserMapper;
import com.ruoyi.user.service.IUserService;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
 * 小程序用户管理Service业务层处理
 *
 * @author wuchao
 * @date 2022-03-03
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class UserServiceImpl implements IUserService {

    private final UserMapper baseMapper;

    private final WxUserService wxUserService;

    private final IEmployeeService employeeService;

    private final UserThirdIdentityMapper userThirdIdentityMapper;

    /**
     * 查询小程序用户管理
     *
     * @param id 小程序用户管理主键
     * @return 小程序用户管理
     */
    @Override
    public UserVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询小程序用户管理列表
     *
     * @param bo 小程序用户管理
     * @return 小程序用户管理
     */
    @Override
    public TableDataInfo<UserVo> queryPageList(UserBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<User> lqw = buildQueryWrapper(bo);
        Page<UserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询小程序用户管理列表
     *
     * @param bo 小程序用户管理
     * @return 小程序用户管理
     */
    @Override
    public List<UserVo> queryList(UserBo bo) {
        LambdaQueryWrapper<User> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<User> buildQueryWrapper(UserBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<User> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getMobile()), User::getMobile, bo.getMobile());
        lqw.like(StringUtils.isNotBlank(bo.getNickname()), User::getNickname, bo.getNickname());
        lqw.eq(StringUtils.isNotBlank(bo.getHeadPhoto()), User::getHeadPhoto, bo.getHeadPhoto());
        lqw.eq(bo.getAge() != null, User::getAge, bo.getAge());
        lqw.eq(bo.getGender() != null, User::getGender, bo.getGender());
        lqw.like(StringUtils.isNotBlank(bo.getRealName()), User::getRealName, bo.getRealName());
        lqw.eq(StringUtils.isNotBlank(bo.getBirthday()), User::getBirthday, bo.getBirthday());
        lqw.eq(bo.getStatus() != null, User::getStatus, bo.getStatus());
        lqw.eq(bo.getLastLoginTime() != null, User::getLastLoginTime, bo.getLastLoginTime());
        return lqw;
    }

    /**
     * 新增小程序用户管理
     *
     * @param bo 小程序用户管理
     * @return 结果
     */
    @Override
    public Boolean insertByBo(UserBo bo) {
        User add = BeanUtil.toBean(bo, User.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改小程序用户管理
     *
     * @param bo 小程序用户管理
     * @return 结果
     */
    @Override
    public Boolean updateByBo(UserBo bo) {
        User update = BeanUtil.toBean(bo, User.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(User entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除小程序用户管理
     *
     * @param ids 需要删除的小程序用户管理主键
     * @return 结果
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User authorization(WxUserDto wxUserDto) {
        //获取openId
        String openId = wxUserService.getOpenIdByCode(wxUserDto.getCode());

        //查询此openid是否绑定过用户
        UserThirdIdentity userThirdIdentity = userThirdIdentityMapper.selectOne(
            new LambdaQueryWrapper<UserThirdIdentity>()
                .eq(UserThirdIdentity::getThirdType, 0)
                .eq(UserThirdIdentity::getIdentityCode, openId)
                .last("limit 1")
        );

        User user;
        //该用户未绑定过，则创建
        if (ObjectUtil.isNull(userThirdIdentity)) {
            //创建用户
            user = new User();
            user.setNickname(wxUserDto.getNickname());
            user.setHeadPhoto(wxUserDto.getHeadPhoto());
            user.setAge(wxUserDto.getAge());
            user.setGender(wxUserDto.getGender());//info.getGender()
            user.setRealName(wxUserDto.getRealName());
            user.setBirthday(wxUserDto.getBirthday());
            user.setStatus(true);
            //保存用户信息
            this.baseMapper.insert(user);

            //保存第三方关系
            userThirdIdentity = new UserThirdIdentity();
            userThirdIdentity.setUserId(user.getId());
            userThirdIdentity.setThirdType(0);
            userThirdIdentity.setIdentityCode(openId);
            userThirdIdentityMapper.insert(userThirdIdentity);
        } else {
            user = this.getById(userThirdIdentity.getUserId(), true);
        }

//        //TODO 自定义用户
//        User user = this.baseMapper.selectById(1L);
//        if (ObjectUtil.isNull(user)) {
//            user = new User();
//            user.setMobile("10086");
//            user.setNickname("老师");
//            user.setHeadPhoto("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic%2Fe8%2F34%2F02%2Fe834028fa4b313a1607872736437ef2d.jpg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1648636830&t=5c4d53742351fbed90487a5b34e60058");
//            user.setAge(18);
//            user.setGender(0);//info.getGender()
//            user.setRealName("");
//            user.setBirthday("");
//            user.setStatus(true);
//            //保存用户信息
//            this.baseMapper.insert(user);
//
//            //保存用户的第三方身份
//            UserThirdIdentityBo userThirdIdentity = new UserThirdIdentityBo();
//            userThirdIdentity.setUserId(user.getId());
//            userThirdIdentity.setThirdType(0);
//            userThirdIdentity.setIdentityCode("openId");
//            userThirdIdentityService.insertByBo(userThirdIdentity);
//        }else {
//            //更新用户信息
//            this.baseMapper.updateById(user);
//        }

        return user;
    }


    @Override
    public User getById(Long userId, boolean isThrow) {
        User obj = this.baseMapper.selectById(userId);
        if (ObjectUtil.isNull(obj)) {
            if (isThrow) {
                throw new ServiceException("用户不存在");
            }
        }
        return obj;
    }

    @Override
    public Employee login(WxEmployeeDto wxEmployeeDto) {
        String username = wxEmployeeDto.getUsername();
        String password = wxEmployeeDto.getPassword();
        Employee user = loadUserByUsername(username);
        Integer errorNumber = RedisUtils.getCacheObject(Constants.LOGIN_ERROR + username);
        if (!BCrypt.checkpw(password, user.getPassword())) {
            // 是否第一次
            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
            // 达到规定错误次数 则锁定登录
            if (errorNumber.equals(Constants.LOGIN_ERROR_NUMBER)) {
                RedisUtils.setCacheObject(Constants.LOGIN_ERROR + username, errorNumber, Constants.LOGIN_ERROR_LIMIT_TIME, TimeUnit.MINUTES);
                throw new UserException("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME);
            } else {
                // 未达到规定错误次数 则递增
                RedisUtils.setCacheObject(Constants.LOGIN_ERROR + username, errorNumber);
                throw new UserException("user.password.retry.limit.count", errorNumber);
            }
        }
        return user;
    }

    private Employee loadUserByUsername(String username) {
        Employee user = employeeService.selectUserByUserName(username);
        if (ObjectUtil.isNull(user)) {
            log.info("登录用户：{} 不存在.", username);
            throw new UserException("user.not.exists", username);
        } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            log.info("登录用户：{} 已被删除.", username);
            throw new UserException("user.password.delete", username);
        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            log.info("登录用户：{} 已被停用.", username);
            throw new UserException("user.blocked", username);
        }
        return user;
    }
}
