package api

import (
	"context"
	"fmt"
	"log/slog"
	"net/http"
	"time"

	"github.com/TopherMayor/unified-media-manager/internal/config"
	"github.com/TopherMayor/unified-media-manager/internal/db"
	"github.com/labstack/echo/v4"
)

func healthLive(c echo.Context) error {
	return c.JSON(http.StatusOK, map[string]string{"status": "alive"})
}

func healthReady(database *db.DB, cfg *config.Config) echo.HandlerFunc {
	return func(c echo.Context) error {
		ctx, cancel := context.WithTimeout(c.Request().Context(), 5*time.Second)
		defer cancel()

		checks := map[string]string{}
		allReady := true

		if err := database.Ping(ctx); err != nil {
			checks["database"] = "unhealthy: " + err.Error()
			allReady = false
			slog.Error("readiness check failed", "component", "database", "error", err)
		} else {
			checks["database"] = "healthy"
		}

		if err := checkHTTPService(ctx, cfg.QdrantURL+"/healthz"); err != nil {
			checks["qdrant"] = "unhealthy: " + err.Error()
			allReady = false
			slog.Error("readiness check failed", "component", "qdrant", "error", err)
		} else {
			checks["qdrant"] = "healthy"
		}

		if err := checkHTTPService(ctx, cfg.OllamaURL+"/api/version"); err != nil {
			checks["ollama"] = "unhealthy: " + err.Error()
			allReady = false
			slog.Error("readiness check failed", "component", "ollama", "error", err)
		} else {
			checks["ollama"] = "healthy"
		}

		status := "healthy"
		code := http.StatusOK
		if !allReady {
			status = "degraded"
			code = http.StatusServiceUnavailable
		}

		return c.JSON(code, map[string]interface{}{"status": status, "checks": checks})
	}
}

func checkHTTPService(ctx context.Context, url string) error {
	client := &http.Client{Timeout: 3 * time.Second}
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return fmt.Errorf("build request: %w", err)
	}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("request failed: %w", err)
	}
	resp.Body.Close()
	if resp.StatusCode >= 500 {
		return fmt.Errorf("server returned %d", resp.StatusCode)
	}
	return nil
}
