package ink.wgink.login.oauth2.server.service.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import ink.wgink.login.oauth2.server.exceptions.OAuth2ClientExpireException;
import ink.wgink.login.oauth2.server.exceptions.OAuth2ClientStateException;
import ink.wgink.login.oauth2.server.pojo.pos.OAuth2ClientPO;
import ink.wgink.login.oauth2.server.service.IOAuth2ClientService;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: OauthClientDetailsService
 * @Description: Oauth客户端业务
 * @Author: WangGeng
 * @Date: 2020/7/22 8:03 下午
 * @Version: 1.0
 **/
@Primary
@Component
public class OAuth2ClientDetailsServiceImpl implements ClientDetailsService {
    private static final Logger LOG = LoggerFactory.getLogger(OAuth2ClientDetailsServiceImpl.class);
    @Autowired
    private IOAuth2ClientService oAuth2ClientService;

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        if (StringUtils.isBlank(clientId)) {
            throw new OAuth2ClientExpireException("客户端ID不能为空");
        }
        OAuth2ClientPO oAuth2ClientPO = oAuth2ClientService.getPO(clientId);
        if (oAuth2ClientPO == null) {
            throw new OAuth2ClientStateException("客户端不存在");
        }
        // 如果是第三方系统，判断到期时间
        if (StringUtils.equals(oAuth2ClientPO.getSystemType(), IOAuth2ClientService.OAUTH_CLIENT_SYSTEM_TYPE_THIRD)) {
            String expireTime = oAuth2ClientPO.getExpireTime();
            if (StringUtils.isBlank(oAuth2ClientPO.getSystemState())) {
                throw new OAuth2ClientStateException("客户端状态异常");
            }
            if (StringUtils.equals(oAuth2ClientPO.getSystemState(), IOAuth2ClientService.OAUTH_CLIENT_SYSTEM_STATE_LOCKING)) {
                throw new OAuth2ClientStateException("客户端锁定");
            }
            if (StringUtils.isBlank(oAuth2ClientPO.getExpireTime())) {
                throw new OAuth2ClientExpireException("客户端到期时间异常");
            }
            DateTime now = DateTime.now();
            DateTime expireTimeDateTime = DateTime.parse(expireTime, DateTimeFormat.forPattern("yyyy-MM-dd"));
            if (now.isAfter(expireTimeDateTime)) {
                throw new OAuth2ClientExpireException("客户端已过期");
            }
        }
        BaseClientDetails clientDetails = new BaseClientDetails(oAuth2ClientPO.getClientId(),
                oAuth2ClientPO.getResourceIds(),
                oAuth2ClientPO.getScope(),
                oAuth2ClientPO.getAuthorizedGrantTypes(),
                oAuth2ClientPO.getAuthorities());
        clientDetails.setAutoApproveScopes(Arrays.asList(oAuth2ClientPO.getAutoapprove().split(",")));
        clientDetails.setClientSecret(oAuth2ClientPO.getClientSecret());
        clientDetails.setAccessTokenValiditySeconds(oAuth2ClientPO.getAccessTokenValidity());
        clientDetails.setRefreshTokenValiditySeconds(oAuth2ClientPO.getRefreshTokenValidity());
        // 设置附加信息，json格式
        String additionalInformation = oAuth2ClientPO.getAdditionalInformation();
        if (!StringUtils.isBlank(additionalInformation)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                Map additionalInformationMap = objectMapper.readValue(additionalInformation, Map.class);
                clientDetails.setAdditionalInformation(additionalInformationMap);
            } catch (IOException e) {
                LOG.error(e.getMessage(), e);
            }
        }
        // 设置scope
        if (!StringUtils.isBlank(oAuth2ClientPO.getScope())) {
            clientDetails.setScope(org.springframework.util.StringUtils.commaDelimitedListToSet(oAuth2ClientPO.getScope()));
        }
        return clientDetails;
    }


}
