package service

import (
	"context"
	"database/sql"
	"time"

	"github.com/redis/go-redis/v9"
)

// HealthChecker provides health check functionality for dependencies
type HealthChecker struct {
	db          *sql.DB
	redisClient *redis.Client
}

// NewHealthChecker creates a new health checker instance
func NewHealthChecker(db *sql.DB, redisClient *redis.Client) *HealthChecker {
	return &HealthChecker{
		db:          db,
		redisClient: redisClient,
	}
}

// CheckDatabase checks if the database connection is healthy
func (h *HealthChecker) CheckDatabase() bool {
	if h.db == nil {
		return false
	}

	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()

	var result int
	err := h.db.QueryRowContext(ctx, "SELECT 1").Scan(&result)
	if err != nil {
		return false
	}

	return result == 1
}

// CheckRedis checks if the Redis connection is healthy
func (h *HealthChecker) CheckRedis() bool {
	if h.redisClient == nil {
		return false
	}

	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()

	err := h.redisClient.Ping(ctx).Err()
	return err == nil
}

// GetDatabaseStats returns database connection statistics
func (h *HealthChecker) GetDatabaseStats() (active, idle int) {
	if h.db == nil {
		return 0, 0
	}
	stats := h.db.Stats()
	return stats.InUse, stats.Idle
}

// GetRedisStats returns Redis connection statistics
func (h *HealthChecker) GetRedisStats() (total, idle int) {
	if h.redisClient == nil {
		return 0, 0
	}
	stats := h.redisClient.PoolStats()
	if stats == nil {
		return 0, 0
	}
	return int(stats.TotalConns), int(stats.IdleConns)
}

// HealthStatus represents the health status of all dependencies
type HealthStatus struct {
	Database DatabaseHealth `json:"database"`
	Redis    RedisHealth    `json:"redis"`
}

// DatabaseHealth represents database health information
type DatabaseHealth struct {
	Healthy             bool  `json:"healthy"`
	ActiveConns         int   `json:"active_connections"`
	IdleConns           int   `json:"idle_connections"`
	OpenConns           int   `json:"open_connections"`
	MaxOpenConns        int   `json:"max_open_connections"`
	WaitCount           int64 `json:"wait_count"`
	MaxIdleClosed       int64 `json:"max_idle_closed"`
	MaxLifetimeClosed   int64 `json:"max_lifetime_closed"`
}

// RedisHealth represents Redis health information
type RedisHealth struct {
	Healthy     bool `json:"healthy"`
	TotalConns  int  `json:"total_connections"`
	IdleConns   int  `json:"idle_connections"`
}

// GetHealthStatus returns comprehensive health status
func (h *HealthChecker) GetHealthStatus() HealthStatus {
	status := HealthStatus{}

	// Database health
	status.Database.Healthy = h.CheckDatabase()
	if h.db != nil {
		stats := h.db.Stats()
		status.Database.ActiveConns = stats.InUse
		status.Database.IdleConns = stats.Idle
		status.Database.OpenConns = stats.OpenConnections
		status.Database.MaxOpenConns = stats.MaxOpenConnections
		status.Database.WaitCount = stats.WaitCount
		status.Database.MaxIdleClosed = stats.MaxIdleClosed
		status.Database.MaxLifetimeClosed = stats.MaxLifetimeClosed
	}

	// Redis health
	status.Redis.Healthy = h.CheckRedis()
	if h.redisClient != nil {
		stats := h.redisClient.PoolStats()
		if stats != nil {
			status.Redis.TotalConns = int(stats.TotalConns)
			status.Redis.IdleConns = int(stats.IdleConns)
		}
	}

	return status
}
