package runner_test

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

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/extension/runner"
)

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

	var calls int
	base := roundTripFunc(func(request *http.Request) (*http.Response, error) {
		calls++
		require.Equal(t, "https://mcp.example.com/mcp", request.URL.String())
		require.Equal(t, "secret-value", request.Header.Get("X-MCP-Key"))
		return &http.Response{
			StatusCode: http.StatusOK,
			Header:     make(http.Header),
			Body:       io.NopCloser(strings.NewReader(`{}`)),
			Request:    request,
		}, nil
	})
	transport, err := runner.NewFixedProviderTransport(
		runner.FixedProviderTransportOptions{
			Endpoint: "https://mcp.example.com/mcp",
			Auth: runner.AuthSpec{
				Kind:   runner.AuthHeader,
				Header: "X-MCP-Key",
				Fields: []runner.CredentialField{
					{Name: "apiKey", Required: true, Secret: true},
				},
			},
			Credentials: runner.Credentials{"apiKey": "secret-value"},
			Transport:   base,
		},
	)
	require.NoError(t, err)

	request, err := http.NewRequest(http.MethodPost, "https://mcp.example.com/mcp", nil)
	require.NoError(t, err)
	response, err := transport.RoundTrip(request)
	require.NoError(t, err)
	require.NoError(t, response.Body.Close())
	require.Equal(t, 1, calls)

	escaped, err := http.NewRequest(http.MethodPost, "https://other.example.com/mcp", nil)
	require.NoError(t, err)
	response, err = transport.RoundTrip(escaped)
	require.Nil(t, response)
	require.Equal(t, runner.ErrorValidation, runner.CodeOf(err))
	require.Equal(t, 1, calls)
	require.Empty(t, escaped.Header.Get("X-MCP-Key"))
}

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

	testCases := []runner.FixedProviderTransportOptions{
		{
			Endpoint: "http://mcp.example.com/mcp",
			Auth:     runner.AuthSpec{Kind: runner.AuthNone},
		},
		{
			Endpoint: "https://mcp.example.com/mcp?key=secret",
			Auth:     runner.AuthSpec{Kind: runner.AuthNone},
		},
		{
			Endpoint: "https://user:password@mcp.example.com/mcp",
			Auth:     runner.AuthSpec{Kind: runner.AuthNone},
		},
		{
			Endpoint: "https://mcp.example.com/mcp",
			Auth: runner.AuthSpec{
				Kind:   runner.AuthHeader,
				Header: "X-MCP-Key",
				Fields: []runner.CredentialField{
					{Name: "apiKey", Required: true, Secret: true},
				},
			},
			Credentials: runner.Credentials{"apiKey": ""},
		},
	}
	for index, options := range testCases {
		transport, err := runner.NewFixedProviderTransport(options)
		require.Nil(t, transport)
		expected := runner.ErrorValidation
		if index == len(testCases)-1 {
			expected = runner.ErrorConnectionUnavailable
		}
		require.Equal(t, expected, runner.CodeOf(err))
		require.NotContains(t, err.Error(), "secret")
		require.NotContains(t, err.Error(), "password")
	}
}

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

	for _, header := range []string{
		"Mcp-Session-Id",
		"Mcp-Protocol-Version",
		"Last-Event-ID",
	} {
		spec := runner.AuthSpec{
			Kind:   runner.AuthHeader,
			Header: header,
			Fields: []runner.CredentialField{
				{Name: "apiKey", Required: true, Secret: true},
			},
		}
		require.Error(t, spec.ValidateSpec(), header)
	}
}

type roundTripFunc func(*http.Request) (*http.Response, error)

func (function roundTripFunc) RoundTrip(
	request *http.Request,
) (*http.Response, error) {
	return function(request)
}
