package authapi

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

	"github.com/go-chi/chi/v5"
)

func TestValidateFlowSlugAllowed(t *testing.T) {
	t.Parallel()
	for _, slug := range []string{FlowEnrollment, FlowRecovery, FlowAuthentication} {
		rec := httptest.NewRecorder()
		req := httptest.NewRequest(http.MethodPost, "/flows/"+slug+"/start", nil)
		got, ok := validateFlowSlug(rec, req, slug)
		if !ok || got != slug {
			t.Fatalf("slug %q: ok=%v got=%q code=%d", slug, ok, got, rec.Code)
		}
	}
}

func TestValidateFlowSlugRejected(t *testing.T) {
	t.Parallel()
	rec := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodPost, "/flows/default-invalidation-flow/start", nil)
	_, ok := validateFlowSlug(rec, req, "default-invalidation-flow")
	if ok {
		t.Fatal("expected slug to be rejected")
	}
	if rec.Code != http.StatusNotFound {
		t.Fatalf("status = %d", rec.Code)
	}
}

func TestRespondFlowMissingCookie(t *testing.T) {
	t.Parallel()
	h := NewHandler("http://127.0.0.1:1", "http://localhost:3004", nil)
	rec := httptest.NewRecorder()
	req := httptest.NewRequest(http.MethodPost, "/flows/ulti-enrollment/respond", bytes.NewReader([]byte(`{"payload":{"component":"x"}}`)))
	rctx := chi.NewRouteContext()
	rctx.URLParams.Add("slug", FlowEnrollment)
	req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
	h.RespondFlow(rec, req)
	if rec.Code != http.StatusUnauthorized {
		t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
	}
}

func TestBuildLoginRedirectURL(t *testing.T) {
	t.Parallel()
	got := buildLoginRedirectURL("http://localhost:3004", "/mail/inbox")
	want := "http://localhost:3004/api/auth/login?returnTo=%2Fmail%2Finbox"
	if got != want {
		t.Fatalf("got %q want %q", got, want)
	}
}

func TestFlowRateLimiterMemory(t *testing.T) {
	t.Parallel()
	lim := NewFlowRateLimiter(nil)
	req := httptest.NewRequest(http.MethodPost, "/start", nil)
	req.RemoteAddr = "203.0.113.1:1234"
	for i := 0; i < flowRateLimitMax; i++ {
		if !lim.Allow(req) {
			t.Fatalf("attempt %d should be allowed", i+1)
		}
	}
	if lim.Allow(req) {
		t.Fatal("expected rate limit block")
	}
}
