package cn.newfeifan.mall.module.member.controller.app.auth;

import cn.hutool.core.util.StrUtil;
import cn.newfeifan.mall.framework.common.enums.UserTypeEnum;
import cn.newfeifan.mall.framework.common.pojo.CommonResult;
import cn.newfeifan.mall.framework.operatelog.core.annotations.OperateLog;
import cn.newfeifan.mall.framework.security.config.SecurityProperties;
import cn.newfeifan.mall.framework.security.core.annotations.PreAuthenticated;
import cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils;
import cn.newfeifan.mall.module.member.controller.app.auth.vo.*;
import cn.newfeifan.mall.module.member.convert.auth.AuthConvert;
import cn.newfeifan.mall.module.member.service.auth.MemberAuthService;
import cn.newfeifan.mall.module.system.api.social.SocialClientApi;
import cn.newfeifan.mall.module.system.api.social.dto.SocialWxJsapiSignatureRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
import static cn.newfeifan.mall.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

@Tag(name = "用户 APP - 认证")
@RestController
@RequestMapping("/member/auth")
@Validated
@Slf4j
public class AppAuthController {

    @Resource
    private MemberAuthService authService;

    @Resource
    private SocialClientApi socialClientApi;

    @Resource
    private SecurityProperties securityProperties;


    @PostMapping("/login")
    @Operation(summary = "使用手机号 + 密码登录")
    public CommonResult<AppAuthLoginRespVO> login(@RequestBody @Valid AppAuthLoginReqVO reqVO) {
        return success(authService.login(reqVO));
    }

    @PostMapping("/logout")
    @PermitAll
    @Operation(summary = "登出系统")
    public CommonResult<Boolean> logout(HttpServletRequest request) {
        String token = SecurityFrameworkUtils.obtainAuthorization(request,
                securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
        if (StrUtil.isNotBlank(token)) {
            authService.logout(token);
        }
        return success(true);
    }

    @PostMapping("/deleteUser")
    @Operation(summary = "用户注销")
    @Parameter(name = "deleteUser", description = "用户注销", required = true)
    public CommonResult<Boolean> deleteUser(HttpServletRequest request){
        authService.deleteUser(getLoginUserId());

        String token = SecurityFrameworkUtils.obtainAuthorization(request,
                securityProperties.getTokenHeader(), securityProperties.getTokenParameter());
        if (StrUtil.isNotBlank(token)) {
            authService.logout(token);
        }

        return success(true);
    }

    @PostMapping("/refresh-token")
    @Operation(summary = "刷新令牌")
    @Parameter(name = "refreshToken", description = "刷新令牌", required = true)
    @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
    public CommonResult<AppAuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken) {
        return success(authService.refreshToken(refreshToken));
    }

    // ========== 短信登录相关 ==========

    @PostMapping("/sms-register")
    @Operation(summary = "使用用户名 + 手机 + 密码注册")
    public CommonResult<AppAuthLoginRespVO> smsRegister(@RequestBody @Valid AppAuthSmsRegisterReqVO reqVO) {
        return success(authService.smsRegister(reqVO));
    }

    @PostMapping("/send-sms-code")
    @Operation(summary = "发送手机验证码")
    public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid AppAuthSmsSendReqVO reqVO) {
        authService.sendSmsCode(getLoginUserId(), reqVO);
        return success(true);
    }

    @PostMapping("/validate-sms-code")
    @Operation(summary = "校验手机验证码")
    public CommonResult<Boolean> validateSmsCode(@RequestBody @Valid AppAuthSmsValidateReqVO reqVO) {
        authService.validateSmsCode(getLoginUserId(), reqVO);
        return success(true);
    }

    // ========== 社交登录相关 ==========

    @GetMapping("/social-auth-redirect")
    @Operation(summary = "社交授权的跳转")
    @Parameters({
            @Parameter(name = "type", description = "社交类型", required = true),
            @Parameter(name = "redirectUri", description = "回调路径")
    })
    public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
                                                   @RequestParam("redirectUri") String redirectUri) {
        return CommonResult.success(authService.getSocialAuthorizeUrl(type, redirectUri));
    }

    @PostMapping("/create-weixin-jsapi-signature")
    @Operation(summary = "创建微信 JS SDK 初始化所需的签名",
            description = "参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档")
    public CommonResult<SocialWxJsapiSignatureRespDTO> createWeixinMpJsapiSignature(@RequestParam("url") String url) {
        SocialWxJsapiSignatureRespDTO signature = socialClientApi.createWxMpJsapiSignature(
                UserTypeEnum.MEMBER.getValue(), url);
        return success(AuthConvert.INSTANCE.convert(signature));
    }


    @PostMapping("/weChatOfficialLogin")
    @Operation(summary = "需要获取到对应的code",
            description = "绑定二维码后免登录")
    public CommonResult<SocialWxJsapiSignatureRespDTO> weChatOfficialLogin(@RequestParam("code") String code) {
        SocialWxJsapiSignatureRespDTO signature = socialClientApi.createWxMpJsapiSignature(
                UserTypeEnum.MEMBER.getValue(), code);
        return success(AuthConvert.INSTANCE.convert(signature));
    }

    @GetMapping("/redirectLogin")
    @Operation(summary = "重定向登录")
    @PreAuthenticated
    public CommonResult<String> redirectLogin() {
        return success(authService.redirectLogin());
    }

}
