package vmquery

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"

	"github.com/tidbcloud/observability/vm-migration/internal/schema"
)

// startExportServer starts a loopback server for ExportShard probes and
// registers cleanup. The returned options point at the server with a 5s
// timeout; override fields per case.
func startExportServer(t *testing.T, h http.HandlerFunc) ExportOptions {
	t.Helper()
	srv := httptest.NewServer(h)
	t.Cleanup(srv.Close)
	return ExportOptions{
		SourceURLTemplate: srv.URL + "/select/{tenant}/prometheus",
		Timeout:           5 * time.Second,
	}
}

func TestExportShard(t *testing.T) {
	shard := schema.Shard{
		ShardID:   "abc",
		Tenant:    "1001:0",
		TimeStart: "2026-06-16T00:00:00Z",
		TimeEnd:   "2026-06-17T00:00:00Z",
	}

	t.Run("Success", func(t *testing.T) {
		body := strings.Repeat("x", 12345)
		opts := startExportServer(t, func(w http.ResponseWriter, _ *http.Request) {
			w.WriteHeader(http.StatusOK)
			fmt.Fprint(w, body)
		})
		opts.Match = MatchAll
		res := ExportShard(context.Background(), &http.Client{Timeout: 5 * time.Second}, shard, opts)
		assert.Empty(t, res.Error, "Error should be empty")
		assert.Equal(t, int64(len(body)), res.Bytes)
		assert.Equal(t, "abc", res.ShardID)
	})

	t.Run("HTTPError", func(t *testing.T) {
		opts := startExportServer(t, func(w http.ResponseWriter, _ *http.Request) {
			w.WriteHeader(http.StatusInternalServerError)
			fmt.Fprint(w, "boom")
		})
		res := ExportShard(context.Background(), &http.Client{Timeout: 5 * time.Second}, shard, opts)
		assert.NotEmpty(t, res.Error, "Error should contain HTTP 500 message")
	})

	t.Run("PreCancelledContext", func(t *testing.T) {
		opts := startExportServer(t, func(w http.ResponseWriter, r *http.Request) {
			<-r.Context().Done()
		})
		opts.Timeout = 30 * time.Second
		ctx, cancel := context.WithCancel(context.Background())
		cancel()
		res := ExportShard(ctx, &http.Client{Timeout: 30 * time.Second}, shard, opts)
		assert.NotEmpty(t, res.Error, "Error should contain ctx cancellation")
	})

	t.Run("DefaultMatchAll", func(t *testing.T) {
		var got string
		opts := startExportServer(t, func(w http.ResponseWriter, r *http.Request) {
			_ = r.ParseForm()
			got = r.FormValue("match[]")
			w.WriteHeader(http.StatusOK)
		})
		_ = ExportShard(context.Background(), &http.Client{Timeout: 5 * time.Second}, shard, opts)
		assert.Equal(t, MatchAll, got, "match[] should default to MatchAll")
	})
}
