package com.cm.common.converter;

import com.cm.common.pojo.bos.UserBO;
import com.cm.common.pojo.bos.UserInfoBO;
import com.cm.common.utils.authority.AuthorityUtil;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @ClassName: UserAuthConverter
 * @Description: 重写用户认证
 * @Author: WangGeng
 * @Date: 2019/2/27 4:57 PM
 * @Version: 1.0
 **/
public class UserAuthConverter implements UserAuthenticationConverter {

    private Collection<? extends GrantedAuthority> defaultAuthorities;
    private UserDetailsService userDetailsService;

    public UserAuthConverter() {
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    public Map<String, ?> convertUserAuthentication(Authentication authentication) {
        Map<String, Object> response = new LinkedHashMap();
        response.put("user_name", authentication.getName());
        response.put("user_info", authentication.getPrincipal());
        if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
            response.put("authorities", AuthorityUtil.authorities(authentication.getAuthorities()));
        }
        return response;
    }

    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        if (map.containsKey("user_name")) {
            Object principal = map.get("user_name");
            Collection<? extends GrantedAuthority> authorities = this.getAuthorities(map);
            if (this.userDetailsService != null) {
                UserBO userBO = (UserBO) this.userDetailsService.loadUserByUsername((String) map.get("user_name"));
                authorities = userBO.getAuthorities();
                UserInfoBO userInfoBO = new UserInfoBO();
                userInfoBO.setUserId(userBO.getUserId());
                userInfoBO.setUserUsername(userBO.getUsername());
                userInfoBO.setUserName(userBO.getUserName());
                userInfoBO.setUserPhone(userBO.getUserPhone());
                principal = userInfoBO;
            } else {
                // 包含用户信息，则直接抽取其中的用户信息
                if (map.containsKey("user_info")) {
                    Map<String, Object> userInfo = (Map<String, Object>) map.get("user_info");
                    UserInfoBO userInfoBO = new UserInfoBO();
                    userInfoBO.setUserId(userInfo.get("userId").toString());
                    userInfoBO.setUserUsername(userInfo.get("username").toString());
                    userInfoBO.setUserName(userInfo.get("userName").toString());
                    userInfoBO.setUserPhone(userInfo.get("userPhone") == null ? "" : userInfo.get("userPhone").toString());
                    principal = userInfoBO;
                }
            }
            return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
        } else {
            return null;
        }
    }

    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        if (!map.containsKey("authorities")) {
            // 没有设置过默认权限
            if (this.defaultAuthorities == null) {
                return new ArrayList<>(0);
            }
            return this.defaultAuthorities;
        } else {
            Object authorities = map.get("authorities");
            if (authorities instanceof String) {
                return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
            } else if (authorities instanceof Collection) {
                return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection) authorities));
            } else {
                throw new IllegalArgumentException("授权信息必须是字符串或者集合");
            }
        }
    }
}
