/*
 * 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 java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;

import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

import org.apache.commons.lang3.StringUtils;
import org.apache.hugegraph.config.ServerOptions;
import org.glassfish.hk2.api.MultiException;

import org.apache.hugegraph.HugeException;
import org.apache.hugegraph.api.API;
import org.apache.hugegraph.config.HugeConfig;
import org.apache.hugegraph.exception.HugeGremlinException;
import org.apache.hugegraph.exception.NotFoundException;
import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.ImmutableMap;

public class ExceptionFilter {

    private static final int BAD_REQUEST_ERROR =
            Response.Status.BAD_REQUEST.getStatusCode();
    private static final int NOT_FOUND_ERROR =
            Response.Status.NOT_FOUND.getStatusCode();
    private static final int INTERNAL_SERVER_ERROR =
            Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();

    public static class TracedExceptionMapper extends API {

        private static boolean forcedTrace = false;

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

        protected boolean trace() {
            if (forcedTrace) {
                return true;
            }
            HugeConfig config = this.configProvider.get();
            if (config == null) {
                return false;
            }
            return config.get(ServerOptions.ALLOW_TRACE);
        }
    }

    @Path("exception/trace")
    @Singleton
    @Tag(name = "TracedExceptionAPI")
    public static class TracedExceptionAPI extends API {

        @GET
        @Timed
        @Produces(APPLICATION_JSON_WITH_CHARSET)
        @RolesAllowed({"admin"})
        public Object get() {
            return ImmutableMap.of("trace", TracedExceptionMapper.forcedTrace);
        }

        @PUT
        @Timed
        @Consumes(APPLICATION_JSON)
        @Produces(APPLICATION_JSON_WITH_CHARSET)
        @RolesAllowed({"admin"})
        public Object trace(boolean trace) {
            TracedExceptionMapper.forcedTrace = trace;
            return ImmutableMap.of("trace", TracedExceptionMapper.forcedTrace);
        }
    }

    @Provider
    public static class HugeExceptionMapper
                  extends TracedExceptionMapper
                  implements ExceptionMapper<HugeException> {

        @Override
        public Response toResponse(HugeException exception) {
            return Response.status(BAD_REQUEST_ERROR)
                           .type(MediaType.APPLICATION_JSON)
                           .entity(formatException(exception, this.trace()))
                           .build();
        }
    }

    @Provider
    public static class IllegalArgumentExceptionMapper
                  extends TracedExceptionMapper
                  implements ExceptionMapper<IllegalArgumentException> {

        @Override
        public Response toResponse(IllegalArgumentException exception) {
            return Response.status(BAD_REQUEST_ERROR)
                           .type(MediaType.APPLICATION_JSON)
                           .entity(formatException(exception, this.trace()))
                           .build();
        }
    }

    @Provider
    public static class NotFoundExceptionMapper
                  extends TracedExceptionMapper
                  implements ExceptionMapper<NotFoundException> {

        @Override
        public Response toResponse(NotFoundException exception) {
            return Response.status(NOT_FOUND_ERROR)
                           .type(MediaType.APPLICATION_JSON)
                           .entity(formatException(exception, this.trace()))
                           .build();
        }
    }

    @Provider
    public static class NoSuchElementExceptionMapper
                  extends TracedExceptionMapper
                  implements ExceptionMapper<NoSuchElementException> {

        @Override
        public Response toResponse(NoSuchElementException exception) {
            return Response.status(NOT_FOUND_ERROR)
                           .type(MediaType.APPLICATION_JSON)
                           .entity(formatException(exception, this.trace()))
                           .build();
        }
    }

    @Provider
    public static class WebApplicationExceptionMapper
                  extends TracedExceptionMapper
                  implements ExceptionMapper<WebApplicationException> {

        @Override
        public Response toResponse(WebApplicationException exception) {
            Response response = exception.getResponse();
            if (response.hasEntity()) {
                return response;
            }
            MultivaluedMap<String, Object> headers = response.getHeaders();
            boolean trace = this.trace(response.getStatus());
            response = Response.status(response.getStatus())
                               .type(MediaType.APPLICATION_JSON)
                               .entity(formatException(exception, trace))
                               .build();
            response.getHeaders().putAll(headers);
            return response;
        }

        private boolean trace(int status) {
            return this.trace() && status == INTERNAL_SERVER_ERROR;
        }
    }

    @Provider
    public static class HugeGremlinExceptionMapper
                  extends TracedExceptionMapper
                  implements ExceptionMapper<HugeGremlinException> {

        @Override
        public Response toResponse(HugeGremlinException exception) {
            return Response.status(exception.statusCode())
                           .type(MediaType.APPLICATION_JSON)
                           .entity(formatGremlinException(exception,
                                                          this.trace()))
                           .build();
        }
    }

    @Provider
    public static class AssertionErrorMapper extends TracedExceptionMapper
                  implements ExceptionMapper<AssertionError> {

        @Override
        public Response toResponse(AssertionError exception) {
            return Response.status(INTERNAL_SERVER_ERROR)
                           .type(MediaType.APPLICATION_JSON)
                           .entity(formatException(exception, true))
                           .build();
        }
    }

    @Provider
    public static class UnknownExceptionMapper extends TracedExceptionMapper
                  implements ExceptionMapper<Throwable> {

        @Override
        public Response toResponse(Throwable exception) {
            if (exception instanceof MultiException &&
                ((MultiException) exception).getErrors().size() == 1) {
                exception = ((MultiException) exception).getErrors().get(0);
            }
            return Response.status(INTERNAL_SERVER_ERROR)
                           .type(MediaType.APPLICATION_JSON)
                           .entity(formatException(exception, this.trace()))
                           .build();
        }
    }

    public static String formatException(Throwable exception, boolean trace) {
        String clazz = exception.getClass().toString();
        String message = exception.getMessage() != null ?
                         exception.getMessage() : "";
        String cause = exception.getCause() != null ?
                       exception.getCause().toString() : "";

        JsonObjectBuilder json = Json.createObjectBuilder()
                                     .add("exception", clazz)
                                     .add("message", message)
                                     .add("cause", cause);

        if (trace) {
            JsonArrayBuilder traces = Json.createArrayBuilder();
            for (StackTraceElement i : exception.getStackTrace()) {
                traces.add(i.toString());
            }
            json.add("trace", traces);
        }

        return json.build().toString();
    }

    public static String formatGremlinException(HugeGremlinException exception,
                                                boolean trace) {
        Map<String, Object> map = exception.response();
        String message = (String) map.get("message");
        String exClassName = (String) map.get("Exception-Class");
        @SuppressWarnings("unchecked")
        List<String> exceptions = (List<String>) map.get("exceptions");
        String stackTrace = (String) map.get("stackTrace");

        message = message != null ? message : "";
        exClassName = exClassName != null ? exClassName : "";
        String cause = exceptions != null ? exceptions.toString() : "";

        JsonObjectBuilder json = Json.createObjectBuilder()
                                     .add("exception", exClassName)
                                     .add("message", message)
                                     .add("cause", cause);

        if (trace && stackTrace != null) {
            JsonArrayBuilder traces = Json.createArrayBuilder();
            for (String part : StringUtils.split(stackTrace, '\n')) {
                traces.add(part);
            }
            json.add("trace", traces);
        }

        return json.build().toString();
    }
}
