package httpx

import (
	"context"
	"net/http"
	"runtime"
	"time"
)

// ReadinessCheck is a named dependency probe run by /readyz. Required checks
// (Mongo) gate readiness; optional ones (atomizer, work performer) are
// reported but non-fatal, per §6.
type ReadinessCheck struct {
	Name     string
	Required bool
	Probe    func(ctx context.Context) error
}

// AddReadinessCheck registers a probe; later phases plug in Mongo and the
// external services here.
func (s *Server) AddReadinessCheck(c ReadinessCheck) {
	s.checks = append(s.checks, c)
}

func (s *Server) handleHealthz(w http.ResponseWriter, _ *http.Request) {
	writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
}

type checkResult struct {
	OK       bool   `json:"ok"`
	Required bool   `json:"required"`
	Error    string `json:"error,omitempty"`
}

func (s *Server) handleReadyz(w http.ResponseWriter, r *http.Request) {
	ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
	defer cancel()

	status := "ok"
	httpStatus := http.StatusOK
	results := make(map[string]checkResult, len(s.checks))
	for _, c := range s.checks {
		res := checkResult{OK: true, Required: c.Required}
		if err := c.Probe(ctx); err != nil {
			res.OK = false
			res.Error = err.Error()
			if c.Required {
				status = "unavailable"
				httpStatus = http.StatusServiceUnavailable
			} else if status == "ok" {
				status = "degraded"
			}
		}
		results[c.Name] = res
	}
	writeJSON(w, httpStatus, map[string]any{"status": status, "checks": results})
}

func (s *Server) handleMetricsz(w http.ResponseWriter, _ *http.Request) {
	counters, gauges := s.metrics.Snapshot()
	writeJSON(w, http.StatusOK, map[string]any{
		"uptimeSec":  int64(time.Since(s.startedAt).Seconds()),
		"goroutines": runtime.NumGoroutine(),
		"counters":   counters,
		"gauges":     gauges,
	})
}
