package org.security.auth.service;

import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.security.auth.config.XYunProperties;
import org.security.common.constant.CommonConstant;
import org.security.desk.xyun.res.AuthResponse;
import org.security.desk.xyun.res.AuthToken;
import org.security.desk.xyun.res.AuthUser;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.util.HashMap;

@Service
@AllArgsConstructor
@Slf4j
public class IXYunAuthServiceImpl implements IXYunAuthService {
	private final XYunProperties xYunProperties;
	private final BladeRedis bladeRedis;

	@Override
	public R getAccessToken() {
		String redisToken = bladeRedis.get(CommonConstant.XYUN_ACCESSTOKEN_REDIS_KEY);
		if (!Func.isNull(redisToken) && !Func.isEmpty(redisToken)) {
			AuthToken authToken = new AuthToken();
			authToken.setAccessToken(redisToken);
			authToken.setRefreshToken(bladeRedis.get(CommonConstant.XYUN_REFRESHTOKEN_REDIS_KEY));
			return R.data(authToken);
		}
		SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
		factory.setReadTimeout(10000);
		factory.setConnectTimeout(10000);
		RestTemplate template = new RestTemplate(factory);

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
		headers.add("Accept", MediaType.APPLICATION_JSON.toString());

		HashMap<String, Object> tokenMap = new HashMap<>();
		tokenMap.put("appId", xYunProperties.getAppId());
		tokenMap.put("secret", xYunProperties.getAppSecret());
		tokenMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
		tokenMap.put("scope", "app");
		HttpEntity<HashMap<String, Object>> tokenHttpEntity = new HttpEntity<>(tokenMap, headers);
		ParameterizedTypeReference<AuthResponse<AuthToken>> tokenTypeRef =
			new ParameterizedTypeReference<AuthResponse<AuthToken>>() {
			};
		AuthResponse<AuthToken> tokenResponse;
		String tokenUrl = xYunProperties.getUrl() + "/gateway/oauth2/token/getAccessToken";
		log.info(">>>>>> 获取token url：" + tokenUrl);
		try {
			tokenResponse = template.exchange(tokenUrl, HttpMethod.POST, tokenHttpEntity, tokenTypeRef).getBody();
		} catch (ResourceAccessException e) {
			return R.fail("香云登录失败，获取accessToken超时，url：" + tokenUrl);
		}
		if (!tokenResponse.isSuccess()) {
			return R.fail("香云登录失败，香云获取token失败，错误码：" + tokenResponse.getErrorCode());
		}
		AuthToken authToken = tokenResponse.getData();
		bladeRedis.setEx(CommonConstant.XYUN_ACCESSTOKEN_REDIS_KEY, authToken.getAccessToken(), Duration.ofSeconds(authToken.getExpireIn()));
		bladeRedis.setEx(CommonConstant.XYUN_REFRESHTOKEN_REDIS_KEY, authToken.getRefreshToken(), Duration.ofSeconds(authToken.getExpireIn()));
		return R.data(authToken);
	}

	@Override
	public R getUserInfo(String ticket, String accessToken) {
		SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
		factory.setReadTimeout(10000);
		factory.setConnectTimeout(10000);
		RestTemplate template = new RestTemplate(factory);

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
		headers.add("Accept", MediaType.APPLICATION_JSON.toString());
		HashMap<String, Object> userMap = new HashMap<>();
		userMap.put("appid", xYunProperties.getAppId());
		userMap.put("ticket", ticket);
		log.info(">>>>>> 获得香云accessToken成功：" + accessToken);
		HttpEntity<HashMap<String, Object>> userHttpEntity = new HttpEntity<>(userMap, headers);
		ParameterizedTypeReference<AuthResponse<AuthUser>> userTypeRef =
			new ParameterizedTypeReference<AuthResponse<AuthUser>>() {
			};
		AuthResponse<AuthUser> userResponse;
		String userUrl = xYunProperties.getUrl() + "/gateway/ticket/user/acquirecontext?accessToken=" + accessToken;
		log.info(">>>>>> 获取user url：" + userUrl);
		try {
			userResponse = template.exchange(userUrl, HttpMethod.POST, userHttpEntity, userTypeRef).getBody();
		} catch (ResourceAccessException e) {
			return R.fail("香云登录失败，获取用户信息超时，url：" + userUrl);
		}
		log.info(JSONObject.toJSONString(userResponse));
		if (!userResponse.isSuccess()) {
			return R.fail("香云登录失败，香云获取用户信息失败，错误码："
				+ userResponse.getErrorCode() + "; " + userResponse.getError());
		}
		return R.data(userResponse.getData());
	}
}
