package handlers

import (
	"database/sql"
	"net/http"
	"runtime"
	"time"

	"github.com/gin-gonic/gin"

	"chat-switchboard/database"
	"chat-switchboard/events"
	"chat-switchboard/health"
	"chat-switchboard/models"
	"chat-switchboard/store"
)

// ── Dashboard Admin Handler ─────────────────
// GET /api/v1/admin/dashboard
// Aggregates live operational data for the built-in admin monitoring page.

var processStartTime = time.Now()

type DashboardAdminHandler struct {
	stores      store.Stores
	healthStore health.Store
	hub         *events.Hub
}

func NewDashboardAdminHandler(stores store.Stores, hs health.Store, hub *events.Hub) *DashboardAdminHandler {
	return &DashboardAdminHandler{stores: stores, healthStore: hs, hub: hub}
}

type runtimeStats struct {
	Goroutines int    `json:"goroutines"`
	HeapMB     int    `json:"heap_mb"`
	SysMB      int    `json:"sys_mb"`
	NumGC      uint32 `json:"num_gc"`
	GoVersion  string `json:"go_version"`
}

func (h *DashboardAdminHandler) GetDashboard(c *gin.Context) {
	ctx := c.Request.Context()

	// Provider health summaries
	var providerHealth []models.ProviderHealthSummary
	windows, err := h.healthStore.ListAllCurrent(ctx)
	if err == nil {
		for _, w := range windows {
			providerHealth = append(providerHealth, models.ProviderHealthSummary{
				ProviderConfigID: w.ProviderConfigID,
				Status:           health.DeriveStatus(w.ErrorRate(), w.RequestCount),
				RequestCount:     w.RequestCount,
				ErrorRate:        w.ErrorRate(),
				ErrorCount:       w.ErrorCount,
				RateLimitCount:   w.RateLimitCount,
				TimeoutCount:     w.TimeoutCount,
				AvgLatencyMs:     w.AvgLatencyMs(),
				MaxLatencyMs:     w.MaxLatencyMs,
				LastError:        w.LastError,
				LastErrorAt:      w.LastErrorAt,
			})
		}
	}

	// 24h usage totals
	since := time.Now().Add(-24 * time.Hour)
	totals, _ := h.stores.Usage.GetTotals(ctx, store.UsageQueryOptions{
		Since: &since,
	})

	// DB pool stats
	var dbPool *sql.DBStats
	if database.DB != nil {
		stats := database.DB.Stats()
		dbPool = &stats
	}

	// WebSocket connections
	wsCount := 0
	if h.hub != nil {
		wsCount = h.hub.ConnCount()
	}

	// Recent errors from audit log (last 10 error-related entries)
	var recentErrors []models.AuditEntry
	entries, _, auditErr := h.stores.Audit.List(ctx, store.AuditListOptions{
		ListOptions:  store.ListOptions{Limit: 10},
		ResourceType: "error",
	})
	if auditErr == nil {
		recentErrors = entries
	}

	// Go runtime stats
	var mem runtime.MemStats
	runtime.ReadMemStats(&mem)
	rt := runtimeStats{
		Goroutines: runtime.NumGoroutine(),
		HeapMB:     int(mem.HeapAlloc / 1024 / 1024),
		SysMB:      int(mem.Sys / 1024 / 1024),
		NumGC:      mem.NumGC,
		GoVersion:  runtime.Version(),
	}

	// Uptime
	uptime := time.Since(processStartTime).Truncate(time.Second).String()

	SafeJSON(c, http.StatusOK, gin.H{
		"provider_health": providerHealth,
		"usage_24h":       totals,
		"db_pool":         dbPool,
		"ws_connections":  wsCount,
		"recent_errors":   recentErrors,
		"runtime":         rt,
		"uptime":          uptime,
	})
}
