package jwt

import (
	"net/http"
	"os"
	"testing"

	"github.com/fiskerinc/cloud-services/pkg/testhelper"
)

const expiredToken = "eyJraWQiOiJlUTNuZFJLaUVcL084VUZ5RHFsYjN0S1RzWG00SzVPMlc4NXd3VWkzT2tNZz0iLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiUGFqSzVNX0d0M3lta0ZOTjhOMUJydyIsInN1YiI6IjJkZDZmZWQ5LWU1ODItNDUxYi1hOTNiLTViOTQxMGRmYmM0MyIsImNvZ25pdG86Z3JvdXBzIjpbInVzLXdlc3QtMl9BV3dqTFh5bTJfQXp1cmVBRCJdLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy13ZXN0LTIuYW1hem9uYXdzLmNvbVwvdXMtd2VzdC0yX0FXd2pMWHltMiIsImNvZ25pdG86dXNlcm5hbWUiOiJhenVyZWFkX2p3dUBmaXNrZXJpbmMuY29tIiwiYXVkIjoiN2NrMnRmb3FhdmM3MmM0NWhoN3RnZTQya2QiLCJpZGVudGl0aWVzIjpbeyJ1c2VySWQiOiJqd3VAZmlza2VyaW5jLmNvbSIsInByb3ZpZGVyTmFtZSI6IkF6dXJlQUQiLCJwcm92aWRlclR5cGUiOiJTQU1MIiwiaXNzdWVyIjoiaHR0cHM6XC9cL3N0cy53aW5kb3dzLm5ldFwvNWFhNGI2NDAtYzlmYy00YTliLWIzYTMtZDRhN2QwMDhmYjVlXC8iLCJwcmltYXJ5IjoidHJ1ZSIsImRhdGVDcmVhdGVkIjoiMTYxMjkwMjQxMzM4MyJ9XSwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE2MTMxNTkzNDAsImV4cCI6MTYxMzE3OTk2MywiaWF0IjoxNjEzMTc2MzYzLCJlbWFpbCI6Imp3dUBmaXNrZXJpbmMuY29tIn0.lMIMjTaG11Y-Ft6wbuE9J3ic4EWmK-VgDXbcO583r8sckgKfWgpTI9Qy3zkkhmN0btDtQP4EqKI5afHKbDVu02wZk2y_y1adgWBxLtOJX3yCifxK99mCQUAjMvyBQ3_YbhLUexv3kvh047w0Fe3VjdPftfRwpfbmQsIYjWhF-MzDjdZJPXnXm3GjbtW6g3eKqA9AHg05ghBC4seatrDhHWKVSYS8DzmfJlsJCcdbdzZQ3fVLnYsVOU8-LK6B-IbpmpTUaobcF-acAwFaNPD56mGxI3xpnvExc9sM8ZBQD2NNhnHqY04p7mjaK2Wf4p73yLtI3SdW5SWy-w1reiaElQ"
const invalidToken = "eyJraWQiOiJlUTNuZFJLaUVcL084VUZ5RHFsYjN0S1RzWG00SzVPMlc4NXd3VWkzT2tNZz0iLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiUGFqSzVNX0d0M3lta0ZOTjhOMUJydyIsInN1YiI6IjJkZDZmZWQ5LWU1ODItNDUxYi1hOTNiLTViOTQxMGRmYmM0MyIsImNvZ25pdG86Z3JvdXBzIjpbInVzLXdlc3QtMl9BV3dqTFh5bTJfQXp1cmVBRCJdLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy13ZXN0LTIuYW1hem9uYXdzLmNvbVwvdXMtd2VzdC0yX0FXd2pMWHltMiIsImNvZ25pdG86dXNlcm5hbWUiOiJhenVyZWFkX2p3dUBmaXNrZXJpbmMuY29tIiwiYXVkIjoiN2NrMnRmb3FhdmM3MmM0NWhoN3RnZTQya2QiLCJpZGVudGl0aWVzIjpbeyJ1c2VySWQiOiJqd3VAZmlza2VyaW5jLmNvbSIsInByb3ZpZGVyTmFtZSI6IkF6dXJlQUQiLCJwcm92aWRlclR5cGUiOiJTQU1MIiwiaXNzdWVyIjoiaHR0cHM6XC9cL3N0cy53aW5kb3dzLm5ldFwvNWFhNGI2NDAtYzlmYy00YTliLWIzYTMtZDRhN2QwMDhmYjVlXC8iLCJwcmltYXJ5IjoidHJ1ZSIsImRhdGVDcmVhdGVkIjoiMTYxMjkwMjQxMzM4MyJ9XSwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE2MTMxNTkzNDAsImV4cCI6MTYxMzE3OTk2MywiaWF0IjoxNjEzMTc2MzYzLCJlbWFpbCI6Imp3dUBmaXNrZXJpbmMuY29tIn0.lMIMjTaG11Y-Ft6wbuE9J3ic4EWmK-VgDXbcO583r8sckgKfWgpTI9Qy3zkkhmN0btDtQP4EqKI5afHKbDVu02wZk2y_y1adgWBxLtOJX3yCifxK99mCQUAjMvyBQ3_YbhLUexv3kvh047w0Fe3VjdPftfRwpfbmQsIYjWhF-MzDjdZJPXnXm3GjbtW6g3eKqA9AHg05ghBC4seatrDhHWKVSYS8DzmfJlsJCcdbdzZQ3fVLnYsVOU8-LK6B-IbpmpTUaobcF-acAwFaNPD56mGxI3xpnvExc9sM8ZBQD2NNhnHqY04p7mjaK2Wf4p73yLtI3SdW5SWy-w1reiaEl"

