package handlers

import (
	"net/http"
	"time"

	"payment/internal/database"

	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

// HealthHandler handles health check and metrics endpoints
type HealthHandler struct {
	db    *gorm.DB
	redis *redis.Client
}

// NewHealthHandler creates a new health handler
func NewHealthHandler(db *gorm.DB, redis *redis.Client) *HealthHandler {
	return &HealthHandler{
		db:    db,
		redis: redis,
	}
}

// HealthCheck performs health checks on all dependencies
func (h *HealthHandler) HealthCheck(c *gin.Context) {
	status := "healthy"
	checks := make(map[string]interface{})

	// Check database
	dbStatus := "healthy"
	if err := database.HealthCheck(h.db); err != nil {
		dbStatus = "unhealthy"
		status = "unhealthy"
		logrus.WithError(err).Error("Database health check failed")
	}
	checks["database"] = map[string]interface{}{
		"status": dbStatus,
		"type":   "postgres",
	}

	// Check Redis
	redisStatus := "healthy"
	ctx := c.Request.Context()
	if err := h.redis.Ping(ctx).Err(); err != nil {
		redisStatus = "unhealthy"
		status = "unhealthy"
		logrus.WithError(err).Error("Redis health check failed")
	}
	checks["redis"] = map[string]interface{}{
		"status": redisStatus,
		"type":   "redis",
	}

	// Determine HTTP status code
	httpStatus := http.StatusOK
	if status == "unhealthy" {
		httpStatus = http.StatusServiceUnavailable
	}

	c.JSON(httpStatus, gin.H{
		"status":    status,
		"timestamp": time.Now().UTC().Format(time.RFC3339),
		"checks":    checks,
		"version":   "1.0.0",
		"service":   "payment-service",
	})
}

// Metrics exposes Prometheus metrics
func (h *HealthHandler) Metrics(c *gin.Context) {
	promhttp.Handler().ServeHTTP(c.Writer, c.Request)
}

// ReadinessCheck performs readiness checks
func (h *HealthHandler) ReadinessCheck(c *gin.Context) {
	// Check if all critical dependencies are ready
	ready := true
	checks := make(map[string]bool)

	// Check database
	if err := database.HealthCheck(h.db); err != nil {
		ready = false
		checks["database"] = false
	} else {
		checks["database"] = true
	}

	// Check Redis
	ctx := c.Request.Context()
	if err := h.redis.Ping(ctx).Err(); err != nil {
		ready = false
		checks["redis"] = false
	} else {
		checks["redis"] = true
	}

	status := "ready"
	httpStatus := http.StatusOK
	if !ready {
		status = "not_ready"
		httpStatus = http.StatusServiceUnavailable
	}

	c.JSON(httpStatus, gin.H{
		"status":    status,
		"timestamp": time.Now().UTC().Format(time.RFC3339),
		"checks":    checks,
	})
}

// LivenessCheck performs liveness checks
func (h *HealthHandler) LivenessCheck(c *gin.Context) {
	// Simple liveness check - if the service is running, it's alive
	c.JSON(http.StatusOK, gin.H{
		"status":    "alive",
		"timestamp": time.Now().UTC().Format(time.RFC3339),
		"uptime":    time.Since(startTime).String(),
	})
}

var startTime = time.Now()
