package org.security.trans.common.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.security.common.config.AppOauth2Propertis;
import org.security.system.user.entity.User;
import org.security.system.user.vo.UserVO;
import org.security.trans.common.dto.AccessTokenDTO;
import org.security.trans.common.dto.AuthResult;
import org.security.trans.common.dto.UserDetailDTO;
import org.security.trans.common.service.Oauth2Service;
import org.security.trans.feign.UserFeignClient;
import org.springblade.core.launch.constant.TokenConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.secure.TokenInfo;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author zj 2022/7/4
 */
@Slf4j
@AllArgsConstructor
@Service
public class Oauth2ServiceImpl implements Oauth2Service {

	private final AppOauth2Propertis appOauth2Propertis;
	private final UserFeignClient userFeignClient;

	@Override
	public String appOauth(HttpServletRequest request) {
		log.info("================app端单点登录授权开始================");
		String ticket = request.getParameter("ticket");
		//1.获取accesstok
		String accessToken = getAccessToken();
		if (StringUtils.isBlank(accessToken)) {
			return "获取授权失败";
		}
		//2.获取用户上线文信息
		UserDetailDTO userDetailDTO = getUserContext(ticket, accessToken);
		if (Objects.isNull(userDetailDTO)) {
			return "获取用户信息失败";
		}
		//3.对比用户
		User user = new User();
		user.setRealName(user.getName());
		R<UserVO> detailResult = userFeignClient.detail(user);
		if (!detailResult.isSuccess()) {
			return "获取用户信息失败";
		}
		UserVO userVO = detailResult.getData();
		if (Objects.isNull(userVO)) {
			return "系统不存在当前用户";
		}
		TokenInfo jwt = SecureUtil.createJWT(getTokenMap(userVO), "app", "security", "access_token");
		log.info("================app端单点登录授权结束================");
		return "redirect:" +
			appOauth2Propertis.getAppIndexUrl() +
			"?ticket=" + ticket +
			"&token=" + jwt.getToken();

	}

	@Override
	public String pcOauth() {
		return null;
	}

	private UserDetailDTO getUserContext(String ticket, String accessToken) {
		HashMap<String, String> userContextMap = new HashMap<>(2);
		userContextMap.put("appid", appOauth2Propertis.getAppId());
		userContextMap.put("ticket", ticket);
		String getUserStr = JSON.toJSONString(userContextMap);
		log.info("================获取用户上下文信息：{}================", getUserStr);
		HttpRequest userPost = HttpUtil.createPost(appOauth2Propertis.getUserContextUrl() + "?accessToken=" + accessToken);
		HttpRequest httpRequest = userPost.body(getUserStr, "application/json");
		HttpResponse httpResponse = httpRequest.execute();
		if (!httpResponse.isOk()) {
			throw new ServiceException("获取用户信息上下文失败");
		}
		String userContext = httpResponse.body();
		AuthResult<UserDetailDTO> authResult = JSON.parseObject(userContext, new TypeReference<AuthResult<UserDetailDTO>>() {
		});
		return authResult.getData();
	}

	private String getAccessToken() {
		HashMap<String, String> tokenMap = new HashMap<>(4);
		tokenMap.put("appId", appOauth2Propertis.getAppId());
		tokenMap.put("secret", appOauth2Propertis.getSecret());
		tokenMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
		tokenMap.put("scope", "app");
		String accessTokenBodyJson = JSON.toJSONString(tokenMap);
		log.info("================获取accessToken：{}================", accessTokenBodyJson);
		HttpRequest post = HttpUtil.createPost(appOauth2Propertis.getAccessTokenUrl());
		post.body(accessTokenBodyJson, "application/json");
		HttpResponse response = post.execute();
		if (!response.isOk()) {
			throw new ServiceException("获取accsssToken失败");
		}
		String accessTokenBody = response.body();
		AuthResult<AccessTokenDTO> accessTokenResult = JSON.parseObject(accessTokenBody, new TypeReference<AuthResult<AccessTokenDTO>>() {
		});
		return accessTokenResult.getData().getRefreshToken();
	}

	private Map<String, Object> getTokenMap(UserVO userVO) {
		Map<String, Object> info = new HashMap<>(16);
		info.put(TokenConstant.CLIENT_ID, "app");
		info.put(TokenConstant.USER_ID, Func.toStr(userVO.getId()));
		info.put(TokenConstant.DEPT_ID, Func.toStr(userVO.getDeptId()));
		info.put(TokenConstant.POST_ID, Func.toStr(userVO.getPostId()));
		info.put(TokenConstant.ROLE_ID, Func.toStr(userVO.getRoleId()));
		info.put(TokenConstant.TENANT_ID, userVO.getTenantId());
		info.put(TokenConstant.OAUTH_ID, "");
		info.put(TokenConstant.ACCOUNT, userVO.getAccount());
		info.put(TokenConstant.USER_NAME, userVO.getRealName());
		info.put(TokenConstant.NICK_NAME, userVO.getName());
		info.put(TokenConstant.REAL_NAME, userVO.getRealName());
		info.put(TokenConstant.ROLE_NAME, userVO.getRoleName());
		info.put(TokenConstant.AVATAR, userVO.getAvatar());
		info.put(TokenConstant.DETAIL, "web");
		info.put(TokenConstant.LICENSE, "security");
		return info;
	}
}
