package server

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

	"go.uber.org/zap/zaptest"
)

// get serves a GET request against the server's handler and returns the recorder.
func get(srv *Server, path string) *httptest.ResponseRecorder {
	req := httptest.NewRequest(http.MethodGet, path, nil)
	rec := httptest.NewRecorder()
	srv.Handler().ServeHTTP(rec, req)
	return rec
}

// TestHealthz verifies that /healthz answers 200 OK.
func TestHealthz(t *testing.T) {
	srv := New(":0", Deps{Logger: zaptest.NewLogger(t)})
	if rec := get(srv, "/healthz"); rec.Code != http.StatusOK {
		t.Fatalf("/healthz status = %d, want %d", rec.Code, http.StatusOK)
	}
}

// TestReadyzReadyWithoutDeps verifies that, with no database and no session
// readiness gate wired, /readyz answers 200 OK.
func TestReadyzReadyWithoutDeps(t *testing.T) {
	srv := New(":0", Deps{Logger: zaptest.NewLogger(t)})
	if rec := get(srv, "/readyz"); rec.Code != http.StatusOK {
		t.Fatalf("/readyz status = %d, want %d", rec.Code, http.StatusOK)
	}
}

// TestReadyzNotReadyWhenSessionsCold verifies that /readyz answers 503 while the
// session cache reports not-ready.
func TestReadyzNotReadyWhenSessionsCold(t *testing.T) {
	srv := New(":0", Deps{
		Logger:        zaptest.NewLogger(t),
		SessionsReady: func() bool { return false },
	})
	if rec := get(srv, "/readyz"); rec.Code != http.StatusServiceUnavailable {
		t.Fatalf("/readyz status = %d, want %d", rec.Code, http.StatusServiceUnavailable)
	}
}

// TestReadyzReadyWhenSessionsWarm verifies that /readyz answers 200 once the
// session cache reports ready (and no database is wired).
func TestReadyzReadyWhenSessionsWarm(t *testing.T) {
	srv := New(":0", Deps{
		Logger:        zaptest.NewLogger(t),
		SessionsReady: func() bool { return true },
	})
	if rec := get(srv, "/readyz"); rec.Code != http.StatusOK {
		t.Fatalf("/readyz status = %d, want %d", rec.Code, http.StatusOK)
	}
}
