package handlers_test

import (
	"context"
	"fmt"
	"net/http"
	"testing"

	"otaupdate/handlers"
	"otaupdate/services"

	m "github.com/fiskerinc/cloud-services/pkg/common"
	orm "github.com/fiskerinc/cloud-services/pkg/db/queries"
	mo "github.com/fiskerinc/cloud-services/pkg/db/queries/mocks"
	th "github.com/fiskerinc/cloud-services/pkg/testhelper"
	"github.com/julienschmidt/httprouter"
)

func TestHandleGetCarsByManifest(t *testing.T) {
	mock := mo.MockCars{}
	mockMan := mo.MockUpdateManifests{
		LoadResponse: &m.UpdateManifest{},
	}
	services.GetDB().SetCars(&mock)
	services.GetDB().SetUpdateManifests(&mockMan)
	expectedCar := `{"vin":"1G1FP87S3GN100062","country":"US","year":2022,"model":"Ocean","trim":"Base","powertrain":"MD23","restraint":"None","body_type":"truck"}`
	expectedResp := fmt.Sprintf(`{"data":[%s],"total":1}`, expectedCar)
	expectedEmptyResp := `{"data":[]}`
	listData := []m.Car{
		{
			VIN:        "1G1FP87S3GN100062",
			Model:      "Ocean",
			Year:       2022,
			Trim:       "Base",
			Country:    "US",
			Powertrain: "MD23",
			Restraint:  "None",
			BodyType:   "truck",
		},
	}
	p := httprouter.Params{
		{"manifest_id", "8"},
	}
	ctx := context.WithValue(context.Background(), httprouter.ParamsKey, p)
	invalidP := httprouter.Params{
		{"manifest_id", "o"},
	}
	invalidCtx := context.WithValue(context.Background(), httprouter.ParamsKey, invalidP)
	tests := []mo.DBHttpTest{
		{
			Name: "Success",
			Request: th.MakeTestRequest(http.MethodGet, "http://example.com/manifests/8/vehicles", nil).
				WithContext(ctx),
			ExpectedStatus:   http.StatusOK,
			ExpectedResponse: expectedResp,
			DBTestCase: mo.DBTestCase{
				ExpectedPage: &orm.PageQueryOptions{
					Limit:  orm.PageQueryOptionsLimitMaximum,
					Offset: 0,
				},
				MockListResponse: listData,
			},
		},
		{
			Name: "Empty",
			Request: th.MakeTestRequest(http.MethodGet, "http://example.com/manifests/8/vehicles", nil).
				WithContext(ctx),
			ExpectedStatus:   http.StatusOK,
			ExpectedResponse: expectedEmptyResp,
			DBTestCase: mo.DBTestCase{
				ExpectedPage: &orm.PageQueryOptions{
					Limit:  orm.PageQueryOptionsLimitMaximum,
					Offset: 0,
				},
				MockListResponse: nil,
			},
		},
		{
			Name: "Invalid param",
			Request: th.MakeTestRequest(http.MethodGet, "http://example.com/manifests/8/vehicles", nil).
				WithContext(invalidCtx),
			ExpectedStatus:   http.StatusBadRequest,
			ExpectedResponse: `{"message":"strconv.Atoi: parsing \"o\": invalid syntax","error":"Bad Request"}`,
		},
		{
			Name: "Error",
			Request: th.MakeTestRequest(http.MethodGet, "http://example.com/manifests/8/vehicles", nil).
				WithContext(ctx),
			ExpectedStatus:   http.StatusServiceUnavailable,
			ExpectedResponse: `{"message":"something went wrong","error":"Service Unavailable"}`,
			DBTestCase: mo.DBTestCase{
				ExpectedPage: &orm.PageQueryOptions{
					Limit:  orm.PageQueryOptionsLimitMaximum,
					Offset: 0,
				},
				MockError: fmt.Errorf("something went wrong"),
			},
		},
		{
			Name: "Wrong limit, -100",
			Request: th.MakeTestRequest(http.MethodGet, "http://example.com/manifests/8/vehicles?limit=-100", nil).
				WithContext(ctx),
			ExpectedStatus:   http.StatusBadRequest,
			ExpectedResponse: `{"message":"Limit less than 0","error":"Bad Request"}`,
		},
		{
			Name: "Wrong limit, 1000",
			Request: th.MakeTestRequest(http.MethodGet, "http://example.com/manifests/8/vehicles?limit=1000", nil).
				WithContext(ctx),
			ExpectedStatus:   http.StatusBadRequest,
			ExpectedResponse: `{"message":"Limit greater than 100","error":"Bad Request"}`,
		},
	}

	mo.RunDBTests(t, tests, handlers.HandleGetCarsByManifest, &mock)
}
