package handlers_test

import (
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"otaupdate/handlers"
	"otaupdate/services"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/db/queries"
	"github.com/fiskerinc/cloud-services/pkg/db/queries/mocks"
	th "github.com/fiskerinc/cloud-services/pkg/testhelper"

	"github.com/stretchr/testify/assert"
)

func TestHandleAPICallsGet(t *testing.T) {
	db := services.GetDB()
	timeMock := time.Date(2022, 3, 11, 3, 16, 12, 0, time.UTC)
	callsList := []common.APICall{
		{
			ClientID:   "jkm@fisker.com",
			AccessType: "jwt_token",
			Method:     "GET",
			Endpoint:   "/some/path",
			CreatedAt:  &timeMock,
		},
		{
			ClientID:   "3dec092e-d869-46e3-be85-258aed85b2fc",
			AccessType: "api_token",
			Method:     "GET",
			Endpoint:   "/some/path",
			CreatedAt:  &timeMock,
		},
	}

	tests := map[string]struct {
		urlQ      string
		callsDB   queries.APICallsInterface
		expStatus int
		expBody   string
	}{
		"correct": {
			urlQ: "?from=" + timeMock.Format(time.RFC3339) + "&to=" + timeMock.Format(time.RFC3339) + "&search=text",
			callsDB: &mocks.MockAPICalls{
				SearchMock: func(filter common.APICallsSearch, paging *queries.PageQueryOptions) ([]common.APICall, int, error) {
					assert.Equal(t, common.APICallsSearch{
						Search: "text",
						From:   &timeMock,
						To:     &timeMock,
					}, filter)
					return callsList, 2, nil
				},
			},
			expStatus: http.StatusOK,
			expBody:   `{"data":[{"client_id":"jkm@fisker.com","access_type":"jwt_token","method":"GET","endpoint":"/some/path","created_at":"2022-03-11T03:16:12Z"},{"client_id":"3dec092e-d869-46e3-be85-258aed85b2fc","access_type":"api_token","method":"GET","endpoint":"/some/path","created_at":"2022-03-11T03:16:12Z"}],"total":2}`,
		},
		"correct_no_params": {
			callsDB: &mocks.MockAPICalls{
				SearchMock: func(filter common.APICallsSearch, paging *queries.PageQueryOptions) ([]common.APICall, int, error) {
					return callsList, 2, nil
				},
			},
			expStatus: http.StatusOK,
			expBody:   `{"data":[{"client_id":"jkm@fisker.com","access_type":"jwt_token","method":"GET","endpoint":"/some/path","created_at":"2022-03-11T03:16:12Z"},{"client_id":"3dec092e-d869-46e3-be85-258aed85b2fc","access_type":"api_token","method":"GET","endpoint":"/some/path","created_at":"2022-03-11T03:16:12Z"}],"total":2}`,
		},
		"bad_from": {
			urlQ:      "?from=kk&to=" + timeMock.Format(time.RFC3339) + "&search=text",
			expStatus: http.StatusBadRequest,
			expBody:   `{"message":"parsing time \"kk\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"kk\" as \"2006\"","error":"Bad Request"}`,
		},
		"bad_to": {
			urlQ:      "?from=" + timeMock.Format(time.RFC3339) + "&to=kk&search=text",
			expStatus: http.StatusBadRequest,
			expBody:   `{"message":"parsing time \"kk\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"kk\" as \"2006\"","error":"Bad Request"}`,
		},
		"bad_limit": {
			urlQ:      "?limit=-2",
			expStatus: http.StatusBadRequest,
			expBody:   `{"message":"Limit less than 0","error":"Bad Request"}`,
		},
		"bad_db": {
			callsDB: &mocks.MockAPICalls{
				SearchMock: func(filter common.APICallsSearch, paging *queries.PageQueryOptions) ([]common.APICall, int, error) {
					return nil, 0, someErr
				},
			},
			expStatus: http.StatusServiceUnavailable,
			expBody:   `{"message":"some err","error":"Service Unavailable"}`,
		},
	}

	for tname, tt := range tests {
		t.Run(tname, func(t *testing.T) {
			r := th.MakeTestRequest(http.MethodPost, "http://example.com/apicalls"+tt.urlQ, nil)
			w := httptest.NewRecorder()

			db.SetAPICalls(tt.callsDB)
			handlers.HandleAPICallsGet(w, r)

			assert.Equal(t, tt.expStatus, w.Code)
			assert.Equal(t, tt.expBody, w.Body.String())
		})
	}
}
