package healthhttp

import (
	"encoding/json"
	"net"
	"net/http"
	"testing"

	"hyapp/pkg/grpchealth"
)

func TestHTTPReadyReflectsCheckerState(t *testing.T) {
	checker := grpchealth.NewServingChecker("test-service")
	server, err := New("127.0.0.1:0", "test-node", checker)
	if err != nil {
		t.Fatalf("New failed: %v", err)
	}
	go func() {
		_ = server.Run()
	}()
	t.Cleanup(func() {
		_ = server.Close(t.Context())
	})

	baseURL := "http://" + server.listener.Addr().String()
	resp, err := http.Get(baseURL + "/healthz/ready")
	if err != nil {
		t.Fatalf("GET not-ready failed: %v", err)
	}
	if resp.StatusCode != http.StatusServiceUnavailable {
		t.Fatalf("not-ready status mismatch: got %d", resp.StatusCode)
	}
	_ = resp.Body.Close()

	checker.MarkServing()
	resp, err = http.Get(baseURL + "/healthz/ready")
	if err != nil {
		t.Fatalf("GET ready failed: %v", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		t.Fatalf("ready status mismatch: got %d", resp.StatusCode)
	}
	var body Response
	if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
		t.Fatalf("decode response failed: %v", err)
	}
	if body.Service != "test-service" || body.NodeID != "test-node" || body.Status != "ok" {
		t.Fatalf("unexpected response: %+v", body)
	}
}

func TestNewDisabledWhenAddrEmpty(t *testing.T) {
	server, err := New("", "node", grpchealth.NewServingChecker("svc"))
	if err != nil {
		t.Fatalf("New empty addr failed: %v", err)
	}
	if server != nil {
		t.Fatalf("empty addr should disable health HTTP server")
	}
}

func TestNewFailsWhenPortAlreadyBound(t *testing.T) {
	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatalf("listen failed: %v", err)
	}
	defer listener.Close()

	if _, err := New(listener.Addr().String(), "node", grpchealth.NewServingChecker("svc")); err == nil {
		t.Fatalf("New should fail on occupied health port")
	}
}
