/**
 * @filename:CustomerUserServiceImpl 2024年04月01日
 * @project trade-client V1.0 Copyright(c) 2024 wanglang Co. Ltd. All right reserved.
 */
package com.trade.client.enterprise.customer.service.impl;

import com.trade.client.enterprise.customer.constant.CustConstant;
import com.trade.client.enterprise.customer.constant.RedisKey;
import com.trade.client.enterprise.customer.domain.CustomerUser;
import com.trade.client.enterprise.customer.domain.model.LoginUserInfo;
import com.trade.client.enterprise.customer.domain.model.RegisterMo;
import com.trade.client.enterprise.customer.enums.ModuleEnum;
import com.trade.client.enterprise.customer.mapper.CustomerUserMapper;
import com.trade.client.enterprise.customer.service.CustomerMessageService;
import com.trade.client.enterprise.customer.service.CustomerUserRemoteService;
import com.trade.client.enterprise.customer.service.CustomerUserService;
import com.trade.client.security.utils.UserUtils;
import com.trade.client.system.domain.CustomerOperationLog;
import com.trade.client.system.service.CustomerOperationLogService;
import com.trade.common.constant.HttpStatus;
import com.trade.common.core.domain.ResponseResult;
import com.trade.common.enums.BusinessType;
import com.trade.common.exception.ServiceException;
import com.trade.common.redis.RedisCache;
import com.trade.common.security.EncryptUtils;
import com.trade.common.utils.LoggerUtil;
import com.trade.common.utils.RegexpUtil;
import com.trade.common.utils.StringUtils;
import com.trade.common.utils.uuid.SnowflakeIdGenerator;
import org.slf4j.Logger;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @Description: 客户服务实现
 * @version: V1.0
 * @author: wanglang
 * @date: 2024年04月01日
 */
@Service
public class CustomerUserServiceImpl extends ServiceImpl<CustomerUserMapper, CustomerUser> implements CustomerUserService {

    private static final Logger log = LoggerUtil.logger(LoggerUtil.LogFileNameEnum.SYS_LOG);;
    @Resource
    private RedisCache redisCache;
    @Resource
    private CustomerUserMapper mapper;
    @Resource
    private CustomerOperationLogService customerOperationLogService;
    @Resource
    private CustomerUserRemoteService customerUserRemoteService;
    @Resource
    @Lazy
    private CustomerMessageService customerMessageService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(RegisterMo register) {
        if (!redisCache.hasKey(RedisKey.VERIFICATION_CODE_EXPIRED + register.getPhoneNumber())) {
            throw new ServiceException("验证码已失效", HttpStatus.BAD_REQUEST);
        }
        String redisCode = redisCache.getCacheObject(RedisKey.VERIFICATION_CODE_EXPIRED + register.getPhoneNumber());
        if (!redisCode.equals(register.getCode())) {
            throw new ServiceException("验证码输入错误，请检查", HttpStatus.BAD_REQUEST);
        }
        if (!checkExistence(null, register.getUserName())) {
            throw new ServiceException("用户昵称已存在,请直接登录或者重新输入新昵称", HttpStatus.BAD_REQUEST);
        }
        if (!this.checkExistence(register.getPhoneNumber(), null)) {
            throw new ServiceException("用户已存在,请直接登录", HttpStatus.BAD_REQUEST);
        }
        CustomerUser customerUser = new CustomerUser(register);
        customerUser.setIdentifierNo(new SnowflakeIdGenerator(1).nextUniqueId());
        mapper.insert(customerUser);
        String referralCode = register.getReferralCode();
        if (!StringUtils.isEmpty(referralCode)) {
            ResponseResult<Boolean> responseResult = customerUserRemoteService.checkReferralCode(referralCode);
            if (responseResult.getCode() != HttpStatus.SUCCESS || !responseResult.getData()) {
                throw new ServiceException("推荐码不正确", HttpStatus.BAD_REQUEST);
            }
        }
        customerUserRemoteService.customerAssign(customerUser.getId(), referralCode, customerUser.getIdentifierNo());
        return true;
    }

