package com.njzscloud.common.security.module.wechat.mini;

import cn.hutool.core.util.StrUtil;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.core.jackson.Jackson;
import com.njzscloud.common.security.ex.UserLoginException;
import com.njzscloud.common.security.module.password.PasswordLoginForm;
import com.njzscloud.common.security.support.LoginForm;
import com.njzscloud.common.security.support.LoginPreparer;
import com.njzscloud.common.wechat.WechatUtil;
import com.njzscloud.common.wechat.param.Code2SessionParam;
import com.njzscloud.common.wechat.result.Code2SessionResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;

import static com.njzscloud.common.security.contant.Constants.LOGIN_WECHAT_URL;

/**
 * 验证码登录，登录参数处理器
 */
@Slf4j
public class WechatMiniLoginPreparer implements LoginPreparer {
    private static final AntPathRequestMatcher matcher = new AntPathRequestMatcher(LOGIN_WECHAT_URL, "POST");

    /**
     * 创建登录参数
     *
     * @param request 请求信息
     * @return 登录参数 {@link PasswordLoginForm}
     */
    @Override
    public LoginForm createLoginForm(HttpServletRequest request) {
        try (ServletInputStream inputStream = request.getInputStream()) {
            WechatMiniLoginForm loginForm = Jackson.toBean(inputStream, WechatMiniLoginForm.class);
            log.info("微信小程序登录表单：{}", Jackson.toJsonStr(loginForm));
            String code = loginForm.getCode();
            if (StrUtil.isBlank(code)) {
                throw new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "微信验证码不能为空");
            }
            Code2SessionResult code2SessionResult = WechatUtil.code2Session(new Code2SessionParam().setJs_code(code));
            Integer errcode = code2SessionResult.getErrcode();
            if (errcode != null && errcode != 0) {
                log.error("微信登录失败, errcode: {}, errmsg: {}", errcode, code2SessionResult.getErrmsg());
                throw new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "微信登录失败");
            }
            String openid = code2SessionResult.getOpenid();
            String unionid = code2SessionResult.getUnionid();
            return loginForm.setOpenid(openid)
                    .setUnionid(unionid);
        } catch (Exception e) {
            throw new UserLoginException(e, ExceptionMsg.SYS_ERR_MSG, "登录表单解析失败");
        }
    }

    /**
     * 是否支持当前登录方式
     *
     * @param request 请求信息
     * @return 当请求方式为 POST 且路径为 /auth/login 时返回 true
     */
    @Override
    public boolean support(HttpServletRequest request) {
        return matcher.matches(request);
    }

}
