package com.yonge.cooleshow.auth.core.handler;

import java.io.IOException;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yonge.cooleshow.auth.config.RongCloudConfig;
import com.yonge.cooleshow.common.entity.ImResult;
import com.yonge.cooleshow.common.entity.ImUserModel;
import com.yonge.cooleshow.common.exception.BizException;
import io.rong.models.response.TokenResult;
import io.rong.models.user.UserModel;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.auth.api.entity.SysUserLogin;
import com.yonge.cooleshow.auth.api.entity.SysUserLoginLog;
import com.yonge.cooleshow.auth.service.SysUserLoginLogService;
import com.yonge.cooleshow.auth.service.SysUserLoginService;
import com.yonge.cooleshow.auth.service.SysUserService;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.security.SecurityConstants;

@Component
public class BaseAuthenticationSuccessEventHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	@Autowired
	private SysUserLoginService sysUserLoginService;
	@Autowired
	private SysUserLoginLogService sysUserLoginLogService;
	@Autowired
	private SysUserService sysUserService;
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private ClientDetailsService clientDetailsService;

	@Autowired
	private AuthorizationServerTokenServices defaultAuthorizationServerTokenServices;

	private final static Logger logger = LoggerFactory.getLogger(BaseAuthenticationSuccessEventHandler.class);

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication){
		
		String clientId = request.getParameter("clientId");
		String clientSecret = request.getParameter("clientSecret");
		if (clientId == null || clientSecret == null) {
			throw new UnapprovedClientAuthenticationException("请求头中client信息为空");
		}
		
		logger.info("用户：{} 登录成功", authentication.getPrincipal());
		HashMap<String,String> hashMap = objectMapper.convertValue(authentication.getPrincipal(), HashMap.class);
		String username = hashMap.get("username");
		SysUser sysUser;
		if(username.startsWith(SecurityConstants.USERNAME_PRINCIPAL_PREFIX)){
			sysUser = sysUserService.queryByUsername(username.split(":")[1]);
		}else {
			sysUser = sysUserService.queryLockByPhone(username.split(":")[1]);
		}
		if(StringUtils.isEmpty(sysUser.getImToken())){
			String name = sysUser.getRealName();
			if(StringUtils.isEmpty(name)){
				name = sysUser.getUsername();
			}
			try {
				TokenResult result = RongCloudConfig.rongCloud.user.register(new UserModel(sysUser.getId().toString(), name, sysUser.getAvatar()));
				if(!result.code.equals(200)){
					logger.error("获取用户token失败:{}",result.errorMessage);
				}
				sysUser.setImToken(result.getToken());
				sysUser.setUpdateTime(new Date());
				sysUserService.update(sysUser);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		Date date = new Date();
		//修改添加登录信息
		SysUserLogin userLogin = sysUserLoginService.findLoginByUserId(sysUser.getId());
		if(userLogin == null){
			userLogin = new SysUserLogin();
			userLogin.setLastLoginIp(request.getRemoteAddr());
			userLogin.setUserId(sysUser.getId());
			userLogin.setLoginCount(1);
			sysUserLoginService.insert(setUserLogin(userLogin,date));
		}else {
			userLogin.setLastLoginIp(request.getRemoteAddr());
			userLogin.setLoginCount(userLogin.getLoginCount() + 1);
			sysUserLoginService.update(setUserLogin(userLogin,date));
		}
		//添加登录日志
		SysUserLoginLog sysUserLoginLog = new SysUserLoginLog();
		sysUserLoginLog.setClientId(clientId);
		sysUserLoginLog.setLoginTime(date);
		sysUserLoginLog.setLoginIp(request.getRemoteAddr());
		sysUserLoginLog.setUserId(sysUser.getId());
		sysUserLoginLogService.insert(sysUserLoginLog);
		
		try {
			String base64ClientCredentials = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes());
			HttpHeaders headers = new HttpHeaders();
			headers.add("Authorization", "Basic " + base64ClientCredentials);
			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

			ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
			TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId, clientDetails.getScope(), "password");
			OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

			OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
			OAuth2AccessToken oAuth2AccessToken = defaultAuthorizationServerTokenServices.createAccessToken(oAuth2Authentication);
			logger.info("获取token 成功：{}", oAuth2AccessToken.getValue());
			Map<String,Object> map = new HashMap<>(3);
			map.put("password", StringUtils.isEmpty(sysUser.getPassword())?false:true);
			map.put("authentication",oAuth2AccessToken);
			
			response.setContentType("application/json; charset=utf-8");
			HttpResponseResult result = new HttpResponseResult(true, HttpStatus.OK.value(), map, "");
			response.getWriter().write(objectMapper.writeValueAsString(result));
		} catch (IOException e) {
			throw new BadCredentialsException("Failed to decode basic authentication token");
		}
	}

	private SysUserLogin setUserLogin(SysUserLogin userLogin,Date date){
		userLogin.setFailCount(0);
		userLogin.setLastLoginTime(date);
		return userLogin;
	}

}
