package com.tuoheng.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tuoheng.constants.OidcConstant;
import com.tuoheng.constants.ThirdConstant;
import com.tuoheng.exception.DiyException;
import com.tuoheng.mapper.RegisteredClientMapper;
import com.tuoheng.model.dto.ClientRoleDto;
import com.tuoheng.model.po.RegisteredClientPo;
import com.tuoheng.model.po.UserPo;
import com.tuoheng.model.result.ProfileResult;
import com.tuoheng.model.result.TokenResult;
import com.tuoheng.service.ThirdService;
import com.tuoheng.until.HttpUtils;
import com.tuoheng.until.JsonResult;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.rmi.ServerException;
import java.util.Base64;
import java.util.List;

/**
 * @Author xiaoying
 * @Date 2023/11/11 10:19
 */
@Service
public class ThirdServiceImpl implements ThirdService {


    @Autowired
    private RestTemplate restTemplate;

    @Value("${oauth2.token.issuer}")
    private String tokenIssuer;
    @Autowired
    private RegisteredClientMapper registeredClientMapper;


    /**
     * 根据第三方授权验证token 进行获取用户信息并跳转相关地址
     *
     * @param clientId 平台标识
     * @return
     */
    @Override
    public JsonResult authorize(String clientId) {
        String username;
        String password;
        if(ThirdConstant.TUOHENG_AIRPORT_ADMIN.equals(clientId)){
            username = ThirdConstant.GZJJ_USERNAME;
            password = ThirdConstant.GZJJ_PASSWORD;
        }else if(ThirdConstant.TUOHENG_TELECOMUMALE_ADMIN.equals(clientId)){
            username = ThirdConstant.HLCG_USERNAME;
            password = ThirdConstant.HLCG_PASSWORD;
        }else {
            return JsonResult.error("clientId error");
        }

        //通过oidc的密码模式获取授权token 等相关信息数据
        TokenResult tokenResult = getToken(clientId,username,password);
        tokenResult.setUserName(username);
        //此时通过token获取当前用户的相关权限信息并进行封装
        tokenResult = getClientResult(tokenResult, clientId, username);
        //数据封装完毕返回数据 以及相关地址 -> 是否重定向
        return JsonResult.success(tokenResult);
    }

    /**
     * 通过账号密码获取token
     */
    private TokenResult getToken(String clientId, String username, String password) {

        RegisteredClientPo clientPo = registeredClientMapper.selectClient(clientId);
        if (ObjectUtils.isEmpty(clientPo)) {
            throw new DiyException("该clientId不存在本系统中");
        }

        String url = tokenIssuer + OidcConstant.OAUTH2_TOKEN;
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("password", password);
        //定死账号密码
        params.add("username", username);
        params.add("grant_type", "password");
        params.add("scope", "openid profile");
        //机场标识
        String clientSecret = clientPo.getClientSecret().split("}")[1];
        String userMsg = clientPo.getClientId() + ":" + clientSecret;
        String authorization = Base64.getEncoder().encodeToString(userMsg.getBytes());

        ParameterizedTypeReference<TokenResult> parameterizedTypeReference =
                new ParameterizedTypeReference<TokenResult>() {
                };

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Authorization", "Basic " + authorization);
        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity(params, headers);

        ResponseEntity<TokenResult> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, parameterizedTypeReference);
        return response.getBody();
    }

    /**
     * 获取对应用户的相关信息
     *
     * @param tokenResult
     * @return
     */
    private TokenResult getClientResult(TokenResult tokenResult, String clientId, String username) {

        String url = tokenIssuer + OidcConstant.GET_USERINFO;

        ParameterizedTypeReference<JsonResult<TokenResult>> parameterizedTypeReference =
                new ParameterizedTypeReference<JsonResult<TokenResult>>() {
                };

        HttpHeaders header = new HttpHeaders();
        header.add("Authorization", "Bearer " + tokenResult.getAccess_token());
        JSONObject object = new JSONObject();
        object.put("username", tokenResult.getUserName());
        HttpEntity httpEntity = new HttpEntity(object, header);

        ResponseEntity<JsonResult<TokenResult>> exchange = restTemplate.exchange(url, HttpMethod.POST, httpEntity, parameterizedTypeReference);

        TokenResult result = exchange.getBody().getData();
        //封装数据
        List<String> authorityList = result.getAuthorityList();
        List<ClientRoleDto> clientRoleDtoList = result.getClientRoleDtoList();
        tokenResult.setAuthorityList(authorityList);
        tokenResult.setClientRoleDtoList(clientRoleDtoList);
        tokenResult.setSub(result.getUserName());
        tokenResult.setUserId(result.getUserId());
        tokenResult.setUserName(result.getUserName());
        ProfileResult profile = new ProfileResult();
        BeanUtils.copyProperties(tokenResult, profile);
        profile.setSub(username);
        profile.setAzp(clientId);
        profile.setAuthority(authorityList);
        profile.setClientRoleList(clientRoleDtoList);
        tokenResult.setProfile(profile);

        return tokenResult;

    }
}
