package api

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

	"github.com/pulse-lets-go/internal/models"
)

// handleZabbix — GET /api/monitoring/zabbix — возвращает JSON для Zabbix LLD + items.
func (a *API) handleZabbix(w http.ResponseWriter, r *http.Request) {
	nodes := a.engine.GetAllNodes()

	data := make([]models.ZabbixNode, 0, len(nodes))
	for _, n := range nodes {
		data = append(data, models.ZabbixNode{
			NodeID:          n.NodeID,
			Status:          n.Status,
			ActiveCalls:     n.ActiveCalls,
			MaxCalls:        n.MaxCalls,
			IdleCPU:         n.IdleCPU,
			LoadAvg:         n.LoadAvg,
			CallFailureRate: n.CallFailureRate,
			Score:           n.Score,
			Disabled:        n.Disabled,
			IsStale:         n.IsStale,
			SecondsAgo:      n.SecondsAgo,
		})
	}

	writeJSON(w, http.StatusOK, models.ZabbixResponse{Data: data})
}

// handlePrometheus — GET /api/monitoring/prometheus — text/plain метрики для Prometheus.
func (a *API) handlePrometheus(w http.ResponseWriter, r *http.Request) {
	nodes := a.engine.GetAllNodes()

	var sb strings.Builder

	// Общие метрики (counter gauge)
	stats := a.engine.GetHealthStats()
	fmt.Fprintf(&sb, "# HELP pulse_route_requests_total Total number of route requests.\n")
	fmt.Fprintf(&sb, "# TYPE pulse_route_requests_total counter\n")
	fmt.Fprintf(&sb, "pulse_route_requests_total %d\n", stats.RouteRequests)

	fmt.Fprintf(&sb, "# HELP pulse_nodes_total Total nodes registered.\n")
	fmt.Fprintf(&sb, "# TYPE pulse_nodes_total gauge\n")
	fmt.Fprintf(&sb, "pulse_nodes_total %d\n", stats.TotalNodes)

	fmt.Fprintf(&sb, "# HELP pulse_nodes_healthy Healthy nodes count.\n")
	fmt.Fprintf(&sb, "# TYPE pulse_nodes_healthy gauge\n")
	fmt.Fprintf(&sb, "pulse_nodes_healthy %d\n", stats.HealthyNodes)

	fmt.Fprintf(&sb, "# HELP pulse_uptime_seconds Uptime in seconds.\n")
	fmt.Fprintf(&sb, "# TYPE pulse_uptime_seconds gauge\n")
	fmt.Fprintf(&sb, "pulse_uptime_seconds %d\n", stats.UptimeSeconds)

	fmt.Fprintf(&sb, "\n")

	for _, n := range nodes {
		id := sanitizePromLabel(n.NodeID)

		fmt.Fprintf(&sb, "pulse_node_active_calls{node=\"%s\"} %d\n", id, n.ActiveCalls)
		fmt.Fprintf(&sb, "pulse_node_max_calls{node=\"%s\"} %d\n", id, n.MaxCalls)
		fmt.Fprintf(&sb, "pulse_node_idle_cpu{node=\"%s\"} %.2f\n", id, n.IdleCPU)
		fmt.Fprintf(&sb, "pulse_node_load_avg{node=\"%s\"} %.2f\n", id, n.LoadAvg)
		fmt.Fprintf(&sb, "pulse_node_call_failure_rate{node=\"%s\"} %.2f\n", id, n.CallFailureRate)
		fmt.Fprintf(&sb, "pulse_node_score{node=\"%s\"} %.2f\n", id, n.Score)
		fmt.Fprintf(&sb, "pulse_node_seconds_ago{node=\"%s\"} %.2f\n", id, n.SecondsAgo)

		disabledVal := 0
		staleVal := 0
		statusVal := 1 // ok
		if n.Disabled {
			disabledVal = 1
		}
		if n.IsStale {
			staleVal = 1
		}
		if n.Status != "ok" {
			statusVal = 0
		}

		fmt.Fprintf(&sb, "pulse_node_disabled{node=\"%s\"} %d\n", id, disabledVal)
		fmt.Fprintf(&sb, "pulse_node_stale{node=\"%s\"} %d\n", id, staleVal)
		fmt.Fprintf(&sb, "pulse_node_status_ok{node=\"%s\"} %d\n", id, statusVal)
	}

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

// sanitizePromLabel заменяет символы, недопустимые в Prometheus-лейблах.
func sanitizePromLabel(s string) string {
	return strings.ReplaceAll(strings.ReplaceAll(s, ".", "_"), "-", "_")
}
