package handler

import (
	"encoding/json"
	"net"
	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"
)

func newIPv4TestServer(t *testing.T, handler http.Handler) *httptest.Server {
	t.Helper()

	ln, err := net.Listen("tcp4", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("failed to bind test server listener: %v", err)
	}

	server := httptest.NewUnstartedServer(handler)
	server.Listener = ln
	server.Start()
	t.Cleanup(server.Close)

	return server
}

func newJWKSHTTPClient(t *testing.T, jwksBody []byte) *http.Client {
	t.Helper()

	return &http.Client{
		Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) {
			if r.URL.Path == "/.well-known/jwks.json" {
				return httpResponse(r, http.StatusOK, string(jwksBody)), nil
			}
			return httpResponse(r, http.StatusNotFound, "not found"), nil
		}),
	}
}

func installKratosWhoamiClient(t *testing.T, identityID string) string {
	t.Helper()

	origDefaultClient := http.DefaultClient
	http.DefaultClient = &http.Client{
		Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) {
			if r.URL.Path != "/sessions/whoami" {
				return httpResponse(r, http.StatusNotFound, "not found"), nil
			}
			if r.Header.Get("Cookie") == "" && r.Header.Get("X-Session-Token") == "" {
				return httpResponse(r, http.StatusUnauthorized, "missing session"), nil
			}
			body, err := json.Marshal(map[string]any{
				"id":               "session-123",
				"authenticated_at": "2026-05-21T00:00:00Z",
				"identity": map[string]any{
					"id": identityID,
					"traits": map[string]any{
						"email": "user@example.com",
					},
				},
			})
			if err != nil {
				return nil, err
			}
			resp := httpResponse(r, http.StatusOK, string(body))
			resp.Header.Set("Content-Type", "application/json")
			return resp, nil
		}),
	}
	t.Cleanup(func() {
		http.DefaultClient = origDefaultClient
	})

	return "http://kratos.test"
}

func jwksURL() string {
	u := &url.URL{Scheme: "http", Host: "jwks.test", Path: "/.well-known/jwks.json"}
	return u.String()
}

func mustJSONBody(t *testing.T, value any) []byte {
	t.Helper()

	body, err := json.Marshal(value)
	if err != nil {
		t.Fatalf("failed to marshal test body: %v", err)
	}
	return body
}
