package gitlab

import (
	"io"
	"net/http"
	"net/url"
	"strings"
	"testing"

	"buf.build/go/protovalidate"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/httpz"
)

func TestDefaultErrorHandlerWithReason_DiscardUnknownFields(t *testing.T) {
	// GIVEN
	u, err := url.Parse("https://gitlab.example.com/api/v4/anything")
	require.NoError(t, err)

	resp := &http.Response{
		Request:    &http.Request{URL: u},
		StatusCode: http.StatusUnauthorized,
		Header:     http.Header{httpz.ContentTypeHeader: {"application/json"}},
		Body:       io.NopCloser(strings.NewReader(`{"message": "anything", "ignored": "ignored"}`)),
	}

	// WHEN
	err = DefaultErrorHandlerWithReason(resp)

	// THEN
	require.EqualError(t, err, "HTTP status code: 401 for path /api/v4/anything with reason anything")
}

func TestHCheckContentType(t *testing.T) {
	v, err := protovalidate.New()
	require.NoError(t, err)
	t.Run("no content", func(t *testing.T) {
		called := false
		h := hCheckContentType("text/plain", func(v protovalidate.Validator, resp *http.Response) error {
			called = true
			return nil
		})
		err = h(v, &http.Response{
			StatusCode: http.StatusNoContent,
		})
		require.NoError(t, err)
		assert.True(t, called)
	})
	t.Run("invalid type", func(t *testing.T) {
		h := hCheckContentType("text/plain", func(v protovalidate.Validator, resp *http.Response) error {
			assert.Fail(t, "unexpected call")
			return nil
		})
		err = h(v, &http.Response{
			StatusCode: http.StatusOK,
			Header: http.Header{
				httpz.ContentTypeHeader: {"application/json"},
			},
		})
		require.EqualError(t, err, `unexpected Content-Type in response: "application/json"`)
	})
	t.Run("more than one type", func(t *testing.T) {
		h := hCheckContentType("text/plain", func(v protovalidate.Validator, resp *http.Response) error {
			assert.Fail(t, "unexpected call")
			return nil
		})
		err = h(v, &http.Response{
			StatusCode: http.StatusOK,
			Header: http.Header{
				httpz.ContentTypeHeader: {"text/plain", "application/json"},
			},
		})
		require.EqualError(t, err, `expecting single Content-Type in response, got: ["text/plain" "application/json"]`)
	})
	t.Run("missing type", func(t *testing.T) {
		h := hCheckContentType("text/plain", func(v protovalidate.Validator, resp *http.Response) error {
			assert.Fail(t, "unexpected call")
			return nil
		})
		err = h(v, &http.Response{
			StatusCode: http.StatusOK,
		})
		require.EqualError(t, err, `expecting single Content-Type in response, got: []`)
	})
	t.Run("correct type", func(t *testing.T) {
		called := false
		h := hCheckContentType("text/plain", func(v protovalidate.Validator, resp *http.Response) error {
			called = true
			return nil
		})
		err = h(v, &http.Response{
			StatusCode: http.StatusOK,
			Header: http.Header{
				httpz.ContentTypeHeader: {"text/plain"},
			},
		})
		require.NoError(t, err)
		assert.True(t, called)
	})
}
