package app

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

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

func TestIsDeterministicGiteaProviderRejection(t *testing.T) {
	t.Parallel()

	for _, statusCode := range []int{
		http.StatusBadRequest,
		http.StatusUnauthorized,
		http.StatusForbidden,
		http.StatusNotFound,
		http.StatusMethodNotAllowed,
		http.StatusGone,
		http.StatusUnprocessableEntity,
	} {
		statusCode := statusCode
		t.Run(fmt.Sprintf("permanent_%d", statusCode), func(t *testing.T) {
			t.Parallel()
			err := fmt.Errorf("provider call: %w", &giteaUpstreamError{
				StatusCode: statusCode,
				Body:       "sensitive upstream detail",
			})
			require.True(t, isDeterministicGiteaProviderRejection(err))
		})
	}

	for _, statusCode := range []int{
		http.StatusRequestTimeout,
		http.StatusConflict,
		http.StatusTooEarly,
		http.StatusTooManyRequests,
		http.StatusInternalServerError,
		http.StatusBadGateway,
		http.StatusServiceUnavailable,
	} {
		statusCode := statusCode
		t.Run(fmt.Sprintf("transient_%d", statusCode), func(t *testing.T) {
			t.Parallel()
			err := &giteaUpstreamError{StatusCode: statusCode}
			require.False(t, isDeterministicGiteaProviderRejection(err))
		})
	}

	t.Run("transport", func(t *testing.T) {
		t.Parallel()
		require.False(t, isDeterministicGiteaProviderRejection(errors.New("connection reset")))
	})
}

func TestFormatGiteaApprovalProviderErrorHidesPermanentUpstreamDetails(t *testing.T) {
	t.Parallel()

	upstream := &giteaUpstreamError{
		StatusCode: http.StatusForbidden,
		Body:       `{"message":"token secret cannot create hook","url":"https://gitea.internal/api/v1/repos/acme/agentteam/hooks"}`,
	}
	err := formatGiteaApprovalProviderError("Failed to create Gitea webhook", upstream)

	require.ErrorIs(t, err, ErrGiteaConnectionConfigurationFailed)
	require.ErrorIs(t, err, ErrBadRequest)
	require.EqualError(t, err, "Failed to create Gitea webhook")
	require.NotContains(t, err.Error(), "token secret")
	require.NotContains(t, err.Error(), "gitea.internal")
}

func TestFormatGiteaApprovalProviderErrorKeepsTransientFailuresRetryable(t *testing.T) {
	t.Parallel()

	for _, statusCode := range []int{http.StatusTooManyRequests, http.StatusServiceUnavailable} {
		err := formatGiteaApprovalProviderError("Failed to configure Gitea connection", &giteaUpstreamError{
			StatusCode: statusCode,
		})
		require.NotErrorIs(t, err, ErrGiteaConnectionConfigurationFailed)
		require.ErrorIs(t, err, ErrBadRequest)
	}
	err := formatGiteaApprovalProviderError("Failed to configure Gitea connection", errors.New("connection reset"))
	require.NotErrorIs(t, err, ErrGiteaConnectionConfigurationFailed)
	require.ErrorIs(t, err, ErrBadRequest)
}
