/*
 * Copyright 2017 The Mifos Initiative.
 *
 * Licensed 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 io.mifos.core.api.util;

import feign.Feign;
import feign.FeignException;
import feign.Response;
import io.mifos.core.api.annotation.ThrowsException;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

/**
 * @author Myrle Krantz
 */
@RunWith(Parameterized.class)
public class AnnotatedErrorDecoderTest {

  private final TestCase testCase;

  public AnnotatedErrorDecoderTest(final TestCase testCase) {
    this.testCase = testCase;
  }

  @Parameterized.Parameters
  public static Collection testCases() throws NoSuchMethodException {
    final Collection<TestCase> ret = new ArrayList<>();

    final Response emptyInternalServerErrorResponse = Response.builder()
            .status(HttpStatus.INTERNAL_SERVER_ERROR.value())
            .reason("blah")
            .headers(Collections.emptyMap())
            .build();

    final Response emptyBadRequestResponse = Response.builder()
            .status(HttpStatus.BAD_REQUEST.value())
            .reason("blah")
            .headers(Collections.emptyMap())
            .build();

    final Response emptyConflictResponse = Response.builder()
            .status(HttpStatus.CONFLICT.value())
            .reason("blah")
            .headers(Collections.emptyMap())
            .build();

    final Response emptyIAmATeapotResponse = Response.builder()
            .status(HttpStatus.I_AM_A_TEAPOT.value())
            .reason("blah")
            .headers(Collections.emptyMap())
            .build();

    final Response emptyUnauthorizedResponse = Response.builder()
            .status(HttpStatus.UNAUTHORIZED.value())
            .reason("blah")
            .headers(Collections.emptyMap())
            .build();

    final Response emptyForbiddenResponse = Response.builder()
            .status(HttpStatus.FORBIDDEN.value())
            .reason("blah")
            .headers(Collections.emptyMap())
            .build();

    final String madeUpMethodKey = "x";

    final String annotationlessMethodKey =
        Feign.configKey(AnnotationlessInterface.class, AnnotationlessInterface.class.getMethod("method"));

    final String oneAnnotatedMethodKey =
        Feign.configKey(OneMethodInterface.class, OneMethodInterface.class.getMethod("method"));

    final String onceAnnotatedMethodKey =
        Feign.configKey(OneMethodOneAnnotationInterface.class, OneMethodOneAnnotationInterface.class.getMethod("method"));

    ret.add(new TestCase("Methodless interface")
        .clazz(MethodlessInterface.class)
        .methodKey(madeUpMethodKey)
        .response(emptyConflictResponse)
        .expectedResult(FeignException.errorStatus(madeUpMethodKey, emptyConflictResponse)));

    ret.add(new TestCase("Annotationless interface")
        .clazz(AnnotationlessInterface.class)
        .methodKey(annotationlessMethodKey)
        .response(emptyConflictResponse)
        .expectedResult(FeignException.errorStatus(annotationlessMethodKey, emptyConflictResponse)));

    ret.add(new TestCase("Interface with one method mapped to parameterless exception")
        .clazz(OneMethodInterface.class)
        .methodKey(oneAnnotatedMethodKey)
        .response(emptyBadRequestResponse)
        .expectedResult(new ParameterlessException()));

    ret.add(new TestCase("Interface with one method mapped to parametered exception")
        .clazz(OneMethodInterface.class)
        .methodKey(oneAnnotatedMethodKey)
        .response(emptyConflictResponse)
        .expectedResult(new ParameteredException(emptyConflictResponse)));

    ret.add(new TestCase("Interface with one method mapped to an exception which can't be constructed by reflection")
        .clazz(OneMethodInterface.class)
        .methodKey(oneAnnotatedMethodKey)
        .response(emptyIAmATeapotResponse)
        .expectedResult(FeignException.errorStatus(oneAnnotatedMethodKey, emptyIAmATeapotResponse)));

    ret.add(new TestCase("Interface with one method, not mapped to the response code returned")
        .clazz(OneMethodInterface.class)
        .methodKey(oneAnnotatedMethodKey)
        .response(emptyUnauthorizedResponse)
        .expectedResult(FeignException.errorStatus(oneAnnotatedMethodKey, emptyUnauthorizedResponse)));

    ret.add(new TestCase("Interface with one method that has one annotation")
        .clazz(OneMethodOneAnnotationInterface.class)
        .methodKey(onceAnnotatedMethodKey)
        .response(emptyBadRequestResponse)
        .expectedResult(new ParameterlessException()));

    ret.add(new TestCase("Bad request on an interface in which bad request isn't mapped.")
        .clazz(AnnotationlessInterface.class)
        .methodKey(annotationlessMethodKey)
        .response(emptyBadRequestResponse)
        .expectedResult(new IllegalArgumentException("blah")));

    ret.add(new TestCase("Request with invalid token.")
        .clazz(OneMethodOneAnnotationInterface.class)
        .methodKey(onceAnnotatedMethodKey)
        .response(emptyForbiddenResponse)
        .expectedResult(new InvalidTokenException("blah")));

    ret.add(new TestCase("Internal Server Error on an interface in which internal server error isn't mapped.")
        .clazz(AnnotationlessInterface.class)
        .methodKey(annotationlessMethodKey)
        .response(emptyInternalServerErrorResponse)
        .expectedResult(new InternalServerError("blah")));

    return ret;
  }

