package com.skr.mdm.authentication.user.sms;

import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import com.skr.mdm.enums.MdmEncryptEnum;
import com.skr.mdm.util.SmUtils;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class SmsAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public static final String SPRING_SECURITY_FORM_SMS_CODE_KEY = "SMSCode";
    public static final String PHONE = "phone";
    public static final String COMPANY_ID = "companyId";
    public static final String IMEI = "imei";
    public static final String OAID = "oaid";
    public static final String UUID = "uuid";

    public static final String SECRET_KEY = "secretKey";

    private SM4 sm4 = null;

    private String mdmEncrypt;

    public SmsAuthenticationFilter() {
        super(new AntPathRequestMatcher("/sms/login", HttpMethod.POST.name()));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if (Boolean.TRUE && !request.getMethod().equals(HttpMethod.POST.name())) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            obtainSecretKey(request);
        }
        String smsCode = obtainSmsCode(request);
        String phone = obtainPhone(request);
        String imei = obtainImei(request);
        String oaid = obtainOaid(request);
        String uuid = obtainUuid(request);
        String companyId = obtainCompanyId(request);
        if (phone == null) {
            phone = "";
        }

        if (smsCode == null) {
            smsCode = "";
        }

        if (imei == null) {
            imei = "";
        }

        if (oaid == null) {
            oaid = "";
        }

        if (uuid == null) {
            uuid = "";
        }

        SmsAuthenticationToken authRequest = new SmsAuthenticationToken(phone, smsCode, imei, oaid, uuid, companyId);

        setDetails(request, authRequest);

        return this.getAuthenticationManager().authenticate(authRequest);
    }

    @Nullable
    protected String obtainSmsCode(HttpServletRequest request) {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            return sm4.decryptStr(request.getParameter(SPRING_SECURITY_FORM_SMS_CODE_KEY));
        }
        return request.getParameter(SPRING_SECURITY_FORM_SMS_CODE_KEY);
    }

    @Nullable
    protected String obtainPhone(HttpServletRequest request) {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            return sm4.decryptStr(request.getParameter(PHONE));
        }
        return request.getParameter(PHONE);
    }

    @Nullable
    protected String obtainCompanyId(HttpServletRequest request) {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            return sm4.decryptStr(request.getParameter(COMPANY_ID));
        }
        return request.getParameter(COMPANY_ID);
    }


    @Nullable
    protected String obtainImei(HttpServletRequest request) {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            return sm4.decryptStr(request.getParameter(IMEI));
        }
        return request.getParameter(IMEI);
    }

    @Nullable
    protected String obtainOaid(HttpServletRequest request) {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            return sm4.decryptStr(request.getParameter(OAID));
        }
        return request.getParameter(OAID);
    }

    @Nullable
    protected String obtainUuid(HttpServletRequest request) {
        if (MdmEncryptEnum.SM.getMdmEncrypt().equals(mdmEncrypt)) {
            return sm4.decryptStr(request.getParameter(UUID));
        }
        return request.getParameter(UUID);
    }

    @Nullable
    protected String obtainSecretKey(HttpServletRequest request) {
        String secretKey = request.getHeader(SECRET_KEY);
        SM2 sm2 = SmUtils.sm2Sign();
        byte[] secretKeyBytes = sm2.decrypt(secretKey, KeyType.PrivateKey);
        sm4 = SmUtil.sm4(secretKeyBytes);
        return request.getHeader(SECRET_KEY);
    }


    protected void setDetails(HttpServletRequest request,
                              SmsAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    public void setMdmEncrypt(String mdmEncrypt) {
        this.mdmEncrypt = mdmEncrypt;
    }
}