package com.ym.mec.auth.core.provider;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException;
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.ym.mec.auth.api.dto.SysUserInfo;
import com.ym.mec.auth.api.entity.LoginEntity;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.auth.api.entity.SysUserDevice;
import com.ym.mec.auth.config.token.PhoneAuthenticationToken;
import com.ym.mec.auth.service.SysUserDeviceService;
import com.ym.mec.auth.service.SysUserService;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.service.IdGeneratorService;

public class PhoneAuthenticationProvider extends AbstractAuthenticationProvider {

	private UserDetailsService userDetailsService;

	private IdGeneratorService smsCodeService;

	private SysUserService sysUserService;
	
	private SysUserDeviceService sysUserDeviceService;
	
	@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 username, Authentication authentication) throws AuthenticationException {

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

		String smsCode = loginEntity.getSmsCode();
		
		String phone = loginEntity.getPhone();

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

		String clientId = loginEntity.getClientId();

		Boolean isRegister = loginEntity.getIsRegister();
		
		String deviceNum = loginEntity.getDeviceNum();

		SysUserInfo userInfo = sysUserService.queryUserInfoByPhone(phone);

		if (userInfo == null) {
			if (isRegister == false || StringUtils.equals("SYSTEM", clientId)) {
				throw new LockedException("用户不存在");
			}
			if (StringUtils.isNotBlank(deviceNum) && !StringUtils.equals("STUDENT", clientId)) {
				// 检查设备
				List<SysUserDevice> sysUserDeviceList = sysUserDeviceService.queryByDeviceNum(deviceNum);

				if (sysUserDeviceList != null && sysUserDeviceList.size() > 0) {
					throw new BadCredentialsException("当前设备已绑定账号，请更换设备");
				}

				userInfo = sysUserService.initUser(loginEntity.getPhone(), clientId);

				SysUserDevice sysUserDevice = new SysUserDevice();
				sysUserDevice.setUserId(userInfo.getSysUser().getId());
				sysUserDevice.setDeviceNum(deviceNum);
				sysUserDevice.setBindTime(new Date());
				sysUserDeviceService.insert(sysUserDevice);
			} else {
				userInfo = sysUserService.initUser(loginEntity.getPhone(), clientId);
			}
		} else {
			SysUser user = userInfo.getSysUser();
			if (user == null) {
				throw new LockedException("用户不存在");
			}
			if (StringUtils.isNotBlank(deviceNum) && !StringUtils.equals("STUDENT", clientId)) {
				// 检查设备
				try {
					sysUserDeviceService.bindDevice(user.getId(), deviceNum);
				} catch (Exception e) {
					throw new BadCredentialsException("当前设备已绑定账号，请更换设备");
				}
			}
			if (!userInfo.getSysUser().getUserType().contains(clientId)) {
				if (isRegister == false || StringUtils.equals("SYSTEM", clientId)) {
					throw new LockedException("用户不存在");
				} else {
					user.setUserType(user.getUserType() + "," + clientId);
					user.setUpdateTime(new Date());

					// 添加userType以及附加信息
					if (StringUtils.equals("STUDENT", clientId)) {
						user.setOrganId(sysUserService.getLesseeOrganId());
						sysUserService.saveStudent(user.getId());
					} else if (StringUtils.equals("TEACHER", clientId)) {
						sysUserService.saveTeacher(user.getId());
					}
					sysUserService.update(user);
				}
			}
		}

		UserDetails loadedUser;
		try {
			loadedUser = userDetailsService.loadUserByUsername(username);
		} 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;
	}

	public void setSysUserDeviceService(SysUserDeviceService sysUserDeviceService) {
		this.sysUserDeviceService = sysUserDeviceService;
	}
}
