package com.community.huiju.security;

import com.community.commom.constant.Constant;
import com.community.commom.session.UserElement;
import com.community.huiju.constant.Header;
import com.community.huiju.constant.RequestURI;
import com.community.huiju.constant.Status;
import com.community.huiju.dto.RoleDTO;
import com.community.huiju.service.IRoleService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 预授权
 * @author weiximei
 */
@Slf4j
public class RestPreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter {

    private AntPathMatcher matcher = new AntPathMatcher();

    private IRoleService iRoleService;


    /** 用户类型请求登陆类型 **/
    @Deprecated
    private String loginType;

    /**
     * 不需要权限访问的路径
     */
    private List<String> noneSecurity;

    /**
     * 获取主体信息
     *
     *      1.验证是否有权限
     *      2.授权
     *
     * @param request
     * @return
     */
    @Override
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        List<GrantedAuthority> grantedAuthorityList = new ArrayList<>();
        // 不需要的拦截请求处理
        if (isNoneSecurity(request.getRequestURI().toString()) || "OPTIONS".equals(request.getMethod())){
            GrantedAuthority[] authorities = new GrantedAuthority[1];
            GrantedAuthority roleNone = new SimpleGrantedAuthority(Constant.ROLE_NONEUSER);
            authorities[0]=roleNone;
            grantedAuthorityList.add(authorities[0]);
            return new TokenAuthrentication(grantedAuthorityList);
        }

        isInspection(request);

        String requestUrl = request.getRequestURI();
        if (null == request.getAttribute(Header.HEADER_ERROR.getValue())){
            try {
                UserElement userElement = getUserElement(request);
                if (null == userElement) {
                    request.setAttribute(Header.HEADER_ERROR.getValue(), Status.RESPONSE_STATUS_803.getValue());
                }else {
                    List<RoleDTO> roleDTOList = Lists.newArrayList();
                    if (matcher.match(RequestURI.APP_API.getUrl(), requestUrl)) {
                        roleDTOList = iRoleService.getAppUserRoleByUserId(userElement.getId());
                    }else if (matcher.match(RequestURI.OPERATE_API.getUrl(), requestUrl)) {
                        roleDTOList = iRoleService.getWebOperateUserRoleByUserId(userElement.getId());
                    }else if (matcher.match(RequestURI.PROPERTY_API.getUrl(), requestUrl)) {
                        roleDTOList = iRoleService.getWebPropertyUserRoleUserId(userElement.getId());
                    }

                    grantedAuthorityList = roleDTOList.stream()
                            .map(e->new SimpleGrantedAuthority(e.getRoleName()))
                            .collect(Collectors.toList());
                }
            } catch (Exception e){
                log.error("用户授权失败!",e);
                e.printStackTrace();
            }

        }else {
            // 校验有问题后, 需要给个角色, 让流程继续下去
            GrantedAuthority[] authorities = new GrantedAuthority[1];
            GrantedAuthority roleNone = new SimpleGrantedAuthority(Constant.ROLE_NONE);
            authorities[0]=roleNone;
            grantedAuthorityList.add(authorities[0]);
        }

        return new TokenAuthrentication(grantedAuthorityList);
    }


    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest httpServletRequest) {
        return null;
    }

    /**
     * 验证url是否是不需要权限访问
     * @param url
     * @return
     */
    private boolean isNoneSecurity(String url){
        for (String sysMenu : noneSecurity) {
            if (matcher.match(sysMenu,url)){
                return true;
            }
        }
        return false;
    }

    /**
     * 检验Token, App版本, 用户登录类型
     * @param request
     */
    private void isInspection(HttpServletRequest request){
        // Token检测
        String token = request.getHeader(Header.REQUEST_X_AUTH_TOKEN.getValue());
        if (StringUtils.isBlank(token)) {
            request.setAttribute(Header.HEADER_ERROR.getValue(), Status.RESPONSE_STATUS_802.getValue());
        }
        // APP版本检测
//        String version = request.getHeader(Header.REQUEST_VERSION.getValue());
//        if (StringUtils.isBlank(version)){
//            request.setAttribute(Header.HEADER_ERROR.getValue(),Status.RESPONSE_STATUS_800.getValue());
//        }

    }


    /**
     * 获取用户session信息
     * @param request
     * @return
     */
    public UserElement getUserElement(HttpServletRequest request){
        String requestUrl = request.getRequestURI();
        HttpSession session = request.getSession();
        UserElement userElement = null;
        if (matcher.match(RequestURI.APP_API.getUrl(), requestUrl)) {
            userElement = (UserElement) session.getAttribute(Constant.APP_USER_SESSION);
        } else if (matcher.match(RequestURI.OPERATE_API.getUrl(), requestUrl) || matcher.match(RequestURI.PROPERTY_API.getUrl(), requestUrl)) {
            userElement = (UserElement) session.getAttribute(Constant.WEB_USER_SESSION);
        }

        return userElement;
    }

    public RestPreAuthenticatedProcessingFilter(List<String> noneSecurity,IRoleService iRoleService) {
        this.noneSecurity = noneSecurity;
        this.iRoleService = iRoleService;
    }
}
