package api

import (
	"fmt"
	"net/http"
	"strings"
	"time"
)

// handleHealth returns a simple health check response.
// GET /api/health  (public, no auth)
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
	writeJSON(w, http.StatusOK, map[string]interface{}{
		"status":     "ok",
		"version":    s.appVersion,
		"uptime_sec": int64(time.Since(s.startTime).Seconds()),
	})
}

// handleMetrics serves Prometheus-compatible metrics.
// GET /metrics  (public or token-protected)
//
// Metrics are DB-backed gauges; no in-process counters needed.
// Format: https://prometheus.io/docs/instrumenting/exposition_formats/
func (s *Server) handleMetrics(w http.ResponseWriter, r *http.Request) {
	if !s.metricsCfg.Enabled {
		writeError(w, http.StatusNotFound, "metrics disabled")
		return
	}

	// Optional token protection
	if s.metricsCfg.Token != "" {
		tok := extractBearerToken(r)
		if tok == "" {
			// Also accept ?token= query param for scraper convenience
			tok = r.URL.Query().Get("token")
		}
		if tok != s.metricsCfg.Token {
			w.Header().Set("WWW-Authenticate", `Bearer realm="archivmail metrics"`)
			writeError(w, http.StatusUnauthorized, "invalid metrics token")
			return
		}
	}

	ctx := r.Context()
	var sb strings.Builder

	metric := func(name, help, typ string, val interface{}) {
		fmt.Fprintf(&sb, "# HELP %s %s\n", name, help)
		fmt.Fprintf(&sb, "# TYPE %s %s\n", name, typ)
		fmt.Fprintf(&sb, "%s %v\n", name, val)
	}

	// ── Mail counts ───────────────────────────────────────────────────────
	activity, _ := s.store.MailActivityStats(ctx)
	if activity != nil {
		metric("archivmail_mails_last_60min", "Mails received in the last 60 minutes", "gauge", activity.Last60Min)
		metric("archivmail_mails_last_24h", "Mails received in the last 24 hours", "gauge", activity.Last24h)
		metric("archivmail_mails_last_7d", "Mails received in the last 7 days", "gauge", activity.Last7d)
		metric("archivmail_mails_last_30d", "Mails received in the last 30 days", "gauge", activity.Last30d)
	}

	// Total mails + storage bytes from DB
	var totalMails int64
	var totalBytes int64
	if s.store != nil {
		_ = s.store.DBQueryRow(ctx,
			`SELECT COUNT(*), COALESCE(SUM(size_bytes),0) FROM emails`,
		).Scan(&totalMails, &totalBytes)
	}
	metric("archivmail_mails_total", "Total number of archived mails", "gauge", totalMails)
	metric("archivmail_storage_bytes", "Total size of archived mails in bytes", "gauge", totalBytes)

	// Tenant count
	var tenantCount int64
	if s.tenantStore != nil {
		_ = s.store.DBQueryRow(ctx, `SELECT COUNT(*) FROM tenants`).Scan(&tenantCount)
	}
	metric("archivmail_tenants_total", "Total number of tenants", "gauge", tenantCount)

	// User count
	var userCount int64
	_ = s.store.DBQueryRow(ctx, `SELECT COUNT(*) FROM users WHERE active = true`).Scan(&userCount)
	metric("archivmail_users_total", "Total number of active users", "gauge", userCount)

	// Process uptime
	metric("archivmail_uptime_seconds", "Process uptime in seconds", "gauge", int64(time.Since(s.startTime).Seconds()))

	w.Header().Set("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(sb.String())) //nolint:errcheck
}