func init() {
	os.Setenv("JWK_URL", "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_AWwjLXym2/.well-known/jwks.json")
}

func TestValidation(t *testing.T) {
	validator := NewJWTValidator("")
	type testCase struct {
		Name               string
		Token              string
		ExpectedError      string
		DisableExpireCheck bool
	}

	tests := []testCase{
		{
			Name:          "Expired",
			Token:         expiredToken,
			ExpectedError: "token expired",
		},
		{
			Name:          "Invalid",
			Token:         invalidToken,
			ExpectedError: "invalid token",
		},
		{
			Name:               "Expired Disabled",
			Token:              expiredToken,
			DisableExpireCheck: true,
		},
	}

	for _, test := range tests {
		validator.DisableExpireCheck(test.DisableExpireCheck)
		_, err := validator.ValidateToken(test.Token)
		if err != nil && err.Error() != test.ExpectedError {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedError, err.Error())
		}
		if test.ExpectedError == "" && err != nil {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedError, err.Error())
		}
	}
}

func TestGetPayload(t *testing.T) {
	payload, err := GetPayload(expiredToken)
	if err != nil {
		t.Errorf(testhelper.TestErrorTemplate, "Payload", "No error", err)
	}
	if payload == nil {
		t.Errorf(testhelper.TestErrorTemplate, "Payload", "Not nil", payload)
	}
	if len(payload) == 0 {
		t.Errorf(testhelper.TestErrorTemplate, "Payload", "Has data", len(payload))
	}
}

func TestGetAuthorizationHeader(t *testing.T) {
	type testCase struct {
		Name          string
		Request       *http.Request
		ExpectedToken string
		ExpectedError string
	}

	tests := []testCase{
		{
			Name:          "No header",
			Request:       testhelper.MakeTestRequestWithHeaders(http.MethodGet, "/", map[string]string{}, nil),
			ExpectedError: "no authorization header",
		},
		{
			Name: "Blank header",
			Request: testhelper.MakeTestRequestWithHeaders(http.MethodGet, "/", map[string]string{
				"Authorization": "",
			}, nil),
			ExpectedError: "no authorization header",
		},
		{
			Name: "No Bearer",
			Request: testhelper.MakeTestRequestWithHeaders(http.MethodGet, "/", map[string]string{
				"Authorization": "XXXXXXXXXXX",
			}, nil),
			ExpectedError: "missing Bearer",
		},
		{
			Name: "Good header",
			Request: testhelper.MakeTestRequestWithHeaders(http.MethodGet, "/", map[string]string{
				"Authorization": "Bearer XXXXXXXXXXX",
			}, nil),
			ExpectedToken: "XXXXXXXXXXX",
		},
	}

	for _, test := range tests {
		auth, err := GetAuthorizationHeader(test.Request)
		if err != nil && err.Error() != test.ExpectedError {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedError, err.Error())
		}
		if test.ExpectedError == "" && err != nil {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedError, err.Error())
		}
		if auth.Token != test.ExpectedToken {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedToken, auth.Token)
		}
	}
}
