package clustergateway

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

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

func TestGetComponentRawMetrics_URLConstruction(t *testing.T) {
	const (
		sharedPoolID      = "pool-123"
		wantComponentType = "tikv"
		wantPodName       = "db-tikv-0"
		fakeMetricsBody   = "tikv_store_size_bytes 100\n"
	)

	var receivedPath string

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		receivedPath = r.URL.Path
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(fakeMetricsBody))
	}))
	defer server.Close()

	client := newTestClient()
	sharedPool := newTestSharedPool(sharedPoolID, server.URL)

	body, err := client.GetComponentRawMetrics(context.Background(), sharedPool, wantComponentType, wantPodName)
	require.NoError(t, err)
	assert.Equal(t, []byte(fakeMetricsBody), body)

	dataplaneNamespace := sharedPool.GetDataPlaneNamespace()
	wantPath := "/cluster-agent/" + dataplaneNamespace + "/api/v1/clusters/" + sharedPoolID + "/components/" + wantComponentType + "/" + wantPodName + "/metrics"
	assert.Equal(t, wantPath, receivedPath,
		"path should have componentType and podName substituted; unsubstituted {placeholders} indicate a constant mismatch")
}

func TestGetComponentRawMetrics_NonOKStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusServiceUnavailable)
		_, _ = w.Write([]byte("tikv unavailable"))
	}))
	defer server.Close()

	client := newTestClient()
	sharedPool := newTestSharedPool("pool-456", server.URL)

	_, err := client.GetComponentRawMetrics(context.Background(), sharedPool, "tikv", "db-tikv-0")
	require.Error(t, err)
	assert.Contains(t, err.Error(), "GetComponentRawMetrics response not expected")
}

func TestGetComponentNodeMetrics_URLConstruction(t *testing.T) {
	const (
		sharedPoolID      = "pool-123"
		wantComponentType = "tikv"
		wantPodName       = "db-tikv-0"
		fakeMetricsBody   = "node_disk_reads_completed_total 42\n"
	)

	var receivedPath string

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		receivedPath = r.URL.Path
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(fakeMetricsBody))
	}))
	defer server.Close()

	client := newTestClient()
	sharedPool := newTestSharedPool(sharedPoolID, server.URL)

	body, err := client.GetComponentNodeMetrics(context.Background(), sharedPool, wantComponentType, wantPodName)
	require.NoError(t, err)
	assert.Equal(t, []byte(fakeMetricsBody), body)

	dataplaneNamespace := sharedPool.GetDataPlaneNamespace()
	wantPath := "/cluster-agent/" + dataplaneNamespace + "/api/v1/clusters/" + sharedPoolID + "/components/" + wantComponentType + "/" + wantPodName + "/node-metrics"
	assert.Equal(t, wantPath, receivedPath,
		"path should end in /node-metrics; unsubstituted {placeholders} indicate a constant mismatch")
}

func TestGetComponentNodeMetrics_NonOKStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusServiceUnavailable)
		_, _ = w.Write([]byte("node-exporter unavailable"))
	}))
	defer server.Close()

	client := newTestClient()
	sharedPool := newTestSharedPool("pool-456", server.URL)

	_, err := client.GetComponentNodeMetrics(context.Background(), sharedPool, "tikv", "db-tikv-0")
	require.Error(t, err)
	assert.Contains(t, err.Error(), "GetComponentNodeMetrics response not expected")
}
