package monitoring

import (
	"strconv"
	"sync"
	"time"

	"github.com/prometheus/client_golang/prometheus"
)

// Metrics 监控指标
type Metrics struct {
	// HTTP请求指标
	httpRequestsTotal   *prometheus.CounterVec
	httpRequestDuration *prometheus.HistogramVec

	// 数据库指标
	dbQueriesTotal  *prometheus.CounterVec
	dbQueryDuration *prometheus.HistogramVec

	// 用户指标
	userRegistrations *prometheus.CounterVec
	userLogins        *prometheus.CounterVec
	activeUsers       *prometheus.GaugeVec

	// 系统指标
	systemMemoryUsage prometheus.Gauge
	systemGoroutines  prometheus.Gauge

	// 私有注册表（测试时互不干扰）
	registry *prometheus.Registry
}

// globalMetrics 全局单例（生产使用）
var (
	globalMetrics     *Metrics
	globalMetricsOnce sync.Once
)

// NewMetrics 创建监控指标（每次创建使用独立 registry，避免重复注册 panic）
func NewMetrics() *Metrics {
	reg := prometheus.NewRegistry()
	m := &Metrics{registry: reg}
	m.httpRequestsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "http_requests_total",
			Help: "Total number of HTTP requests",
		},
		[]string{"method", "path", "status"},
	)
	m.httpRequestDuration = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Name:    "http_request_duration_seconds",
			Help:    "HTTP request duration in seconds",
			Buckets: prometheus.DefBuckets,
		},
		[]string{"method", "path"},
	)
	m.dbQueriesTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "db_queries_total",
			Help: "Total number of database queries",
		},
		[]string{"operation", "table"},
	)
	m.dbQueryDuration = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Name:    "db_query_duration_seconds",
			Help:    "Database query duration in seconds",
			Buckets: prometheus.DefBuckets,
		},
		[]string{"operation", "table"},
	)
	m.userRegistrations = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "user_registrations_total",
			Help: "Total number of user registrations",
		},
		[]string{"type"},
	)
	m.userLogins = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "user_logins_total",
			Help: "Total number of user logins",
		},
		[]string{"type", "status"},
	)
	m.activeUsers = prometheus.NewGaugeVec(
		prometheus.GaugeOpts{
			Name: "active_users",
			Help: "Number of active users",
		},
		[]string{"period"},
	)
	m.systemMemoryUsage = prometheus.NewGauge(
		prometheus.GaugeOpts{
			Name: "system_memory_usage_bytes",
			Help: "Current memory usage in bytes",
		},
	)
	m.systemGoroutines = prometheus.NewGauge(
		prometheus.GaugeOpts{
			Name: "system_goroutines",
			Help: "Number of goroutines",
		},
	)

	// 注册到私有 registry
	reg.MustRegister(
		m.httpRequestsTotal,
		m.httpRequestDuration,
		m.dbQueriesTotal,
		m.dbQueryDuration,
		m.userRegistrations,
		m.userLogins,
		m.activeUsers,
		m.systemMemoryUsage,
		m.systemGoroutines,
	)

	return m
}

// GetGlobalMetrics 获取全局单例 Metrics（生产使用，同时注册到默认 registry）
func GetGlobalMetrics() *Metrics {
	globalMetricsOnce.Do(func() {
		m := NewMetrics()
		// 将私有 registry 的指标也注册到默认 registry
		prometheus.DefaultRegisterer.Register(m.httpRequestsTotal)   //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.httpRequestDuration) //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.dbQueriesTotal)      //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.dbQueryDuration)     //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.userRegistrations)   //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.userLogins)          //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.activeUsers)         //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.systemMemoryUsage)   //nolint:errcheck
		prometheus.DefaultRegisterer.Register(m.systemGoroutines)    //nolint:errcheck
		globalMetrics = m
	})
	return globalMetrics
}

// GetRegistry 获取私有 Prometheus registry
func (m *Metrics) GetRegistry() *prometheus.Registry {
	return m.registry
}

// IncHTTPRequest 记录HTTP请求
func (m *Metrics) IncHTTPRequest(method, path string, status int) {
	m.httpRequestsTotal.WithLabelValues(method, path, strconv.Itoa(status)).Inc()
}

// ObserveHTTPRequestDuration 记录HTTP请求耗时
func (m *Metrics) ObserveHTTPRequestDuration(method, path string, duration time.Duration) {
	m.httpRequestDuration.WithLabelValues(method, path).Observe(duration.Seconds())
}

// IncDBQuery 记录数据库查询
func (m *Metrics) IncDBQuery(operation, table string) {
	m.dbQueriesTotal.WithLabelValues(operation, table).Inc()
}

// ObserveDBQueryDuration 记录数据库查询耗时
func (m *Metrics) ObserveDBQueryDuration(operation, table string, duration time.Duration) {
	m.dbQueryDuration.WithLabelValues(operation, table).Observe(duration.Seconds())
}

// IncUserRegistration 记录用户注册
func (m *Metrics) IncUserRegistration(userType string) {
	m.userRegistrations.WithLabelValues(userType).Inc()
}

// IncUserLogin 记录用户登录
func (m *Metrics) IncUserLogin(loginType, status string) {
	m.userLogins.WithLabelValues(loginType, status).Inc()
}

// SetActiveUsers 设置活跃用户数
func (m *Metrics) SetActiveUsers(period string, count float64) {
	m.activeUsers.WithLabelValues(period).Set(count)
}

// SetMemoryUsage 设置内存使用量
func (m *Metrics) SetMemoryUsage(bytes float64) {
	m.systemMemoryUsage.Set(bytes)
}

// SetGoroutines 设置协程数
func (m *Metrics) SetGoroutines(count float64) {
	m.systemGoroutines.Set(count)
}

// GetMetrics 获取Prometheus指标收集器
func (m *Metrics) GetMetrics() []prometheus.Collector {
	return []prometheus.Collector{
		m.httpRequestsTotal,
		m.httpRequestDuration,
		m.dbQueriesTotal,
		m.dbQueryDuration,
		m.userRegistrations,
		m.userLogins,
		m.activeUsers,
		m.systemMemoryUsage,
		m.systemGoroutines,
	}
}
