package middleware

import (
	"bytes"
	"context"
	"log/slog"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	applog "github.com/pingcap/agent-git-service/internal/logging"
	"github.com/pingcap/agent-git-service/internal/tenant"
)

func TestRequestLogging_ClientClosedStatusLogsAtInfo(t *testing.T) {
	var buf bytes.Buffer
	prev := slog.Default()
	logger := slog.New(slog.NewTextHandler(&buf, nil))
	slog.SetDefault(logger)
	t.Cleanup(func() {
		slog.SetDefault(prev)
	})

	handler := RequestLogging()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(statusClientClosedRequest)
		_, _ = w.Write([]byte(`{"message":"Client Closed Request"}`))
	}))

	req := httptest.NewRequest(http.MethodGet, "/api/v3/repos/acme/demo/issues", nil)
	rr := httptest.NewRecorder()
	handler.ServeHTTP(rr, req)

	logLine := buf.String()
	if !strings.Contains(logLine, "level=INFO") {
		t.Fatalf("expected INFO level log, got %q", logLine)
	}
	if strings.Contains(logLine, "level=WARN") || strings.Contains(logLine, "level=ERROR") {
		t.Fatalf("did not expect warning/error log, got %q", logLine)
	}
	if !strings.Contains(logLine, "status=499") {
		t.Fatalf("expected status=499 in log, got %q", logLine)
	}
}

func TestRequestLogging_UsesOnlyResolvedTenantHost(t *testing.T) {
	var requestAttrs []slog.Attr
	handler := RequestLogging()(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		requestAttrs = applog.SnapshotAttrs(r.Context())
		w.WriteHeader(http.StatusNoContent)
	}))

	info := tenant.Info{
		ID:               "tenant-a",
		CanonicalBaseURL: "https://public.example.test",
	}
	ctx := tenant.WithInfo(context.Background(), info)
	ctx = tenant.WithResolvedHost(ctx, "public.example.test")
	req := httptest.NewRequest(http.MethodGet, "http://internal.invalid/api/v3", nil).WithContext(ctx)
	req.Host = "internal.invalid"
	rr := httptest.NewRecorder()
	handler.ServeHTTP(rr, req)

	got := make(map[string]string, len(requestAttrs))
	for _, attr := range requestAttrs {
		got[attr.Key] = attr.Value.String()
	}
	if got["tenant_id"] != "tenant-a" {
		t.Fatalf("tenant_id attribute = %q, want tenant-a", got["tenant_id"])
	}
	if got["host"] != "public.example.test" {
		t.Fatalf("host attribute = %q, want resolved host", got["host"])
	}
	for _, value := range got {
		if strings.Contains(value, "internal.invalid") {
			t.Fatalf("raw request host leaked into request log attributes: %#v", got)
		}
	}
}
