package com.springboot.cloud.auth.authentication.service.impl;

import com.springboot.cloud.auth.authentication.entity.Popedom;
import com.springboot.cloud.auth.authentication.service.AuthenticationService;
import com.springboot.cloud.auth.authentication.service.PopedomService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class AuthenticationServiceImpl implements AuthenticationService {

    @Autowired
    private PopedomService popedomService;

    /**
     * @param authRequest 访问的url,method
     * @return 有权限true, 无权限或全局资源中未找到请求url返回否
     */
    @Override
    public boolean decide(HttpServletRequest authRequest) {
        log.debug("正在访问的url是:{}", authRequest.getServletPath());
        //获取用户认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取此url访问对应的权限资源信息
        List<ConfigAttribute> configAttributes = popedomService.findConfigAttributesByUrl(authRequest);
        if (configAttributes.size() == 0) {
            //如果未匹配到资源，则返回未授权
            return false;
        } else if (configAttributes.size() == 1) {
            //默认授权所有资源，所有资源都会匹配,如果仅匹配到一个资源，则必定不是功能接口
            return true;
        } else {
            String companyId = Optional.ofNullable(authRequest.getParameter("companyId")).orElseGet(String::new);
//            String companyId = Optional.ofNullable(UserContextHolder.getInstance().getCurrentCompany()).orElseGet(String::new);
            //获取此访问用户所有角色拥有的权限资源
            List<Popedom> userPopedoms = findPopedomByUsername(companyId, authentication.getName());
            //用户拥有权限资源 与 url要求的资源进行对比
            return isMatch(companyId,configAttributes, userPopedoms);
        }

    }

    /**
     * url对应资源与用户拥有资源进行匹配
     * 前端传入所在公司
     * @param userPopedoms
     * @return
     */
    public boolean isMatch(String companyId,List<ConfigAttribute> urlConfigAttributes, List<Popedom> userPopedoms) {
        //首先检查用户所属角色是否有资源权限
        Optional<Popedom> optionalPopedom = userPopedoms.stream().filter(popedom -> urlConfigAttributes.contains(new SecurityConfig(popedom.getId()))).findAny();
        if(optionalPopedom.isPresent()){
            //再检查用户所在公司应用是否过期
            return popedomService.license(companyId, optionalPopedom.orElseGet(Popedom::new).getApplicationCode());
        }else{
            return false;
        }
    }

    /**
     * 根据用户所被授予的角色，查询到用户所拥有的资源
     *
     * @param username
     * @return
     */
    private List<Popedom> findPopedomByUsername(String companyId, String username) {
        //用户被授予的角色资源
        List<Popedom> popedoms = popedomService.queryByUsername(companyId, username);
        if (log.isDebugEnabled()) {
            log.debug("用户被授予角色的资源数量是:{}, 资源集合信息为:{}", popedoms.size(), popedoms);
        }
        return popedoms;
    }
}
