/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with this
 * work for additional information regarding copyright ownership. The ASF
 * licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package org.apache.hugegraph.api.filter;

import static org.apache.hugegraph.config.ServerOptions.WHITE_IP_STATUS;

import java.io.IOException;
import java.security.Principal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import javax.xml.bind.DatatypeConverter;

import org.apache.hugegraph.auth.HugeAuthenticator;
import org.apache.hugegraph.auth.HugeAuthenticator.RequiredPerm;
import org.apache.hugegraph.auth.HugeAuthenticator.RolePerm;
import org.apache.hugegraph.auth.HugeAuthenticator.User;
import org.apache.hugegraph.auth.RolePermission;
import org.apache.hugegraph.config.HugeConfig;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticationException;
import org.glassfish.grizzly.http.server.Request;
import org.glassfish.grizzly.utils.Charsets;
import org.slf4j.Logger;

import com.alipay.remoting.util.StringUtils;
import com.google.common.collect.ImmutableList;

import jakarta.annotation.Priority;
import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.NotAuthorizedException;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.PreMatching;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.SecurityContext;
import jakarta.ws.rs.core.UriInfo;
import jakarta.ws.rs.ext.Provider;

@Provider
@PreMatching
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {

    public static final String BASIC_AUTH_PREFIX = "Basic ";
    public static final String BEARER_TOKEN_PREFIX = "Bearer ";

    private static final Logger LOG = Log.logger(AuthenticationFilter.class);

    private static final List<String> WHITE_API_LIST = ImmutableList.of(
            "auth/login",
            "versions"
    );

    private static String whiteIpStatus;

    private static final String STRING_WHITE_IP_LIST = "whiteiplist";
    private static final String STRING_ENABLE = "enable";

    @Context
    private jakarta.inject.Provider<GraphManager> managerProvider;

    @Context
    private jakarta.inject.Provider<Request> requestProvider;

    @Context
    private jakarta.inject.Provider<HugeConfig> configProvider;

    @Override
    public void filter(ContainerRequestContext context) throws IOException {
        if (AuthenticationFilter.isWhiteAPI(context)) {
            return;
        }
        User user = this.authenticate(context);
        Authorizer authorizer = new Authorizer(user, context.getUriInfo());
        context.setSecurityContext(authorizer);
    }

    protected User authenticate(ContainerRequestContext context) {
        GraphManager manager = this.managerProvider.get();
        E.checkState(manager != null, "Context GraphManager is absent");

        if (!manager.requireAuthentication()) {
            // Return anonymous user with admin role if disable authentication
            return User.ANONYMOUS;
        }

        // Get peer info
        Request request = this.requestProvider.get();
        String peer = null;
        String path = null;
        if (request != null) {
            peer = request.getRemoteAddr() + ":" + request.getRemotePort();
            path = request.getRequestURI();
        }

        // Check whiteIp
        if (whiteIpStatus == null) {
            whiteIpStatus = this.configProvider.get().get(WHITE_IP_STATUS);
        }

        if (Objects.equals(whiteIpStatus, STRING_ENABLE) && request != null) {
            peer = request.getRemoteAddr() + ":" + request.getRemotePort();
            path = request.getRequestURI();

            String remoteIp = request.getRemoteAddr();
            Set<String> whiteIpList = manager.authManager().listWhiteIPs();
            boolean whiteIpEnabled = manager.authManager().getWhiteIpStatus();
            if (!path.contains(STRING_WHITE_IP_LIST) && whiteIpEnabled &&
                !whiteIpList.contains(remoteIp)) {
                throw new ForbiddenException(
                        String.format("Remote ip '%s' is not permitted",
                                      remoteIp));
            }
        }

        Map<String, String> credentials = new HashMap<>();
        // Extract authentication credentials
        String auth = context.getHeaderString(HttpHeaders.AUTHORIZATION);
        if (auth == null) {
            throw new NotAuthorizedException(
                      "Authentication credentials are required",
                      "Missing authentication credentials");
        }

        if (auth.startsWith(BASIC_AUTH_PREFIX)) {
            auth = auth.substring(BASIC_AUTH_PREFIX.length());
            auth = new String(DatatypeConverter.parseBase64Binary(auth),
                              Charsets.ASCII_CHARSET);
            String[] values = auth.split(":");
            if (values.length != 2) {
                throw new BadRequestException(
                          "Invalid syntax for username and password");
            }

            final String username = values[0];
            final String password = values[1];

            if (StringUtils.isEmpty(username) ||
                StringUtils.isEmpty(password)) {
                throw new BadRequestException(
                          "Invalid syntax for username and password");
            }

            credentials.put(HugeAuthenticator.KEY_USERNAME, username);
            credentials.put(HugeAuthenticator.KEY_PASSWORD, password);
        } else if (auth.startsWith(BEARER_TOKEN_PREFIX)) {
            String token = auth.substring(BEARER_TOKEN_PREFIX.length());
            credentials.put(HugeAuthenticator.KEY_TOKEN, token);
        } else {
            throw new BadRequestException(
                      "Only HTTP Basic or Bearer authentication is supported");
        }

        credentials.put(HugeAuthenticator.KEY_ADDRESS, peer);
        credentials.put(HugeAuthenticator.KEY_PATH, path);

        // Validate the extracted credentials
        try {
            return manager.authenticate(credentials);
        } catch (AuthenticationException e) {
            throw new NotAuthorizedException("Authentication failed",
                                             e.getMessage());
        }
    }

    public static class Authorizer implements SecurityContext {

        private final UriInfo uri;
        private final User user;
        private final Principal principal;

        public Authorizer(final User user, final UriInfo uri) {
            E.checkNotNull(user, "user");
            E.checkNotNull(uri, "uri");
            this.uri = uri;
            this.user = user;
            this.principal = new UserPrincipal();
        }

        public String username() {
            return this.user.username();
        }

        public RolePermission role() {
            return this.user.role();
        }

        @Override
        public Principal getUserPrincipal() {
            return this.principal;
        }

        @Override
        public boolean isUserInRole(String required) {
            if (required.equals(HugeAuthenticator.KEY_DYNAMIC)) {
                // Let the resource itself determine dynamically
                return true;
            } else {
                return this.matchPermission(required);
            }
        }

        @Override
        public boolean isSecure() {
            return "https".equals(this.uri.getRequestUri().getScheme());
        }

        @Override
        public String getAuthenticationScheme() {
            return SecurityContext.BASIC_AUTH;
        }

        private boolean matchPermission(String required) {
            boolean valid;
            RequiredPerm requiredPerm;

            if (!required.startsWith(HugeAuthenticator.KEY_OWNER)) {
                // Permission format like: "admin"
                requiredPerm = new RequiredPerm();
                requiredPerm.owner(required);
            } else {
                // The required like: $owner=graph1 $action=vertex_write
                requiredPerm = RequiredPerm.fromPermission(required);

                /*
                 * Replace owner value(it may be a variable) if the permission
                 * format like: "$owner=$graph $action=vertex_write"
                 */
                String owner = requiredPerm.owner();
                if (owner.startsWith(HugeAuthenticator.VAR_PREFIX)) {
                    // Replace `$graph` with graph name like "graph1"
                    int prefixLen = HugeAuthenticator.VAR_PREFIX.length();
                    assert owner.length() > prefixLen;
                    owner = owner.substring(prefixLen);
                    owner = this.getPathParameter(owner);
                    requiredPerm.owner(owner);
                }
            }

            if (LOG.isDebugEnabled()) {
                LOG.debug("Verify permission {} {} for user '{}' with role {}",
                          requiredPerm.action().string(),
                          requiredPerm.resourceObject(),
                          this.user.username(), this.user.role());
            }

            // verify role permission
            valid = RolePerm.match(this.role(), requiredPerm);

            if (!valid && LOG.isInfoEnabled() &&
                !required.equals(HugeAuthenticator.USER_ADMIN)) {
                LOG.info("User '{}' is denied to {} {}",
                         this.user.username(), requiredPerm.action().string(),
                         requiredPerm.resourceObject());
            }
            return valid;
        }

        private String getPathParameter(String key) {
            List<String> params = this.uri.getPathParameters().get(key);
            E.checkState(params != null && params.size() == 1,
                         "There is no matched path parameter: '%s'", key);
            return params.get(0);
        }

        private final class UserPrincipal implements Principal {

            @Override
            public String getName() {
                return Authorizer.this.user.getName();
            }

            @Override
            public String toString() {
                return Authorizer.this.user.toString();
            }

            @Override
            public int hashCode() {
                return Authorizer.this.user.hashCode();
            }

            @Override
            public boolean equals(Object obj) {
                return Authorizer.this.user.equals(obj);
            }
        }
    }

    public static boolean isWhiteAPI(ContainerRequestContext context) {
        String path = context.getUriInfo().getPath();

        for (String whiteApi : WHITE_API_LIST) {
            if (path.endsWith(whiteApi)) {
                return true;
            }
        }
        return false;
    }
}
