package connectsrv_test

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

	"go.opentelemetry.io/otel/attribute"
	sdkmetric "go.opentelemetry.io/otel/sdk/metric"
	"go.opentelemetry.io/otel/sdk/metric/metricdata"

	"scrabble/gateway/internal/config"
	"scrabble/gateway/internal/connectsrv"
	"scrabble/gateway/internal/ratelimit"
)

// TestUnsupportedEngineHandler drives the /telemetry/unsupported beacon route end to end: a POST
// increments unsupported_engine_total with the normalised labels and replies 204; a GET is 405.
func TestUnsupportedEngineHandler(t *testing.T) {
	reader := sdkmetric.NewManualReader()
	meter := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)).Meter("test")
	edge := connectsrv.NewServer(connectsrv.Deps{
		Limiter:   ratelimit.New(),
		RateLimit: config.DefaultRateLimit(),
		Meter:     meter,
	})
	srv := httptest.NewServer(edge.HTTPHandler())
	defer srv.Close()
	url := srv.URL + "/telemetry/unsupported"

	// A GET is rejected.
	getResp, err := http.Get(url)
	if err != nil {
		t.Fatalf("get: %v", err)
	}
	getResp.Body.Close()
	if getResp.StatusCode != http.StatusMethodNotAllowed {
		t.Errorf("GET status = %d, want 405", getResp.StatusCode)
	}

	// A POST is accepted (204) and folded into the counter with normalised labels.
	body := `{"reason":"no_bigint","chromium":"66","version":"v1.2.3","ua":"Mozilla/5.0 ... Chrome/66"}`
	resp, err := http.Post(url, "application/json", bytes.NewBufferString(body))
	if err != nil {
		t.Fatalf("post: %v", err)
	}
	resp.Body.Close()
	if resp.StatusCode != http.StatusNoContent {
		t.Errorf("POST status = %d, want 204", resp.StatusCode)
	}

	var rm metricdata.ResourceMetrics
	if err := reader.Collect(context.Background(), &rm); err != nil {
		t.Fatalf("collect: %v", err)
	}
	var total int64
	for _, sm := range rm.ScopeMetrics {
		for _, md := range sm.Metrics {
			if md.Name != "unsupported_engine_total" {
				continue
			}
			sum, ok := md.Data.(metricdata.Sum[int64])
			if !ok {
				t.Fatalf("unsupported_engine_total is not an int64 sum")
			}
			for _, dp := range sum.DataPoints {
				reason, _ := dp.Attributes.Value(attribute.Key("reason"))
				chromium, _ := dp.Attributes.Value(attribute.Key("chromium"))
				if reason.AsString() != "no_bigint" || chromium.AsString() != "66" {
					t.Errorf("labels = %s/%s, want no_bigint/66", reason.AsString(), chromium.AsString())
				}
				total += dp.Value
			}
		}
	}
	if total != 1 {
		t.Errorf("unsupported_engine_total = %d, want 1", total)
	}
}
