package cn.sikey.mcdisk.controller.app.wristwatch;

import cn.sikey.framework.common.exception.ServiceException;
import cn.sikey.framework.common.pojo.CommonResult;
import cn.sikey.mcdisk.controller.app.wristwatch.vo.*;
import cn.sikey.mcdisk.enums.CodeStatusEnum;
import cn.sikey.mcdisk.enums.RateLimit;
import cn.sikey.mcdisk.service.AuthorizeService;
import cn.sikey.mcdisk.util.PhoneValidatorUtil;
import cn.sikey.mcdisk.util.SmsRateLimiterUtil;
import cn.sikey.selenium.api.selenium.SmsApi;
import cn.sikey.selenium.api.selenium.dto.AuthRespVO;
import cn.sikey.selenium.api.selenium.dto.TriggerSmsReqDTO;
import cn.sikey.selenium.api.selenium.dto.VerifyCodeReqDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @Author: nelson
 * @Date: 2025/5/29
 * @Description: 设备授权
 */
@RestController
@RequestMapping("/mcdisk/wristwatch/authorize")
@Slf4j
public class AuthorizeController {

    @Resource
    private AuthorizeService authorizeService;

    @Resource
    private SmsApi smsApi;

    @Qualifier("myTaskExecutor")
    @Autowired
    public ThreadPoolTaskExecutor myTaskExecutor;

    @Resource
    private SmsRateLimiterUtil smsRateLimiterUtil;

    public static final Integer MOBILE_FORMAT_ERROR = 40001;

    /**
     * 发送验证码
     *
     * @param triggerSmsReqDTO 验证码
     * @return
     */
    @RateLimit(key = "triggerSmsVerification", type = RateLimit.LimitType.GLOBAL)
    @PostMapping("/triggerSmsVerification")
    public CommonResult triggerSmsVerification(@Validated @RequestBody TriggerSmsReqDTO triggerSmsReqDTO) {
        if (!PhoneValidatorUtil.isValid(triggerSmsReqDTO.getPhoneNumber())) {
            throw new ServiceException(MOBILE_FORMAT_ERROR, "手机号格式不对");
        }

        smsApi.triggerSmsVerification(triggerSmsReqDTO);

        TriggerSmsVerificationReqVO triggerSmsVerificationReqVO = smsRateLimiterUtil.checkAndIncrement(triggerSmsReqDTO.getPhoneNumber(), 10);

        myTaskExecutor.execute(() -> {
            // 更新设备授权accessToken
            authorizeService.updateAuthorizeAccessTokenByDeviceId(triggerSmsReqDTO.getTicket());
            log.info("[发送验证码]更新设备授权accessToken，成功");
        });

        return CommonResult.success(triggerSmsVerificationReqVO);
    }

    /**
     * 验证码登录
     *
     * @param verifyCodeReqDTO 登录
     * @return
     */
    @RateLimit(key = "verifyCodeAndLogin", type = RateLimit.LimitType.GLOBAL)
    @PostMapping("/verifyCodeAndLogin")
    public CommonResult<AuthRespVO> verifyCodeAndLogin(@Validated @RequestBody VerifyCodeReqDTO verifyCodeReqDTO) {
        if (!PhoneValidatorUtil.isValid(verifyCodeReqDTO.getPhoneNumber())) {
            throw new ServiceException(MOBILE_FORMAT_ERROR, "手机号格式不对");
        }
        return smsApi.verifyCodeAndLogin(verifyCodeReqDTO);
    }

    /**
     * 获取accessToken
     *
     * @param accessToken1ReqVO accessToken
     * @return
     */
    // @RateLimit(key = "accessToken1", type = RateLimit.LimitType.GLOBAL)
    @GetMapping("/accessToken1")
    public CommonResult accessToken1(@Validated AccessToken1ReqVO accessToken1ReqVO) {
        return authorizeService.accessToken1(accessToken1ReqVO);
    }

    /**
     * 刷新Token oauth2/refreshToken
     *
     * @param refreshTokenReqVO refreshTokenReqVO
     * @return
     */
    @RateLimit(key = "refreshToken", type = RateLimit.LimitType.GLOBAL)
    @GetMapping("/refreshToken")
    public CommonResult refreshToken(@Validated RefreshTokenReqVO refreshTokenReqVO) {
        return authorizeService.refreshToken(refreshTokenReqVO);
    }

    /**
     * 设备授权
     *
     * @param oauthReqVO  授权
     * @param accessToken accessToken
     * @return
     */
    /*@RateLimit(key = "wristwatchAuthorization", type = RateLimit.LimitType.GLOBAL)
    @PostMapping("/authorization")
    public CommonResult authorization(@RequestHeader(name = "accessToken") String accessToken, @Validated @RequestBody OauthReqVO oauthReqVO) {
        return authorizeService.oauth(oauthReqVO, accessToken);
    }*/

    /**
     * 查询设备认证
     *
     * @param queryOauthReqVO 设备编码
     * @return
     */
    // @RateLimit(key = "queryAuthorization", type = RateLimit.LimitType.GLOBAL)
    @GetMapping("/queryAuthorization")
    public CommonResult<AuthorizeRespVO> queryAuthorization(@Validated QueryOauthReqVO queryOauthReqVO) {
        return CommonResult.success(authorizeService.queryOauth(queryOauthReqVO.getTicket()));
    }

    /**
     * 手表退出登录
     *
     * @param logoutReqVO 手表退出登录
     * @return
     */
    @PostMapping("/logout")
    public CommonResult logout(@Validated @RequestBody LogoutReqVO logoutReqVO) {
        // 更新设备授权状态
        authorizeService.updateAuthorizeByDeviceId(logoutReqVO.getTicket(), CodeStatusEnum.LOG_OUT.getCode());

        myTaskExecutor.execute(() -> {
            // 更新设备授权accessToken
            authorizeService.updateAuthorizeAccessTokenByDeviceId(logoutReqVO.getTicket());
            log.info("[手表退出登录]更新设备授权accessToken，成功");
        });

        return CommonResult.success();
    }

    /**
     * 通知家长授权
     *
     * @param notifyParentsAuthorizationReqVO 通知家长授权
     * @return
     */
    @PostMapping("/notifyParentsAuthorization")
    public CommonResult notifyParentsAuthorization(@Validated @RequestBody NotifyParentsAuthorizationReqVO notifyParentsAuthorizationReqVO) {
        authorizeService.notifyParentsAuthorization(notifyParentsAuthorizationReqVO);
        return CommonResult.success();
    }
}
