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

import com.keao.edu.auth.api.dto.SysUserInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

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.auth.service.SysUserService;
import com.keao.edu.common.service.IdGeneratorService;

public class PhoneAuthenticationProvider extends AbstractAuthenticationProvider {

	private UserDetailsService userDetailsService;

	private IdGeneratorService smsCodeService;

	private SysUserService sysUserService;

	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails, Authentication authentication) throws AuthenticationException {

		if (authentication.getCredentials() == null) {
			throw new BadCredentialsException(this.messages.getMessage("PhoneAuthenticationProvider.badCredentials", "Bad credentials"));
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	protected UserDetails retrieveUser(String phone, Authentication authentication) throws AuthenticationException {

		LoginEntity loginEntity = (LoginEntity) authentication.getCredentials();
		if (loginEntity == null) {
			throw new BadCredentialsException("Bad credentials");
		}

		String smsCode = loginEntity.getSmsCode();

		SysUserInfo userInfo = sysUserService.queryUserInfoByPhone(loginEntity.getPhone());
		if (userInfo == null && StringUtils.isNotEmpty(loginEntity.getRegisterFlag())) {
			sysUserService.initUser(loginEntity);
		}

		// 验证码验证
		boolean b = smsCodeService.verifyValidCode(StringUtils.substringAfter(phone, SecurityConstants.PHONE_PRINCIPAL_PREFIX), smsCode);
		if (!b) {
			throw new BadCredentialsException("验证码校验失败");
		}

		UserDetails loadedUser;
		try {
			loadedUser = userDetailsService.loadUserByUsername(phone);
		} catch (UsernameNotFoundException e) {
			throw e;
		} catch (Exception e) {
			throw new InternalAuthenticationServiceException(e.getMessage(), e);
		}

		if (loadedUser == null) {
			throw new InternalAuthenticationServiceException("账户不存在");
		} else {
			return loadedUser;
		}
	}

	@Override
	protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
		PhoneAuthenticationToken result = new PhoneAuthenticationToken(principal, authentication.getCredentials(), user.getAuthorities());
		result.setDetails(authentication.getDetails());
		return result;
	}

	@Override
	public boolean supports(Class<?> aClass) {
		return PhoneAuthenticationToken.class.isAssignableFrom(aClass);
	}

	public void setUserDetailsService(UserDetailsService userDetailsService) {
		this.userDetailsService = userDetailsService;
	}

	public void setSysUserService(SysUserService sysUserService) {
		this.sysUserService = sysUserService;
	}

	public void setSmsCodeService(IdGeneratorService smsCodeService) {
		this.smsCodeService = smsCodeService;
	}
}
