package routes

import (
	"net/http"
	"sync"
	"time"

	"github.com/Wei-Shaw/sub2api/internal/prommetrics"
	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// HealthChecker defines the interface for health check dependencies
type HealthChecker interface {
	CheckDatabase() bool
	CheckRedis() bool
}

var (
	healthChecker     HealthChecker
	healthCheckerOnce sync.Once
)

// SetHealthChecker sets the health checker instance (called during app initialization)
func SetHealthChecker(checker HealthChecker) {
	healthCheckerOnce.Do(func() {
		healthChecker = checker
	})
}

// RegisterCommonRoutes registers common routes (health check, metrics, etc.)
func RegisterCommonRoutes(r *gin.Engine) {
	// Health check - enhanced with dependency checks
	r.GET("/health", healthHandler)

	// Readiness check - for Kubernetes readiness probe
	r.GET("/ready", readinessHandler)

	// Liveness check - for Kubernetes liveness probe
	r.GET("/live", livenessHandler)

	// Prometheus metrics endpoint - use the shared registry from prommetrics package
	r.GET("/metrics", gin.WrapH(promhttp.HandlerFor(prommetrics.Registry, promhttp.HandlerOpts{})))

	// Claude Code telemetry logs (ignore, return 200 directly)
	r.POST("/api/event_logging/batch", func(c *gin.Context) {
		c.Status(http.StatusOK)
	})

	// Setup status endpoint (always returns needs_setup: false in normal mode)
	// This is used by the frontend to detect when the service has restarted after setup
	r.GET("/setup/status", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"code": 0,
			"data": gin.H{
				"needs_setup": false,
				"step":        "completed",
			},
		})
	})
}

// healthHandler returns the health status of the service and its dependencies
func healthHandler(c *gin.Context) {
	status := "ok"
	statusCode := http.StatusOK

	components := make(map[string]interface{})
	allHealthy := true

	// Check database
	dbStatus := "unknown"
	dbHealthy := false
	if healthChecker != nil {
		dbHealthy = healthChecker.CheckDatabase()
		if dbHealthy {
			dbStatus = "healthy"
		} else {
			dbStatus = "unhealthy"
			allHealthy = false
		}
	}
	components["database"] = gin.H{
		"status":  dbStatus,
		"healthy": dbHealthy,
	}

	// Check Redis
	redisStatus := "unknown"
	redisHealthy := false
	if healthChecker != nil {
		redisHealthy = healthChecker.CheckRedis()
		if redisHealthy {
			redisStatus = "healthy"
		} else {
			redisStatus = "unhealthy"
			allHealthy = false
		}
	}
	components["redis"] = gin.H{
		"status":  redisStatus,
		"healthy": redisHealthy,
	}

	// Overall status
	if !allHealthy {
		status = "degraded"
		statusCode = http.StatusServiceUnavailable
	}

	response := gin.H{
		"status":     status,
		"timestamp":  time.Now().UTC().Format(time.RFC3339),
		"components": components,
	}

	c.JSON(statusCode, response)
}

// readinessHandler checks if the service is ready to accept traffic
func readinessHandler(c *gin.Context) {
	// For readiness, we require all critical dependencies to be healthy
	if healthChecker == nil {
		c.JSON(http.StatusOK, gin.H{
			"status": "ready",
		})
		return
	}

	dbHealthy := healthChecker.CheckDatabase()
	redisHealthy := healthChecker.CheckRedis()

	if dbHealthy && redisHealthy {
		c.JSON(http.StatusOK, gin.H{
			"status":    "ready",
			"timestamp": time.Now().UTC().Format(time.RFC3339),
		})
		return
	}

	components := make(map[string]bool)
	components["database"] = dbHealthy
	components["redis"] = redisHealthy

	c.JSON(http.StatusServiceUnavailable, gin.H{
		"status":     "not_ready",
		"timestamp":  time.Now().UTC().Format(time.RFC3339),
		"components": components,
	})
}

// livenessHandler checks if the service is alive (for Kubernetes liveness probe)
func livenessHandler(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"status":    "alive",
		"timestamp": time.Now().UTC().Format(time.RFC3339),
	})
}

// Prometheus metric update functions - delegate to prommetrics package

// RecordHTTPRequest records an HTTP request for Prometheus metrics
func RecordHTTPRequest(method, path string, statusCode int, duration time.Duration) {
	prommetrics.RecordHTTPRequest(method, path, statusCode, duration)
}

// SetDBConnections sets database connection metrics
func SetDBConnections(active, idle int) {
	prommetrics.SetDBConnections(active, idle)
}

// SetRedisConnections sets Redis connection metrics
func SetRedisConnections(total, idle int) {
	prommetrics.SetRedisConnections(total, idle)
}

// SetActiveAccounts sets the active accounts count
func SetActiveAccounts(count int) {
	prommetrics.SetActiveAccounts(count)
}

// SetRequestQueueDepth sets the request queue depth
func SetRequestQueueDepth(depth int) {
	prommetrics.SetRequestQueueDepth(depth)
}

// SetOpsHealthScore sets the overall health score
func SetOpsHealthScore(score int) {
	prommetrics.SetOpsHealthScore(score)
}

// SetErrorRate sets the error rate
func SetErrorRate(rate float64) {
	prommetrics.SetErrorRate(rate)
}

// SetSuccessRate sets the success rate
func SetSuccessRate(rate float64) {
	prommetrics.SetSuccessRate(rate)
}

// SetQPS sets queries per second
func SetQPS(value float64) {
	prommetrics.SetQPS(value)
}

// SetTPS sets tokens per second
func SetTPS(value float64) {
	prommetrics.SetTPS(value)
}