  @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
  @Test
  public void checkMapping() {

    final AnnotatedErrorDecoder testSubject = new AnnotatedErrorDecoder(
        LoggerFactory.getLogger(AnnotatedErrorDecoderTest.class.getName()), testCase.getClazz());

    final Exception result = testSubject.decode(testCase.getMethodKey(), testCase.getResponse());

    Assert.assertEquals("Test case \"" + testCase.getName() + "\" failed.",
        testCase.expectedResult().getClass(), result.getClass());

    Assert.assertEquals("Test case \"" + testCase.getName() + "\" failed.",
        testCase.expectedResult().getMessage(), result.getMessage());
  }

  private interface MethodlessInterface {

  }

  private interface AnnotationlessInterface {

    @SuppressWarnings("unused")
    void method();
  }

  private interface OneMethodInterface {

    @SuppressWarnings("unused")
    @ThrowsException(status = HttpStatus.BAD_REQUEST, exception = ParameterlessException.class)
    @ThrowsException(status = HttpStatus.CONFLICT, exception = ParameteredException.class)
    @ThrowsException(status = HttpStatus.I_AM_A_TEAPOT, exception = WrongParameteredException.class)
    void method();
  }


  private interface OneMethodOneAnnotationInterface {

    @SuppressWarnings("unused")
    @ThrowsException(status = HttpStatus.BAD_REQUEST, exception = ParameterlessException.class)
    void method();
  }

  private static class TestCase {

    private final String name;
    private Class clazz;
    private String methodKey;
    private Response response;
    private Exception expectedResult;

    private TestCase(final String name) {
      this.name = name;
    }

    public String toString() {
      return name;
    }

    TestCase clazz(final Class newVal) {
      clazz = newVal;
      return this;
    }

    TestCase methodKey(final String newVal) {
      methodKey = newVal;
      return this;
    }

    TestCase response(final Response newVal) {
      response = newVal;
      return this;
    }

    TestCase expectedResult(final Exception newVal) {
      expectedResult = newVal;
      return this;
    }

    Class getClazz() {
      return clazz;
    }

    String getMethodKey() {
      return methodKey;
    }

    Response getResponse() {
      return response;
    }

    Exception expectedResult() {
      return expectedResult;
    }

    String getName() {
      return name;
    }
  }

  private static class ParameterlessException extends RuntimeException {

    @SuppressWarnings("WeakerAccess")
    public ParameterlessException() {
      super("I am a parameterless exception.  Aren't I cool.");
    }
  }

  private static class ParameteredException extends RuntimeException {

    @SuppressWarnings("WeakerAccess")
    public ParameteredException(final Response response) {
      super("I am a parametered exception with a response of " + response.toString());
    }
  }

  private static class WrongParameteredException extends RuntimeException {

    public WrongParameteredException(final String message) {
      super(message);
    }
  }
}
