package loggerdataresp_test

import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"

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

func TestBadDataErrorResp(t *testing.T) {
	type testcase struct {
		Name           string
		Err            error
		ExpectedBody   string
		ExpectedStatus int
	}

	tests := []testcase{
		{
			Name: "Field",
			Err: &ve.FieldError{
				ErrorMsg: "TEST ERROR",
			},
			ExpectedBody:   `{"message":"TEST ERROR","error":"Bad Request"}`,
			ExpectedStatus: http.StatusBadRequest,
		},
		{
			Name: "Postgres Constraint",
			Err: &MockPGError{
				FieldDesc: "THIS IS A TEST",
				Integrity: true,
			},
			ExpectedBody:   `{"message":"THIS IS A TEST","error":"Bad Request"}`,
			ExpectedStatus: http.StatusBadRequest,
		},
		{
			Name: "Postgres Non-Constraint",
			Err: &MockPGError{
				ErrorDesc: "GENERAL ERROR",
				Integrity: false,
			},
			ExpectedBody:   `{"message":"GENERAL ERROR","error":"Service Unavailable"}`,
			ExpectedStatus: http.StatusServiceUnavailable,
		},
		{
			Name:           "SAP not available error",
			Err:            errors.New("calling SAP failed"),
			ExpectedBody:   `{"message":"calling SAP failed","error":"Service Unavailable"}`,
			ExpectedStatus: http.StatusServiceUnavailable,
		},
		{
			Name:           "EOF error check",
			Err:            io.EOF,
			ExpectedBody:   `{"message":"EOF","error":"Not Found"}`,
			ExpectedStatus: http.StatusNotFound,
		},
		{
			Name:           "General",
			Err:            fmt.Errorf("GENERAL ERROR"),
			ExpectedBody:   `{"message":"GENERAL ERROR","error":"Service Unavailable"}`,
			ExpectedStatus: http.StatusServiceUnavailable,
		},
	}

	for _, test := range tests {
		res := httptest.NewRecorder()
		loggerdataresp.BadDataErrorResp(res, test.Err, http.StatusServiceUnavailable, loggerdataresp.EofErrorCheck)

		if res.Result().StatusCode != test.ExpectedStatus {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedStatus, res.Result().StatusCode)
		}

		body := res.Body.String()
		if body != test.ExpectedBody {
			t.Errorf(testhelper.TestErrorTemplate, test.Name, test.ExpectedBody, body)
		}
	}
}

type MockPGError struct {
	ErrorDesc string
	FieldDesc string
	Integrity bool
}

func (mpg *MockPGError) Error() string {
	return mpg.ErrorDesc
}

func (mpg *MockPGError) Field(field byte) string {
	return mpg.FieldDesc
}

func (mpg *MockPGError) IntegrityViolation() bool {
	return mpg.Integrity
}
