package com.zanxiang.game.module.sdk.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.game.module.base.pojo.enums.HttpStatusEnum;
import com.zanxiang.game.module.mybatis.entity.GameExt;
import com.zanxiang.game.module.mybatis.entity.User;
import com.zanxiang.game.module.mybatis.entity.UserCard;
import com.zanxiang.game.module.mybatis.mapper.UserMapper;
import com.zanxiang.game.module.sdk.enums.SmsTypeEnum;
import com.zanxiang.game.module.sdk.pojo.dto.UserDTO;
import com.zanxiang.game.module.sdk.pojo.param.BindPhoneParam;
import com.zanxiang.game.module.sdk.pojo.param.FindPasswordParam;
import com.zanxiang.game.module.sdk.pojo.param.UpdatePasswordParam;
import com.zanxiang.game.module.sdk.pojo.param.UserData;
import com.zanxiang.game.module.sdk.pojo.vo.CustomerVO;
import com.zanxiang.game.module.sdk.pojo.vo.UserVO;
import com.zanxiang.game.module.sdk.service.IGameExtService;
import com.zanxiang.game.module.sdk.service.ISmsService;
import com.zanxiang.game.module.sdk.service.IUserCardService;
import com.zanxiang.game.module.sdk.service.IUserService;
import com.zanxiang.game.module.sdk.util.RegisterUtil;
import com.zanxiang.module.util.JsonUtil;
import com.zanxiang.module.util.bean.BeanUtil;
import com.zanxiang.module.util.exception.BaseException;
import com.zanxiang.module.util.pojo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @author : lingfeng
 * @time : 2022-06-07
 * @description : 用户信息
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private IGameExtService gameExtService;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private IUserCardService userCardService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVO<Boolean> findPassword(FindPasswordParam param, UserData userData) {
        String userName = param.getUserName();
        String mobile = param.getMobile();
        String code = param.getCode();
        String newPassword = param.getNewPassword();
        //查询用户信息
        User user;
        if (Strings.isNotBlank(userName)) {
            user = super.getOne(new LambdaQueryWrapper<User>()
                    .eq(User::getGameId, userData.getGameId())
                    .eq(User::getUsername, userName));
            if (user == null) {
                return ResultVO.fail(HttpStatusEnum.USERNAME_NOT_EXISTS.getMsg());
            }
            if (Strings.isBlank(user.getMobile())) {
                return ResultVO.fail(HttpStatusEnum.ACCOUNT_NOT_BIND_PHONE.getMsg());
            }
            if (!Objects.equals(mobile, user.getMobile())) {
                return ResultVO.fail(HttpStatusEnum.PHONE_NUM_ERROR.getMsg());
            }
        } else {
            user = super.getOne(new LambdaQueryWrapper<User>()
                    .eq(User::getGameId, userData.getGameId())
                    .eq(User::getMobile, mobile));
            if (user == null) {
                return ResultVO.fail(HttpStatusEnum.PHONE_NOT_REG.getMsg());
            }
        }
        //验证码校验
        HttpStatusEnum httpStatusEnum = smsService.smsCheck(SmsTypeEnum.SMS_FIND_PWD.getType(), mobile, code);
        //验证不通过, 返回
        if (!Objects.equals(httpStatusEnum, HttpStatusEnum.SUCCESS)) {
            return ResultVO.fail(httpStatusEnum.getMsg());
        }
        //更新用户密码
        super.update(new LambdaUpdateWrapper<User>()
                .set(User::getUpdateTime, LocalDateTime.now())
                .set(User::getPassword, RegisterUtil.cmfPassword(newPassword))
                .eq(User::getId, user.getId())
        );
        //返回修改成功
        return ResultVO.ok(Boolean.TRUE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVO<Boolean> updatePassword(UpdatePasswordParam param, UserData userData) {
        String oldPassword = param.getOldPassword();
        String newPassword = param.getNewPassword();
        //查询用户信息
        User user = super.getById(userData.getUserId());
        //旧密存在
        if (Strings.isNotBlank(user.getPassword())) {
            //旧密码不可为空
            if (Strings.isBlank(oldPassword)) {
                return ResultVO.fail(HttpStatusEnum.OLD_PASSWORD_EMPTY.getMsg());
            }
            //旧密码错误
            if (!Objects.equals(RegisterUtil.cmfPassword(oldPassword), user.getPassword())) {
                return ResultVO.fail(HttpStatusEnum.OLD_PASSWORD_ERROR.getMsg());
            }
        }
        //新密码校验
        HttpStatusEnum checkPasswordEnum = RegisterUtil.checkPassword(newPassword);
        if (!Objects.equals(checkPasswordEnum, HttpStatusEnum.SUCCESS)) {
            return ResultVO.fail(checkPasswordEnum.getMsg());
        }
        //修改用户密码
        super.update(new LambdaUpdateWrapper<User>()
                .set(User::getPassword, RegisterUtil.cmfPassword(newPassword))
                .set(User::getUpdateTime, LocalDateTime.now())
                .eq(User::getId, user.getId())
        );
        //返回修改成功
        return ResultVO.ok(Boolean.TRUE);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVO<Boolean> bindPhone(BindPhoneParam param, UserData userData) {
        String code = param.getCode();
        String mobile = param.getMobile();
        //判断是否已经绑定该账号
        User user = this.getById(userData.getUserId());
        if (user == null) {
            throw new BaseException("参数错误, 用户信息不存在");
        }
        //判断手机号是否已经绑定
        if (Strings.isNotBlank(user.getMobile()) && Objects.equals(user.getMobile(), mobile)) {
            return ResultVO.fail(HttpStatusEnum.PHONE_IS_BIND.getMsg());
        }
        //校验手机号是否已经绑定了其他账号
        long count = super.count(new LambdaQueryWrapper<User>()
                .eq(User::getGameId, userData.getGameId())
                .eq(User::getMobile, mobile));
        if (count > 0) {
            return ResultVO.fail(HttpStatusEnum.PHONE_BIND_TOO_MUCH.getMsg());
        }
        //验证码校验
        HttpStatusEnum httpStatusEnum = smsService.smsCheck(SmsTypeEnum.SMS_BIND.getType(), mobile, code);
        //验证不通过, 返回
        if (!Objects.equals(httpStatusEnum, HttpStatusEnum.SUCCESS)) {
            return ResultVO.fail(httpStatusEnum.getMsg());
        }
        //修改用户用户手机号
        super.update(new LambdaUpdateWrapper<User>()
                .set(User::getMobile, mobile)
                .set(User::getUpdateTime, LocalDateTime.now())
                .eq(User::getId, userData.getUserId())
        );
        //返回修改成功
        return ResultVO.ok(Boolean.TRUE);
    }

    @Override
    public UserVO getUserDetail(UserData userData) {
        Long userId = userData.getUserId();
        //查询用户信息
        User user = this.getById(userId);
        //查询用户实名信息
        UserCard userCard = userCardService.getOne(new LambdaQueryWrapper<UserCard>()
                .eq(UserCard::getUserId, userId)
                .orderByDesc(UserCard::getCreateTime)
                .last("limit 1"));
        //查询游戏
        GameExt gameExt = gameExtService.getByGameId(userData.getGameId());
        //构造用户登录信息
        UserVO userVO = UserVO.builder()
                .userId(user.getId())
                .userName(user.getUsername())
                .authentication(user.getAuthentication())
                .bindPhone(Strings.isBlank(user.getMobile()) ? 0 : 1)
                .hasOldPassword(Strings.isNotBlank(user.getPassword()))
                .phoneNum(user.getShowPhoneNum())
                .cardName(userCard == null ? null : userCard.getShowCardName())
                .cardId(userCard == null ? null : userCard.getShowCardId())
                .checkSwitch(gameExt.getCheckSwitch())
                .token(userData.getToken())
                .build();
        //判断用户是否为导量H5用户, 修正用户id
        if (user.getRelationUserId() != null) {
            userVO.setUserId(user.getRelationUserId());
        }
        log.error("获取用户详情返回用户信息, userVO : {}", JsonUtil.toString(userVO));
        return userVO;
    }

    @Override
    public CustomerVO getUserCustomer(UserData userData) {
        Long gameId = userData.getGameId();
        GameExt gameExt = gameExtService.getByGameId(gameId);
        return CustomerVO.builder()
                .customerPhone(gameExt.getCustomerPhone())
                .customerQq(gameExt.getCustomerQq())
                .mpAppId(gameExt.getMpAppId())
                .mpAppName(gameExt.getMpAppName())
                .mpCode(gameExt.getMpCode())
                .build();
    }

    @Override
    public UserDTO getUserInfoByMobile(String mobile, Long gameId) {
        User user = super.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getGameId, gameId)
                .eq(User::getMobile, mobile));
        return BeanUtil.copy(user, UserDTO.class);
    }

    @Override
    public UserDTO getUserByOpenId(Long gameId, String openId) {
        User user = super.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getGameId, gameId)
                .eq(User::getOpenId, openId));
        if (user == null) {
            log.error("参数错误, 根据openId查询用户信息不存在, gameId : {}, openId : {}", gameId, openId);
            throw new BaseException("参数错误, 根据openId查询用户信息不存在");
        }
        return BeanUtil.copy(user, UserDTO.class);
    }

    @Override
    public UserDTO getUserByUserId(Long userId) {
        User user = super.getById(userId);
        if (user == null) {
            log.error("参数错误, 根据userId查询用户信息不存在,  userId : {}", userId);
            throw new BaseException("参数错误, 根据userId查询用户信息不存在");
        }
        return BeanUtil.copy(user, UserDTO.class);
    }
}
