package com.yifu.cloud.plus.v1.yifu.auth.filter;

import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yifu.cloud.plus.v1.yifu.auth.config.CASproperties;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.security.token.CasAuthenticationToken;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.*;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author fxj *
 * @date 2022年05月27日 11:14
 * @description
 */
@Slf4j
@Data
@Order(-1)
@RequiredArgsConstructor
public class PasswordDecoderFilter extends UsernamePasswordAuthenticationFilter {

	private static final String KEY_ALGORITHM = "AES";
	/**
	 * 解密登录前端密码 秘钥
	 */
	private String encodeKey = "thanks,yifucloud";

	private boolean postOnly = true;

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		if (this.postOnly && !request.getMethod().equals("POST")) {
			throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
		} else {
			AbstractAuthenticationToken authRequest;
			String casResult = request.getParameter("cas");
			if (Common.isNotNull(casResult)) {
				String ldapName = "";
				try {
					RestTemplate restTemplate = new RestTemplate();
					HttpHeaders headers = new HttpHeaders();
					headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
					MultiValueMap<String,Object> wholeForm = new LinkedMultiValueMap<>();
					wholeForm.add("service", CASproperties.CLIENT_LOGIN_PAGE);
					HttpEntity<MultiValueMap<String,Object>> entity = new org.springframework.http.HttpEntity<>(wholeForm,headers);
					ResponseEntity<String> obj = restTemplate.exchange(CASproperties.SPRING_SECURITY_CAS_SERVER + "/" + casResult, HttpMethod.POST, entity, String.class);

					if (obj.getStatusCode().value() == 200) {
						String st = obj.getBody();
						log.info("Successful service ticket request: " + st);
						wholeForm.clear();
						wholeForm.add("service", CASproperties.CLIENT_LOGIN_PAGE);
						wholeForm.add("ticket", st);
						obj = restTemplate.exchange(CASproperties.CAS_SERVER_PATH + "/p3/serviceValidate?service=" + CASproperties.CLIENT_LOGIN_PAGE + "&ticket=" + st + "&format=JSON"
								, HttpMethod.GET,entity, String.class);
						log.info("cas返回用户信息》》》", JSON.toJSONString(obj));
						if(obj.getStatusCode().value() == 200){
							try {
								JSONObject result = JSON.parseObject(obj.getBody());
								ldapName = result.getJSONObject("serviceResponse").getJSONObject("authenticationSuccess").getString("user");
							}catch (Exception var6){
								throw new AuthenticationServiceException("验证失败！统一用户中心未正确获得用户信息！");
							}
						}
					}
				} catch (Exception e) {
					log.error(e.getMessage());
					throw new AuthenticationServiceException("验证失败！");
				}
				authRequest = new CasAuthenticationToken(ldapName, null);
			} else {
				String username = this.obtainUsername(request);
				username = username != null ? username : "";
				username = username.trim();
				String password = this.obtainPassword(request);
				password = password != null ? decryptAES(password) : "";
				authRequest = new UsernamePasswordAuthenticationToken(username, password);
				setDetails(request, authRequest);
			}
			return this.getAuthenticationManager().authenticate(authRequest);
		}
	}

	/**
	 * 原文解密
	 * @return
	 */
	private String decryptAES(String password) {
		// 构建前端对应解密AES 因子
		AES aes = new AES(Mode.CFB, Padding.NoPadding,
				new SecretKeySpec(encodeKey.getBytes(), KEY_ALGORITHM),
				new IvParameterSpec(encodeKey.getBytes()));
		// 解密
		return  aes.decryptStr(password);
	}

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