
package com.tmerclub.cloud.biz.controller.app;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.google.common.collect.Maps;
import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.auth.feign.AccountFeignClient;
import com.tmerclub.cloud.api.auth.vo.AuthAccountVO;
import com.tmerclub.cloud.api.user.feign.UserFeignClient;
import com.tmerclub.cloud.api.user.vo.UserApiVO;
import com.tmerclub.cloud.biz.dto.SendAndCheckSmsDTO;
import com.tmerclub.cloud.biz.service.SmsLogService;
import com.tmerclub.cloud.common.cache.util.RedisUtil;
import com.tmerclub.cloud.common.constant.SendTypeEnum;
import com.tmerclub.cloud.common.constant.StatusEnum;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Objects;

/**
 * @author tmerclub
 * @date 2021/01/16
 */
@RequestMapping("/ua/sms/verification_code")
@RestController
@Tag(name = "短信接口")
public class SmsController {

    @Autowired
    private SmsLogService smsLogService;
    @DubboReference
    private UserFeignClient userFeignClient;
    @DubboReference
    private AccountFeignClient accountFeignClient;

    public static final String CHECK_REGISTER_SMS_FLAG = "checkRegisterSmsFlag";
    public static final String CHECK_UPDATE_SMS_FLAG = "checkUpdatePwdSmsFlag";
    public static final String UPDATE_PWD_SMS_FLAG = "updatePwdSmsFlag";

    @PutMapping("/register")
    @Operation(summary = "发送注册验证码", description = "发送注册验证码")
    public ServerResponseEntity<Void> register(@Valid @RequestBody SendAndCheckSmsDTO sendAndCheckSmsDto) {
        if (accountFeignClient.countByMobile(sendAndCheckSmsDto.getMobile()).getData() > 0) {
            // 该手机号已注册，无法重新注册
            return ServerResponseEntity.showFailMsg("该手机号已注册，无法重新注册");
        }
        // 每个手机号每分钟只能发十个注册的验证码，免得接口被利用
        smsLogService.sendSmsCode(SendTypeEnum.REGISTER, sendAndCheckSmsDto.getMobile(), Maps.newHashMap());
        return ServerResponseEntity.success();
    }

    @PutMapping("/check_register")
    @Operation(summary = "校验验证码", description = "校验验证码返回校验成功的标识")
    public ServerResponseEntity<String> checkRegisterSms(@Valid @RequestBody SendAndCheckSmsDTO sendAndCheckSmsDto) {
        // 每个ip每分钟只能发十个注册的验证码，免得接口被利用
        if (!smsLogService.checkValidCode(sendAndCheckSmsDto.getMobile(), sendAndCheckSmsDto.getValidCode(), SendTypeEnum.REGISTER)) {
            // 验证码有误或已过期
            return ServerResponseEntity.fail(ResponseEnum.VERIFICATION_CODE_ERROR);
        }
        String checkRegisterSmsFlag = IdUtil.simpleUUID();
        RedisUtil.set(CHECK_REGISTER_SMS_FLAG + checkRegisterSmsFlag, sendAndCheckSmsDto.getMobile(), 600);
        return ServerResponseEntity.success(checkRegisterSmsFlag);
    }

    @PutMapping("/apply_shop")
    @Operation(summary = "发送申请开店验证码", description = "发送申请开店验证码")
    public ServerResponseEntity<Void> applyShopSms(@Valid @RequestBody SendAndCheckSmsDTO sendSmsParam) {
        if (accountFeignClient.countByMobileAndSysType(sendSmsParam.getMobile(), SysTypeEnum.MULTISHOP.value()).getData() > 0) {
            return ServerResponseEntity.showFailMsg("手机号已存在，请更换手机号再次尝试");
        }
        // 每个手机号每分钟只能发十个注册的验证码，免得接口被利用
        smsLogService.sendSmsCode(SendTypeEnum.VALID, sendSmsParam.getMobile(), Maps.newHashMap());
        return ServerResponseEntity.success();
    }

    @PutMapping("/apply_supplier")
    @Operation(summary = "发送申请开店验证码", description = "发送申请开店验证码")
    public ServerResponseEntity<Void> applySupplierSms(@Valid @RequestBody SendAndCheckSmsDTO sendSmsParam) {
        if (accountFeignClient.countByMobileAndSysType(sendSmsParam.getMobile(), SysTypeEnum.SUPPLIER.value()).getData() > 0) {
            return ServerResponseEntity.showFailMsg("手机号已存在，请更换手机号再次尝试");
        }
        // 每个手机号每分钟只能发十个注册的验证码，免得接口被利用
        smsLogService.sendSmsCode(SendTypeEnum.VALID, sendSmsParam.getMobile(), Maps.newHashMap());
        return ServerResponseEntity.success();
    }

