package mocks

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"regexp"
	"testing"

	th "github.com/fiskerinc/cloud-services/pkg/testhelper"
	"github.com/fiskerinc/cloud-services/pkg/validator"
	"github.com/julienschmidt/httprouter"
)

const IGNORE_EXPECTED_RESP = "IGNORE_EXPECTED_RESP"

// Deprecated. Use modules_go/testrunner/test_case.go and modules_go/db/queries/mocks/dbtestcase.go
type DBHttpTest struct {
	Name                  string
	Request               *http.Request
	ExpectedStatus        int
	ExpectedResponse      string
	ExpectedResponseRegex *regexp.Regexp
	ValidateResponse      bool `default:"false"`

	DBTestCase
}

func (test *DBHttpTest) ValidateHttp(t *testing.T, w *httptest.ResponseRecorder) {
	if test.ExpectedStatus != w.Result().StatusCode {
		th.Equal(t, fmt.Sprintf("%s status code", test.Name), test.ExpectedStatus, w.Result().StatusCode)
	}

	if test.ExpectedResponseRegex != nil {
		if !test.ExpectedResponseRegex.Match(w.Body.Bytes()) {
			th.Equal(t, fmt.Sprintf("%s body", test.Name), test.ExpectedResponseRegex, w.Body.String())
		}
	} else if test.ExpectedResponse != IGNORE_EXPECTED_RESP && test.ExpectedResponse != w.Body.String() {
		th.Equal(t, fmt.Sprintf("%s body", test.Name), test.ExpectedResponse, w.Body.String())
	}

	if test.ValidateResponse {
		err := validator.ValidateStruct(w.Body)
		th.NoError(t, fmt.Sprintf("%s validate body", test.Name), err)
	}
}

func RunDBTests(t *testing.T, tests []DBHttpTest, handler http.HandlerFunc, mock DBMockHelperInterface) {
	for _, test := range tests {
		test.SetupDB(mock)

		w := th.ExecHTTPHandler(handler, test.Request)

		test.ValidateHttp(t, w)
		test.Validate(t, test.Name, mock)
	}
}

func ExecHTTPRouterHandler(handler http.HandlerFunc, routePath string, request *http.Request) *httptest.ResponseRecorder {
	recorder := httptest.NewRecorder()

	router := httprouter.New()
	router.HandlerFunc(request.Method, routePath, handler)
	router.ServeHTTP(recorder, request)

	return recorder
}

func RunParamHttpTests(t *testing.T, tests []DBHttpTest, handler http.HandlerFunc, routePath string, mock DBMockHelperInterface) {
	for _, test := range tests {
		test.SetupDB(mock)

		w := ExecHTTPRouterHandler(handler, routePath, test.Request)

		test.ValidateHttp(t, w)
		test.Validate(t, test.Name, mock)
	}
}
