package com.huimv.employment.controller.mp;

import com.huimv.employment.common.web.R;
import com.huimv.employment.security.LoginUser;
import com.huimv.employment.security.LoginUserHolder;
import com.huimv.employment.service.auth.AuthService;
import com.huimv.employment.service.auth.PasswordAuthService;
import com.huimv.employment.service.auth.dto.LoginResponse;
import com.huimv.employment.service.auth.dto.PasswordLoginRequest;
import com.huimv.employment.service.auth.dto.PasswordPublicKeyResponse;
import com.huimv.employment.service.auth.dto.PasswordResetRequest;
import com.huimv.employment.service.auth.dto.PasswordSetRequest;
import com.huimv.employment.service.auth.dto.PasswordStatusResponse;
import com.huimv.employment.service.auth.dto.SmsLoginRequest;
import com.huimv.employment.service.auth.dto.SmsSendRequest;
import com.huimv.employment.service.auth.dto.SmsSendResponse;
import com.huimv.employment.service.auth.dto.WechatLoginRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 小程序端认证：短信 / 微信 / 可选账密（登录后设置）。
 * <p>
 * 登录成功后返回 JWT，后续请求 Header 携带 {@code Authorization: Bearer <token>}。
 * 账密相关密码字段须先调用 {@code GET /password/public-key} 获取 RSA 公钥，前端加密后再提交。
 * </p>
 */
@RestController
@RequestMapping("/api/v1/mp/auth")
@Tag(name = "认证", description = "短信/微信/账密登录与密码管理。除 password/set、password/status 外均为匿名访问")
public class AuthController {

    private final AuthService authService;
    private final PasswordAuthService passwordAuthService;

    public AuthController(AuthService authService, PasswordAuthService passwordAuthService) {
        this.authService = authService;
        this.passwordAuthService = passwordAuthService;
    }

    @PostMapping("/sms/send")
    @Operation(summary = "发送登录验证码",
            description = "向指定手机号发送 6 位登录验证码，同一号码 60 秒内不可重复发送。"
                    + "Mock 模式（fe.sms.mock-enabled=true）下不实际发短信，验证码固定为 123456。"
                    + "须携带 userType，决定登录后的小程序端身份（enterprise / worker）。")
    public R<SmsSendResponse> sendSmsCode(@Validated @RequestBody SmsSendRequest request) {
        return R.ok(authService.sendLoginCode(request));
    }

    @PostMapping("/sms/login")
    @Operation(summary = "短信验证码登录",
            description = "校验验证码后登录或自动注册，返回 JWT 及用户基本信息。"
                    + "userType 仅在首次注册时写入，老用户须从对应入口（enterprise/worker）登录。"
                    + "登录成功后建议调用 GET /api/v1/mp/getInfo 查询登记状态。")
    public R<LoginResponse> loginBySms(@Validated @RequestBody SmsLoginRequest request) {
        return R.ok(authService.loginBySms(request));
    }

    @PostMapping("/wechat/login")
    @Operation(summary = "微信小程序 code 登录",
            description = "使用 wx.login 获取的 code 换取 openid 并登录。"
                    + "userType 仅在首次注册时写入，老用户须从对应入口登录。"
                    + "Mock 模式（fe.wechat.miniapp.mock-enabled=true）下 code 可为任意非空字符串。"
                    + "短信用户与微信用户一期未做账号合并，openid 与手机号分别建号。")
    public R<LoginResponse> loginByWechat(@Validated @RequestBody WechatLoginRequest request) {
        return R.ok(authService.loginByWechat(request));
    }

    @GetMapping("/password/public-key")
    @Operation(summary = "获取 RSA 公钥",
            description = "返回 PEM 格式 RSA 公钥，前端用于加密密码后再调用 login/set/reset 接口。"
                    + "明文密码不在网络传输，服务端解密后 BCrypt 入库。")
    public R<PasswordPublicKeyResponse> passwordPublicKey() {
        return R.ok(passwordAuthService.getPublicKey());
    }

    @PostMapping("/password/login")
    @Operation(summary = "用户名/手机号 + 密码登录",
            description = "account 支持用户名或手机号；encryptedPassword 为 RSA 加密后的 Base64 字符串。"
                    + "连续密码错误 5 次将锁定账号 30 分钟。")
    public R<LoginResponse> loginByPassword(@Validated @RequestBody PasswordLoginRequest request) {
        return R.ok(passwordAuthService.loginByPassword(request));
    }

    @PostMapping("/password/set")
    @Operation(summary = "设置或修改登录密码",
            description = "需 JWT 鉴权。首次设密须传 username（全局唯一）及 encryptedPassword、encryptedConfirmPassword。"
                    + "已设密用户改密须额外传 encryptedOldPassword。所有密码字段均为 RSA 加密 Base64。")
    @SecurityRequirement(name = "Authorization")
    public R<Void> setPassword(@Validated @RequestBody PasswordSetRequest request) {
        LoginUser loginUser = LoginUserHolder.require();
        passwordAuthService.setPassword(loginUser.getUserId(), request);
        return R.ok();
    }

    @PostMapping("/password/reset")
    @Operation(summary = "短信验证码重置密码",
            description = "忘记密码场景：须账号已设置过登录密码；未设密用户请验证码登录后调用 POST /password/set。"
                    + "先调用 POST /sms/send 获取验证码，再提交手机号、验证码及新密码（RSA 加密）。")
    public R<Void> resetPassword(@Validated @RequestBody PasswordResetRequest request) {
        passwordAuthService.resetPassword(request);
        return R.ok();
    }

    @GetMapping("/password/status")
    @Operation(summary = "查询是否已设置登录密码",
            description = "需 JWT 鉴权。返回 passwordSet 及 usernameMask（已设密时）。")
    @SecurityRequirement(name = "Authorization")
    public R<PasswordStatusResponse> passwordStatus() {
        LoginUser loginUser = LoginUserHolder.require();
        return R.ok(passwordAuthService.getPasswordStatus(loginUser.getUserId()));
    }
}
