package clinic_internal_api

import (
	"context"
	"encoding/json"
	"errors"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"

	"github.com/stretchr/testify/require"
	"go.opentelemetry.io/otel/trace"
)

func TestResourceClientUsesFixedInternalPathAndPreservesPayloadNumbers(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, http.MethodGet, r.Method)
		require.Equal(t, "/clinic/api/v1/internal/data-proxy/v1/orgs/123/clusters/cluster-a/activities", r.URL.Path)
		require.Equal(t, "10", r.URL.Query().Get("begin_ts"))
		require.Empty(t, r.Header.Get("Authorization"))
		require.Empty(t, r.Header.Get("Cookie"))
		require.Equal(t, "22222222222222222222222222222222", r.Header.Get("X-Trace-ID"))
		w.Header().Set("Content-Type", "application/json")
		_, _ = w.Write([]byte(`{"activities":[{"activity_id":"a","payload":{"large":9007199254740993}}],"partial":true,"cursor":"next"}`))
	}))
	defer server.Close()

	client := NewClient(server.URL)
	spanContext := trace.NewSpanContext(trace.SpanContextConfig{
		TraceID: trace.TraceID{0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22},
		SpanID:  trace.SpanID{1},
	})
	ctx := trace.ContextWithSpanContext(context.Background(), spanContext)
	result, err := client.ListActivities(ctx, 123, "cluster-a", url.Values{"begin_ts": {"10"}})
	require.NoError(t, err)
	require.Len(t, result.Activities, 1)
	require.Equal(t, json.Number("9007199254740993"), result.Activities[0].Payload.(map[string]any)["large"])
	require.True(t, result.Partial)
	require.Equal(t, "next", result.Cursor)
}

func TestResourceClientReturnsTypedStatusWithoutLeakingBody(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
		http.Error(w, "internal secret detail", http.StatusNotFound)
	}))
	defer server.Close()

	client := NewClient(server.URL)
	_, err := client.GetOrgClusterMetadata(context.Background(), 123, "missing")
	var upstreamError *UpstreamError
	require.ErrorAs(t, err, &upstreamError)
	require.Equal(t, http.StatusNotFound, upstreamError.StatusCode)
	require.NotContains(t, err.Error(), "internal secret detail")
}

func TestResourceClientRejectsRedirect(t *testing.T) {
	targetCalled := false
	target := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {
		targetCalled = true
	}))
	defer target.Close()
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, target.URL, http.StatusFound)
	}))
	defer server.Close()

	client := NewClient(server.URL)
	_, err := client.GetClusterMetadata(context.Background(), "cluster-a")
	var upstreamError *UpstreamError
	require.True(t, errors.As(err, &upstreamError))
	require.Equal(t, http.StatusFound, upstreamError.StatusCode)
	require.False(t, targetCalled)
}