    @Override
    public boolean updatePassword(String phoneNumber, String password, String code) {
        if (StringUtils.isEmpty(phoneNumber)) {
            throw new ServiceException("手机号不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(password)) {
            throw new ServiceException("密码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(code)) {
            throw new ServiceException("验证码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (!CustomerUser.verifyPasswordRules(password)) {
            throw new ServiceException("重置密码密码必须是8～16位数字、字母以及特殊字符的组合", HttpStatus.BAD_REQUEST);
        }
        if (!redisCache.hasKey(RedisKey.VERIFICATION_CODE_EXPIRED + phoneNumber)) {
            throw new ServiceException("验证码已失效", HttpStatus.BAD_REQUEST);
        }
        String redisCode = redisCache.getCacheObject(RedisKey.VERIFICATION_CODE_EXPIRED + phoneNumber);
        if (!redisCode.equals(code)) {
            throw new ServiceException("\"验证码输入错误，请检查", HttpStatus.BAD_REQUEST);
        }
        CustomerUser customerUser = mapper.selectByPhoneOrName(phoneNumber);
        if (customerUser == null) {
            throw new ServiceException("用户不存在", HttpStatus.BAD_REQUEST);
        }
        String content = "忘记密码操作:手机号" + phoneNumber + ",重置密码成功";
        customerUser.resetPassword(password);
        customerOperationLogService.sava(new CustomerOperationLog(customerUser.getId(), ModuleEnum.SIGN_UP.getCode(),
                BusinessType.UPDATE.name(), content));
        return mapper.updateById(customerUser) == 1;
    }

    @Override
    public boolean modifyPassword(String oldPassword, String newPassword) {
        if (StringUtils.isEmpty(oldPassword)) {
            throw new ServiceException("旧密码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(newPassword)) {
            throw new ServiceException("新密码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (oldPassword.equals(newPassword)) {
            throw new ServiceException("与旧密码一致请重新输入", HttpStatus.BAD_REQUEST);
        }
        CustomerUser customerUser = getCustomerUser();
        if (!EncryptUtils.matchesPassword(oldPassword, customerUser.getPassword())) {
            throw new ServiceException("旧密码输入错误", HttpStatus.BAD_REQUEST);
        }
        if (!customerUser.verifyPasswordRules(newPassword)) {
            throw new ServiceException("确认新密码密码必须是8～16位数字、字母以及特殊字符的组合", HttpStatus.BAD_REQUEST);
        }
        customerUser.setPassword(EncryptUtils.encryptPassword(newPassword));
        String content = "修改密码成功";
        customerOperationLogService.sava(new CustomerOperationLog(customerUser.getId(), ModuleEnum.SIGN_UP.getCode(),
                BusinessType.UPDATE.name(), content));
        return mapper.updateById(customerUser) == 1;
    }

    @Override
    public boolean modifyPhoneNumber(String code, String newPhoneNumber, String newCode) {
        if (StringUtils.isEmpty(code)) {
            throw new ServiceException("旧手机不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(newPhoneNumber)) {
            throw new ServiceException("新手机号不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(newCode)) {
            throw new ServiceException("新手机验证码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (!RegexpUtil.checkPhone(newPhoneNumber)) {
            throw new ServiceException("手机号格式不正确", HttpStatus.BAD_REQUEST);
        }
        CustomerUser customerUser = getCustomerUser();
        if (!redisCache.hasKey(RedisKey.VERIFICATION_CODE_EXPIRED + customerUser.getPhoneNumber())) {
            throw new ServiceException("旧手机验证码已过期", HttpStatus.BAD_REQUEST);
        }
        if (!redisCache.hasKey(RedisKey.VERIFICATION_CODE_EXPIRED + newPhoneNumber)) {
            throw new ServiceException("新手机验证码已过期", HttpStatus.BAD_REQUEST);
        }
        String redisNewCode = redisCache.getCacheObject(RedisKey.VERIFICATION_CODE_EXPIRED + newPhoneNumber);
        if (!newCode.equals(redisNewCode)) {
            throw new ServiceException("新手机验证码输入有误", HttpStatus.BAD_REQUEST);
        }
        String redisCode = redisCache
                .getCacheObject(RedisKey.VERIFICATION_CODE_EXPIRED + customerUser.getPhoneNumber());
        if (!code.equals(redisCode)) {
            throw new ServiceException("旧手机验证码输入有误", HttpStatus.BAD_REQUEST);
        }
        if (mapper.selectByPhoneOrName(newPhoneNumber) != null) {
            throw new ServiceException("手机号已被占用", HttpStatus.BAD_REQUEST);
        }
        String oldPhoneNumber = customerUser.getPhoneNumber();
        customerUser.setPhoneNumber(newPhoneNumber);
        redisCache.deleteObject(RedisKey.VERIFICATION_CODE_EXPIRED + newPhoneNumber);
        redisCache.deleteObject(RedisKey.VERIFICATION_CODE_EXPIRED + oldPhoneNumber);
        boolean isSuccess = mapper.updateById(customerUser) == 1;
        String content = "修改手机号操作:将手机号" + oldPhoneNumber + "修改为" + newPhoneNumber;
        customerOperationLogService.sava(new CustomerOperationLog(customerUser.getId(), ModuleEnum.SIGN_UP.getCode(),
                BusinessType.UPDATE.name(), content));
        return isSuccess;
    }

    @Override
    public boolean bindingEmail(String email, String code, String phoneCode) {
        if (StringUtils.isEmpty(email)) {
            throw new ServiceException("邮箱不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(code)) {
            throw new ServiceException("邮箱验证码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(phoneCode)) {
            throw new ServiceException("手机验证码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (!RegexpUtil.checkEmail(email)) {
            throw new ServiceException("邮箱格式不正确", HttpStatus.BAD_REQUEST);
        }
        CustomerUser customerUser = getCustomerUser();
        if (!redisCache.hasKey(RedisKey.VERIFICATION_CODE_EXPIRED + customerUser.getPhoneNumber())) {
            throw new ServiceException("手机验证码已过期", HttpStatus.BAD_REQUEST);
        }
        customerMessageService.checkEmailAuthCode(email, code, CustConstant.USER_BINDING_EMAIL_TEMPLATE);
        String redisCode = redisCache
                .getCacheObject(RedisKey.VERIFICATION_CODE_EXPIRED + customerUser.getPhoneNumber());
        if (!phoneCode.equals(redisCode)) {
            throw new ServiceException("手机验证码输入有误", HttpStatus.BAD_REQUEST);
        }
        customerUser.setEmail(email);
        boolean isSuccess = mapper.updateById(customerUser) == 1;
        redisCache.deleteObject(RedisKey.VERIFICATION_CODE_EXPIRED + customerUser.getPhoneNumber());
        String content = "新增邮箱操作:添加邮箱" + email;
        customerOperationLogService.sava(new CustomerOperationLog(customerUser.getId(), ModuleEnum.SIGN_UP.getCode(),
                BusinessType.UPDATE.name(), content));
        return isSuccess;
    }

    @Override
    public boolean modifyEmail(String email, String code, String emailCode) {
        if (StringUtils.isEmpty(email)) {
            throw new ServiceException("新邮箱不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(code)) {
            throw new ServiceException("新邮箱验证码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(emailCode)) {
            throw new ServiceException("当前邮箱验证码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (!RegexpUtil.checkEmail(email)) {
            throw new ServiceException("新邮箱格式不正确", HttpStatus.BAD_REQUEST);
        }
        CustomerUser customerUser = getCustomerUser();
        if (!redisCache.hasKey(RedisKey.VERIFICATION_CODE_EXPIRED + email)) {
            throw new ServiceException("新邮箱验证码已过期", HttpStatus.BAD_REQUEST);
        }
        if (!redisCache.hasKey(RedisKey.VERIFICATION_CODE_EXPIRED + customerUser.getEmail())) {
            throw new ServiceException("当前邮箱验证码已过期", HttpStatus.BAD_REQUEST);
        }
        String redisEmailCode = redisCache.getCacheObject(RedisKey.VERIFICATION_CODE_EXPIRED + email);
        if (!redisEmailCode.equals(code)) {
            throw new ServiceException("新邮箱验证码输入有误,请您检查", HttpStatus.BAD_REQUEST);
        }
        String oldEmailCode = redisCache.getCacheObject(RedisKey.VERIFICATION_CODE_EXPIRED + customerUser.getEmail());
        if (!emailCode.equals(oldEmailCode)) {
            throw new ServiceException("当前邮箱验证码输入有误,请您检查", HttpStatus.BAD_REQUEST);
        }
        String oldEmail = customerUser.getEmail();
        redisCache.deleteObject(RedisKey.VERIFICATION_CODE_EXPIRED + email);
        redisCache.deleteObject(RedisKey.VERIFICATION_CODE_EXPIRED + oldEmail);
        customerUser.setEmail(email);
        String content = "修改邮箱操作:将邮箱" + oldEmail + "修改为" + email;
        customerOperationLogService.sava(new CustomerOperationLog(customerUser.getId(), ModuleEnum.SIGN_UP.getCode(),
                BusinessType.UPDATE.name(), content));
        return mapper.updateById(customerUser) == 1;
    }

    @Override
    public boolean bindXtUserId(Long userId, String xtUserId) {
        CustomerUser customerUser = mapper.selectById(userId);
        if (customerUser == null) {
            throw new ServiceException("用户不存在", HttpStatus.BAD_REQUEST);
        }
        customerUser.setXtUid(xtUserId);
        return mapper.updateById(customerUser) == 1;
    }

    @Override
    public boolean resetPassword(Long userId, String resetPassword, String confirmPassword) {
        if (userId == null) {
            throw new ServiceException("用户ID不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(resetPassword)) {
            throw new ServiceException("重置密码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (StringUtils.isEmpty(confirmPassword)) {
            throw new ServiceException("确认密码不能为空", HttpStatus.BAD_REQUEST);
        }
        if (!resetPassword.equals(confirmPassword)) {
            throw new ServiceException("两次密码不一致", HttpStatus.BAD_REQUEST);
        }
        if (!CustomerUser.verifyPasswordRules(resetPassword)) {
            throw new ServiceException("重置密码密码必须是8～16位数字、字母以及特殊字符的组合", HttpStatus.BAD_REQUEST);
        }
        if (!CustomerUser.verifyPasswordRules(confirmPassword)) {
            throw new ServiceException("确认密码密码必须是8～16位数字、字母以及特殊字符的组合", HttpStatus.BAD_REQUEST);
        }
        CustomerUser customerUser = mapper.selectById(userId);
        if (customerUser == null) {
            throw new ServiceException("用户不存在", HttpStatus.BAD_REQUEST);
        }
        customerUser.resetPassword(confirmPassword);
        return mapper.updateById(customerUser) == 1;
    }

    @Override
    public boolean checkExistence(String phoneNumber, String nickname) {
        CustomerUser customerUser = mapper.selectByPhoneAndName(phoneNumber, nickname);
        return customerUser == null;
    }

    @Override
    public CustomerUser findByPhoneOrName(String userName) {
        return mapper.selectByPhoneOrName(userName);
    }

    @Override
    public CustomerUser getCustomerUser() {
        LoginUserInfo loginUserInfo = UserUtils.getLoginUser();
        CustomerUser customerUser = mapper.selectById(loginUserInfo.getCustomerUserId());
        if (customerUser == null) {
            throw new ServiceException("用户不存在", HttpStatus.BAD_REQUEST);
        }
        return customerUser;
    }

    @Override
    public CustomerUser getCustomerUserInfo() {
        LoginUserInfo loginUserInfo = UserUtils.getLoginUser();
        CustomerUser customerUser = loginUserInfo.getCustomerUser();
        customerUser.setPassword(null);
        return customerUser;
    }
}
