// Package llm formats sentry alerts for delivery to Lark.
//
// Two formatters: a stateless Qwen client (qwen.go — Task 3.6) that calls
// DashScope for natural-language translation, and a template-based fallback
// (this file) used when the LLM is unreachable.
package llm

import (
	"fmt"
	"strings"

	"github.com/nexuscrm/sentry/internal/types"
)

// FormatTemplate produces a deterministic short message for the given rule
// result. Used when the LLM is unavailable. Never returns an empty string.
func FormatTemplate(r types.RuleResult) string {
	icon := "🟡"
	if r.Level == "CRIT" {
		icon = "🔴"
	}

	ctxInt := func(k string) int64 {
		if v, ok := r.Context[k]; ok {
			switch n := v.(type) {
			case int:
				return int64(n)
			case int64:
				return n
			case float64:
				return int64(n)
			}
		}
		return 0
	}
	ctxFloat := func(k string) float64 {
		if v, ok := r.Context[k]; ok {
			switch n := v.(type) {
			case float64:
				return n
			case float32:
				return float64(n)
			case int:
				return float64(n)
			case int64:
				return float64(n)
			}
		}
		return 0
	}
	var body string
	switch r.RuleID {
	case "data.row_spike_warn", "data.row_spike_crit":
		body = fmt.Sprintf(
			"Row-count spike on `%s`: now %d rows (was %d one hour ago, +%.1f%%).",
			r.Entity, ctxInt("current"), ctxInt("baseline_1h"), ctxFloat("delta_pct")*100,
		)
	case "data.row_drop_warn", "data.row_drop_crit":
		body = fmt.Sprintf(
			"Row-count drop on `%s`: now %d rows (was %d one hour ago, %.1f%%).",
			r.Entity, ctxInt("current"), ctxInt("baseline_1h"), ctxFloat("delta_pct")*100,
		)
	case "data.outbox_backlog_warn", "data.outbox_backlog_crit":
		body = fmt.Sprintf(
			"Outbox backlog: %d pending events in `_System_OutboxEvent`.",
			ctxInt("pending"),
		)
	case "data.outbox_failed_surge":
		body = fmt.Sprintf(
			"Outbox failure surge: +%d failed events in the last hour (now %d failed total).",
			ctxInt("delta"), ctxInt("current"),
		)
	case "app.goroutine_leak":
		body = fmt.Sprintf(
			"Goroutine count rising: %d now, %d one hour ago (+%d).",
			ctxInt("current"), ctxInt("baseline_1h"), ctxInt("delta"),
		)
	case "app.heap_growth":
		body = fmt.Sprintf(
			"Heap growth: %d MB now, %d MB two hours ago (+%.1f%%).",
			ctxInt("current_mb"), ctxInt("baseline_2h_mb"), ctxFloat("delta_pct")*100,
		)
	case "app.db_pool_wait":
		body = fmt.Sprintf(
			"DB connection pool exhaustion: %d new waits in the last 10 minutes.",
			ctxInt("delta"),
		)
	case "app.panic_surge":
		body = fmt.Sprintf(
			"Panic surge: %d new panics caught by recovery middleware in the last 10 minutes.",
			ctxInt("delta"),
		)
	case "app.http_5xx_warn", "app.http_5xx_crit":
		body = fmt.Sprintf(
			"HTTP 5xx rate elevated: %.2f%% of requests in the last 10 minutes (%d 5xx / %d total).",
			ctxFloat("fraction")*100, ctxInt("err_delta"), ctxInt("req_delta"),
		)
	case "app.outbox_stall":
		var latestPending int64
		if seq, ok := r.Context["pending_seq"]; ok {
			switch s := seq.(type) {
			case []int64:
				if len(s) > 0 {
					latestPending = s[len(s)-1]
				}
			case []any:
				if len(s) > 0 {
					if v, ok := s[len(s)-1].(float64); ok {
						latestPending = int64(v)
					} else if v, ok := s[len(s)-1].(int64); ok {
						latestPending = v
					}
				}
			}
		}
		body = fmt.Sprintf(
			"Outbox stall: pending count %d non-decreasing over the last 30 minutes.",
			latestPending,
		)
	default:
		body = fmt.Sprintf("Alert on `%s` (rule=%s, level=%s).", r.Entity, r.RuleID, r.Level)
	}

	var sb strings.Builder
	sb.WriteString(icon)
	sb.WriteString(" **")
	sb.WriteString(r.Level)
	sb.WriteString("** ")
	sb.WriteString(r.RuleID)
	sb.WriteString("\n")
	sb.WriteString(body)
	return sb.String()
}
