/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.security.api.filter;


import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.StrUtil;
import com.yami.shop.bean.enums.SmsType;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.config.WxConfig;
import com.yami.shop.security.api.model.YamiUser;
import com.yami.shop.security.api.service.YamiUserDetailsService;
import com.yami.shop.security.comment.enums.App;
import com.yami.shop.security.comment.exception.BadCredentialsException;
import com.yami.shop.security.comment.exception.UsernameNotFoundException;
import com.yami.shop.security.comment.filter.YamiAuthenticationProcessingFilter;
import com.yami.shop.security.comment.token.AuthenticationToken;
import com.yami.shop.service.SmsLogService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * 这里的登录，会有两种情况
 * 1. 账号密码 + 验证码登录
 * 2. 短信登陆
 *
 * 也就是说，只要是正常的登陆，一般都写在这里，
 * 而像微信小程序登陆，微信公众号登陆，qq登陆，新浪微博登陆，google账号登陆，facebook登陆，都在
 * com.yami.shop.security.api.filter.AppLoginAuthenticationFilter
 *
 * @author LGH
 */
@Component
public class LoginAuthenticationFilter extends YamiAuthenticationProcessingFilter {

    private final YamiUserDetailsService yamiUserDetailsService;

    private final PasswordEncoder passwordEncoder;

    private final SmsLogService smsLogService;

    private final WxConfig wxConfig;

    @Autowired
    public LoginAuthenticationFilter(YamiUserDetailsService yamiUserDetailsService, PasswordEncoder passwordEncoder, SmsLogService smsLogService, WxConfig wxConfig) {
        super("/login");
        this.yamiUserDetailsService = yamiUserDetailsService;
        this.passwordEncoder = passwordEncoder;
        this.smsLogService = smsLogService;
        this.wxConfig = wxConfig;
    }

    @Override
    protected UserDetails getUserDetails(AuthenticationToken authentication) {
//        // 验证码登录
//        if (Objects.equals(authentication.getLoginType(), 1)) {
//            if (!smsLogService.checkValidCode(authentication.getPrincipal(), String.valueOf(authentication.getCredentials()), SmsType.LOGIN)){
//                throw new GlobalException("验证码有误或已过期");
//            }
//        }
        // 验证码登录
        if (Objects.equals(authentication.getLoginType(), 1)) {
            boolean validCode;
            try {
                validCode = smsLogService.checkValidCode(authentication.getPrincipal(), String.valueOf(authentication.getCredentials()), SmsType.LOGIN);
            }catch (YamiShopBindException e){
                throw new GlobalException("验证码校验过频繁，请稍后再试");
            }
            if (!validCode){
                throw new GlobalException("验证码有误或已过期");
            }
        }
        // 用户名或手机号，一般的登陆都是通过Principal传过来的
        // 但是微信公众号支付，小程序支付都需要openid，如果单纯的使用账号密码登陆，会导致无法进行支付，所以要通过微信的code获取openId放到当前登录的用户上
        String userNameOrMobile = authentication.getPrincipal();
        String code = null;

        // 在
        if (Objects.equals(authentication.getAppType(), App.MINI.value())
         || Objects.equals(authentication.getAppType(), App.MP.value())) {

            if (!authentication.getPrincipal().contains(StrUtil.COLON)) {
                throw new GlobalException("登陆信息异常");
            }
            String[] principalInfo = authentication.getPrincipal().split(StrUtil.COLON);

            userNameOrMobile = principalInfo[0];
            code = principalInfo[1];
        }

        YamiUser user;
        try {
            user = yamiUserDetailsService.loadUserByMobileOrUserName(userNameOrMobile, authentication.getAppType(),authentication.getLoginType());
        } catch (UsernameNotFoundException var6) {
            throw new UsernameNotFoundException("账号或密码不正确");
        }
        if (!user.isEnabled()) {
            throw new UsernameNotFoundException("账号已被锁定,请联系管理员");
        }

        // 非验证码登录 也就是账号密码登录
        if (!Objects.equals(authentication.getLoginType(), 1)) {
            String encodedPassword = user.getPassword();
            String rawPassword = authentication.getCredentials().toString();
            // 密码不正确
            if (StrUtil.isBlank(encodedPassword) || !passwordEncoder.matches(rawPassword,encodedPassword)){
                throw new BadCredentialsException("账号或密码不正确");
            }
        }


        if (StrUtil.isNotBlank(code)) {
            try {
                // 小程序携带code登录
                if (Objects.equals(authentication.getAppType(), App.MINI.value())) {
                    WxMaJscode2SessionResult session = wxConfig.getWxMaService().getUserService().getSessionInfo(code);
                    user.setSessionKey(session.getSessionKey());
                    user.setBizUserId(session.getOpenid());
                }
                // 公众号携带code登录
                if (Objects.equals(authentication.getAppType(), App.MP.value())) {
//                    WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxConfig.getWxMpService().oauth2getAccessToken(code);
                    WxMpOAuth2AccessToken wxMpOAuth2AccessToken = wxConfig.getWxMpService().getOAuth2Service().getAccessToken(code);
                    user.setBizUserId(wxMpOAuth2AccessToken.getOpenId());
                }
            } catch (me.chanjar.weixin.common.error.WxErrorException e) {
                throw new GlobalException(e.getMessage());
            }
        }


        return user;
    }


}
