// This file verifies O11Y suite concurrency, deterministic ordering, and failure collection.
package evaluation

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"sync/atomic"
	"testing"
	"time"
)

func TestFetchO11YSuiteUsesBoundedWorkersAndCollectsFailures(t *testing.T) {
	decisionAt := time.Date(2026, 6, 13, 13, 35, 0, 0, time.UTC)
	var active atomic.Int32
	var maximum atomic.Int32
	var requests atomic.Int32
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requests.Add(1)
		current := active.Add(1)
		defer active.Add(-1)
		for {
			observed := maximum.Load()
			if current <= observed || maximum.CompareAndSwap(observed, current) {
				break
			}
		}
		time.Sleep(20 * time.Millisecond)

		if r.URL.Query().Get("query") == "case-b" {
			http.Error(w, "expected test failure", http.StatusInternalServerError)
			return
		}
		fmt.Fprintf(w, `{"status":"success","isPartial":false,"data":{"resultType":"matrix","result":[{"metric":{"instance":"pod-0"},"values":[[%d,"1"]]}]}}`, decisionAt.Unix())
	}))
	t.Cleanup(server.Close)

	specs := make([]*O11YExportSpec, 0, 3)
	for _, caseID := range []string{"case-c", "case-a", "case-b"} {
		spec := validO11YExportSpec(server.URL, decisionAt)
		spec.Case.ID = caseID
		spec.Sources = spec.Sources[:1]
		spec.Sources[0].Queries = spec.Sources[0].Queries[:1]
		spec.Sources[0].Queries[0].Name = caseID
		spec.Sources[0].Queries[0].PromQL = caseID
		specs = append(specs, spec)
	}

	outputDir := filepath.Join(t.TempDir(), "suite")
	results, err := FetchO11YSuite(context.Background(), specs, O11YSuiteOptions{
		Client:      server.Client(),
		BearerToken: testBearerToken,
		OutputDir:   outputDir,
		CacheDir:    filepath.Join(t.TempDir(), "cache"),
		Workers:     2,
	})
	if err == nil {
		t.Fatal("FetchO11YSuite() error = nil, want aggregate case failure")
	}
	if got := requests.Load(); got != 3 {
		t.Fatalf("HTTP requests = %d, want all 3 cases processed", got)
	}
	if got := maximum.Load(); got != 2 {
		t.Errorf("maximum concurrent requests = %d, want 2", got)
	}
	if len(results) != 3 || results[0].CaseID != "case-a" || results[1].CaseID != "case-b" || results[2].CaseID != "case-c" {
		t.Fatalf("results = %+v, want deterministic case order", results)
	}
	if results[0].Error != "" || results[1].Error == "" || results[2].Error != "" {
		t.Errorf("result errors = %q, %q, %q; want only case-b failure", results[0].Error, results[1].Error, results[2].Error)
	}
	for _, caseID := range []string{"case-a", "case-c"} {
		if _, statErr := os.Stat(filepath.Join(outputDir, "tidb", PointInTimeCasesDirectory, caseID+".json")); statErr != nil {
			t.Errorf("successful case %s output: %v", caseID, statErr)
		}
	}
}