    /**
     * 发送修改密码验证码接口
     */
    @PutMapping("/update_pwd")
    @Operation(summary = "发送修改密码验证码接口", description = "发送修改密码验证码接口")
    public ServerResponseEntity<Void> sendUpdatePwdCode(@RequestBody SendAndCheckSmsDTO sendSmsParam) {

        List<UserApiVO> userList = userFeignClient.countUserByMobile(sendSmsParam.getMobile()).getData();
        if (CollUtil.isEmpty(userList)){
            throw new LuckException("该手机号码未注册");
        }else if(Objects.equals(userList.get(0).getStatus(), 0)){
            throw new LuckException("该手机号码已被禁用");
        }
        // 每个手机号每分钟只能发十个注册的验证码，免得接口被利用
        smsLogService.sendSmsCode(SendTypeEnum.UPDATE_PASSWORD, sendSmsParam.getMobile(), Maps.newHashMap());
        return ServerResponseEntity.success();
    }

    @PutMapping("/check_update_pwd")
    @Operation(summary = "校验用户忘记密码时的验证码", description = "校验验证码返回校验成功的标识")
    public ServerResponseEntity<String> checkUpdatePwdSms(@Valid @RequestBody SendAndCheckSmsDTO sendAndCheckSmsDto) {
        // 每个ip每分钟只能发十个注册的验证码，免得接口被利用
        String checkUpdatePwdSmsFlag = IdUtil.simpleUUID();
        if (!smsLogService.checkValidCode(sendAndCheckSmsDto.getMobile(), sendAndCheckSmsDto.getValidCode(), SendTypeEnum.UPDATE_PASSWORD)) {
            // 验证码有误或已过期
            return ServerResponseEntity.fail(ResponseEnum.VERIFICATION_CODE_ERROR);
        }
        RedisUtil.set(CHECK_UPDATE_SMS_FLAG + checkUpdatePwdSmsFlag, sendAndCheckSmsDto.getMobile(), 600);
        return ServerResponseEntity.success(checkUpdatePwdSmsFlag);
    }

    @PutMapping("/checkUpdatePhoneSms")
    @Operation(summary = "校验用户手机号修改时的验证码", description = "校验用户手机号修改时的验证码")
    public ServerResponseEntity<String> checkUpdatePhoneSms(@RequestBody SendAndCheckSmsDTO sendAndCheckSmsDTO) {

        if (!smsLogService.checkValidCode(sendAndCheckSmsDTO.getMobile(), sendAndCheckSmsDTO.getValidCode(), SendTypeEnum.VALID)) {
            // 验证码有误或已过期
            throw new LuckException("验证码有误或已过期");
        }
        String checkRegisterSmsFlag = IdUtil.simpleUUID();
        RedisUtil.set(UPDATE_PWD_SMS_FLAG + checkRegisterSmsFlag, sendAndCheckSmsDTO.getMobile(), 600);
        return ServerResponseEntity.success(checkRegisterSmsFlag);
    }

    /**
     * 修改用户手机号时发送验证码
     */
    @PutMapping("/valid")
    @Operation(summary = "发送验证码接口", description = "发送验证码接口")
    public ServerResponseEntity<Void> validSms(@RequestBody SendAndCheckSmsDTO sendSmsParam) {
        if (accountFeignClient.countByMobileAndSysType(sendSmsParam.getMobile(), SysTypeEnum.ORDINARY.value()).getData() > 0) {
            return ServerResponseEntity.showFailMsg("手机号已存在，请更换手机号后再次尝试");
        }
        // 每个手机号每分钟只能发十个注册的验证码，免得接口被利用
        smsLogService.sendSmsCode(SendTypeEnum.VALID, sendSmsParam.getMobile(), Maps.newHashMap());
        return ServerResponseEntity.success();
    }

    @PutMapping("/login_code")
    @Operation(summary = "发送手机号登录验证码接口")
    public ServerResponseEntity<Void> sendLoginCode(@RequestBody SendAndCheckSmsDTO sendSmsParam) {
        ServerResponseEntity<List<AuthAccountVO>> listServerResponseEntity = accountFeignClient.listByUserAccount(null, sendSmsParam.getMobile(), null, SysTypeEnum.ORDINARY);
        if(!listServerResponseEntity.isSuccess()){
            throw new LuckException(listServerResponseEntity.getMsg());
        }
        List<AuthAccountVO> accountList = listServerResponseEntity.getData();
        if(CollUtil.isNotEmpty(accountList) && Objects.equals(accountList.get(0).getStatus(), StatusEnum.DISABLE.value())){
            // 用户已禁用，请联系客服
            return ServerResponseEntity.showFailMsg("用户已禁用，请联系客服");
        }
        // 每个手机号每分钟只能发十个注册的验证码，免得接口被利用
        smsLogService.sendSmsCode(SendTypeEnum.LOGIN, sendSmsParam.getMobile(), Maps.newHashMap());
        return ServerResponseEntity.success();
    }
}
