package api

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

	"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/auth"
	"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/db"
	"github.com/gin-gonic/gin"
)

// The two probes answer different questions on purpose.
//
// /healthz is liveness: the process is up and serving. It touches nothing
// external, because a Mongo outage must not make Kubernetes restart every
// server pod — a restart loop cannot fix someone else's database, and it
// destroys every open command stream and console session on the way.
//
// /readyz is readiness: this pod can serve a request end to end, which needs
// both Mongo and Redis. A failing readiness probe pulls the pod out of the
// Service and leaves it running, which is the behaviour that matters during a
// dependency blip.
//
// Both sit outside /api, so neither the session middleware nor the licence
// gate applies. Neither reveals anything beyond up or down.

const probeTimeout = 2 * time.Second

func handleHealthz(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"status": "ok"})
}

func handleReadyz(c *gin.Context) {
	ctx, cancel := context.WithTimeout(c.Request.Context(), probeTimeout)
	defer cancel()

	checks := gin.H{"mongo": "ok", "redis": "ok"}
	ready := true

	if db.Client == nil {
		checks["mongo"] = "not initialised"
		ready = false
	} else if err := db.Client.Ping(ctx, nil); err != nil {
		checks["mongo"] = "unreachable"
		ready = false
	}

	if err := auth.PingRedis(ctx); err != nil {
		checks["redis"] = "unreachable"
		ready = false
	}

	status := http.StatusOK
	state := "ok"
	if !ready {
		status = http.StatusServiceUnavailable
		state = "unready"
	}
	c.JSON(status, gin.H{"status": state, "checks": checks})
}
