package com.keao.edu.auth.core.filter;

import com.keao.edu.auth.api.entity.LoginEntity;
import com.keao.edu.auth.api.util.SecurityConstants;
import com.keao.edu.auth.config.token.PhoneAuthenticationToken;
import com.keao.edu.datasource.DataSourceContextHolder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AbstractAuthenticationToken;
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.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class PhoneLoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

	private static final String SPRING_SECURITY_RESTFUL_PHONE_KEY = "phone";
	private static final String SPRING_SECURITY_RESTFUL_VERIFY_CODE_KEY = "smsCode";
	private static final String clientIdParameter = "clientId";
	private static final String tenantIdParameter = "tenantId";
	private static final String registerFlagParameter = "registerFlag";
	private static final String organIdParameter = "organId";

	private static final String SPRING_SECURITY_RESTFUL_LOGIN_URL = "/smsLogin";
	private boolean postOnly = true;

	public PhoneLoginAuthenticationFilter() {
		super(new AntPathRequestMatcher(SPRING_SECURITY_RESTFUL_LOGIN_URL, "POST"));
	}

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		if (postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		}
		
		String tenantId = request.getHeader(tenantIdParameter);
		if (StringUtils.isBlank(tenantId)) {
			tenantId = request.getParameter(tenantIdParameter);
		}
		if(StringUtils.isBlank(tenantId)){
			tenantId = DataSourceContextHolder.TENANT_ID;
		}
		
		DataSourceContextHolder.setDataSourceKey(tenantId);

		AbstractAuthenticationToken authRequest;
		// 手机验证码登陆
		String principal = obtainParameter(request, SPRING_SECURITY_RESTFUL_PHONE_KEY);
		String credentials = obtainParameter(request, SPRING_SECURITY_RESTFUL_VERIFY_CODE_KEY);

		String clientId = request.getParameter(clientIdParameter).toUpperCase();
		
		principal = principal.trim();

		LoginEntity loginEntity = new LoginEntity();
		loginEntity.setClientId(clientId);
		loginEntity.setPhone(principal);
		loginEntity.setSmsCode(credentials);
		String organId = obtainParameter(request, organIdParameter);
		if(StringUtils.isNotEmpty(organId)){
			loginEntity.setOrganId(Integer.parseInt(organId));
		}
		loginEntity.setRegisterFlag(obtainParameter(request, registerFlagParameter));

		authRequest = new PhoneAuthenticationToken(SecurityConstants.PHONE_PRINCIPAL_PREFIX + principal, loginEntity);

		// Allow subclasses to set the "details" property
		setDetails(request, authRequest);
		return this.getAuthenticationManager().authenticate(authRequest);
	}

	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
			throws IOException, ServletException {
		super.successfulAuthentication(request, response, chain, authResult);
		// chain.doFilter(request, response);
	}

	private void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) {
		authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
	}

	private String obtainParameter(HttpServletRequest request, String parameter) {
		String result = request.getParameter(parameter);
		return result == null ? "" : result;
	}

}
