package gateway

import (
	"context"
	"errors"
	"net/http"
	"net/http/httptest"
	"testing"

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

func TestHTTPWorkspaceIdentityResolverClassifiesClientAndServiceFailures(t *testing.T) {
	t.Parallel()
	for _, test := range []struct {
		name       string
		status     int
		unresolved bool
	}{
		{name: "malformed input", status: http.StatusBadRequest, unresolved: true},
		{name: "unresolved identity", status: http.StatusUnprocessableEntity, unresolved: true},
		{name: "public credential rejected", status: http.StatusUnauthorized},
		{name: "service credential rejected", status: http.StatusUnauthorized},
		{name: "resolver failed", status: http.StatusInternalServerError},
	} {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
				if test.name == "public credential rejected" {
					writer.Header().Set("Content-Type", "application/json")
					writer.WriteHeader(test.status)
					_, _ = writer.Write([]byte(`{"code":"workspace_identity_unauthorized"}`))
					return
				}
				writer.WriteHeader(test.status)
			}))
			t.Cleanup(server.Close)
			resolver, err := NewHTTPWorkspaceIdentityResolver(server.URL, "internal-token", server.Client())
			require.NoError(t, err)

			_, err = resolver.ResolveWorkspaceIdentity(context.Background(), WorkspaceIdentityRequest{Method: http.MethodGet, Path: "/owner/repo.git/info/refs"})
			if test.unresolved {
				require.ErrorIs(t, err, ErrWorkspaceIdentityUnresolved)
				return
			}
			if test.name == "public credential rejected" {
				require.ErrorIs(t, err, ErrWorkspaceIdentityUnauthorized)
				return
			}
			require.Error(t, err)
			require.False(t, errors.Is(err, ErrWorkspaceIdentityUnresolved))
		})
	}
}

func TestHTTPWorkspaceIdentityResolverAcceptsExactlyOneRouteIdentity(t *testing.T) {
	t.Parallel()
	for _, test := range []struct {
		name       string
		response   string
		want       RouteIdentity
		unresolved bool
	}{
		{name: "workspace", response: `{"workspaceId":"wsp_a"}`, want: RouteIdentity{WorkspaceID: "wsp_a"}},
		{name: "missing workspace", response: `{}`, unresolved: true},
	} {
		t.Run(test.name, func(t *testing.T) {
			server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
				writer.Header().Set("Content-Type", "application/json")
				_, _ = writer.Write([]byte(test.response))
			}))
			t.Cleanup(server.Close)
			resolver, err := NewHTTPWorkspaceIdentityResolver(server.URL, "internal-token", server.Client())
			require.NoError(t, err)
			identity, err := resolver.ResolveWorkspaceIdentity(context.Background(), WorkspaceIdentityRequest{Method: http.MethodGet, Path: "/agent/repo.git/info/refs"})
			if test.unresolved {
				require.ErrorIs(t, err, ErrWorkspaceIdentityUnresolved)
				return
			}
			require.NoError(t, err)
			require.Equal(t, test.want, identity)
		})
	}
}
