package main

import (
	"context"
	"errors"
	"io"
	"net/http"
	"net/http/httptest"
	"sync/atomic"
	"testing"
	"time"
)

func TestReadiness(t *testing.T) {
	var r atomic.Bool
	h := routes(&r, func(http.ResponseWriter, *http.Request) {})
	for _, ready := range []bool{true, false} {
		r.Store(ready)
		w := httptest.NewRecorder()
		h.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/readyz", nil))
		want := 503
		if ready {
			want = 200
		}
		if w.Code != want {
			t.Fatalf("got %d want %d", w.Code, want)
		}
	}
}
func TestShutdownWaitsForRequest(t *testing.T) {
	started, release := make(chan struct{}), make(chan struct{})
	var ready atomic.Bool
	ready.Store(true)
	ts := httptest.NewServer(routes(&ready, func(w http.ResponseWriter, r *http.Request) {
		close(started)
		<-release
		_, _ = io.WriteString(w, "done")
	}))
	defer ts.Close()
	result := make(chan error, 1)
	go func() {
		resp, err := ts.Client().Get(ts.URL + "/work")
		if err != nil {
			result <- err
			return
		}
		defer resp.Body.Close()
		b, err := io.ReadAll(resp.Body)
		if err == nil && string(b) != "done" {
			err = errors.New("incomplete response")
		}
		result <- err
	}()
	<-started
	// Negative case: a canceled budget cannot finish an active request.
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	if err := ts.Config.Shutdown(ctx); !errors.Is(err, context.Canceled) {
		t.Fatalf("want canceled, got %v", err)
	}
	close(release)
	if err := <-result; err != nil {
		t.Fatal(err)
	}
	drain, done := context.WithTimeout(context.Background(), time.Second)
	defer done()
	if err := ts.Config.Shutdown(drain); err != nil {
		t.Fatal(err)
	}
}
