package ai

import (
	"context"
	"encoding/json"
	"fmt"
	"time"
)

// SmartAlertEngine motor de alertas inteligentes
type SmartAlertEngine struct {
	engine        *AIEngine
	alertBuffer   []RawAlert
	correlationWindow time.Duration
}

// RawAlert alerta bruto antes do processamento
type RawAlert struct {
	ID          string
	Metric      string
	Host        string
	Value       float64
	Threshold   float64
	Severity    string
	Timestamp   time.Time
	Labels      map[string]string
}

// SmartAlert alerta processado com IA
type SmartAlert struct {
	ID              string          `json:"id"`
	Title           string          `json:"title"`
	Description     string          `json:"description"`
	Severity        string          `json:"severity"`
	Category        string          `json:"category"`
	AffectedHosts   []string        `json:"affected_hosts"`
	RootCause       string          `json:"root_cause"`
	Impact          string          `json:"impact"`
	Suggestions     []string        `json:"suggestions"`
	RelatedAlerts   []string        `json:"related_alerts"`
	Runbook         string          `json:"runbook,omitempty"`
	IsNoise         bool            `json:"is_noise"`
	Confidence      float64         `json:"confidence"`
	CorrelationID   string          `json:"correlation_id,omitempty"`
	Timestamp       time.Time       `json:"timestamp"`
}

// AlertCorrelation grupo de alertas correlacionados
type AlertCorrelation struct {
	ID              string       `json:"id"`
	Title           string       `json:"title"`
	Alerts          []SmartAlert `json:"alerts"`
	RootCause       string       `json:"root_cause"`
	Impact          string       `json:"impact"`
	Severity        string       `json:"severity"`
	StartTime       time.Time    `json:"start_time"`
	AffectedServices []string    `json:"affected_services"`
}

// NewSmartAlertEngine cria novo engine de alertas inteligentes
func NewSmartAlertEngine(engine *AIEngine) *SmartAlertEngine {
	return &SmartAlertEngine{
		engine:            engine,
		alertBuffer:       make([]RawAlert, 0),
		correlationWindow: 5 * time.Minute,
	}
}

// ProcessAlert processa um alerta com IA
func (s *SmartAlertEngine) ProcessAlert(ctx context.Context, raw RawAlert, systemContext AlertContext) (*SmartAlert, error) {
	// Adicionar ao buffer para correlação
	s.alertBuffer = append(s.alertBuffer, raw)
	s.cleanOldAlerts()

	prompt := fmt.Sprintf(`Analise este alerta e enriqueça com contexto inteligente:

ALERTA:
- Métrica: %s
- Host: %s
- Valor atual: %.2f
- Threshold: %.2f
- Severidade: %s
- Timestamp: %s
- Labels: %v

CONTEXTO DO SISTEMA:
- Deploys recentes: %s
- Alertas relacionados (últimos 5min): %d
- Incidentes abertos: %d
- Horário comercial: %v

ALERTAS RECENTES NO MESMO HOST:
%s

PADRÕES CONHECIDOS:
- Este tipo de alerta costuma ser: %s
- Falsos positivos históricos: %d%%

Analise e responda em JSON:
{
  "title": "título conciso e descritivo",
  "description": "descrição detalhada do que está acontecendo",
  "severity": "info|warning|error|critical",
  "category": "performance|availability|security|capacity|configuration",
  "root_cause": "provável causa raiz",
  "impact": "impacto no negócio/usuários",
  "suggestions": ["ação sugerida 1", "ação sugerida 2"],
  "is_noise": boolean (true se for falso positivo ou não acionável),
  "confidence": 0.0-1.0,
  "runbook": "link ou passos do runbook se existir"
}`,
		raw.Metric,
		raw.Host,
		raw.Value,
		raw.Threshold,
		raw.Severity,
		raw.Timestamp.Format(time.RFC3339),
		raw.Labels,
		systemContext.RecentDeploys,
		s.countRecentAlerts(raw.Host),
		systemContext.OpenIncidents,
		systemContext.IsBusinessHours,
		s.getRecentAlertsForHost(raw.Host),
		systemContext.HistoricalPattern,
		systemContext.FalsePositiveRate,
	)

	response, err := s.engine.chat(ctx, prompt)
	if err != nil {
		return nil, err
	}

	var smart SmartAlert
	if err := json.Unmarshal([]byte(response), &smart); err != nil {
		return nil, err
	}

	smart.ID = raw.ID
	smart.AffectedHosts = []string{raw.Host}
	smart.Timestamp = raw.Timestamp

	return &smart, nil
}

// CorrelateAlerts agrupa alertas relacionados
func (s *SmartAlertEngine) CorrelateAlerts(ctx context.Context, alerts []SmartAlert) (*AlertCorrelation, error) {
	if len(alerts) < 2 {
		return nil, nil
	}

	alertSummary := ""
	for _, a := range alerts {
		alertSummary += fmt.Sprintf("- [%s] %s on %s: %s\n", 
			a.Severity, a.Title, a.AffectedHosts[0], a.RootCause)
	}

	prompt := fmt.Sprintf(`Analise estes alertas e identifique se estão relacionados:

ALERTAS:
%s

Determine:
1. Se os alertas estão correlacionados (mesmo incidente)
2. Qual é a causa raiz comum
3. Qual é o impacto real
4. Qual deve ser a severidade consolidada

Responda em JSON:
{
  "correlated": boolean,
  "title": "título do incidente consolidado",
  "root_cause": "causa raiz comum",
  "impact": "impacto consolidado",
  "severity": "severidade do grupo",
  "affected_services": ["serviço1", "serviço2"],
  "timeline": "sequência de eventos",
  "recommendations": ["recomendação 1", "recomendação 2"]
}`, alertSummary)

	response, err := s.engine.chat(ctx, prompt)
	if err != nil {
		return nil, err
	}

	var result struct {
		Correlated       bool     `json:"correlated"`
		Title           string   `json:"title"`
		RootCause       string   `json:"root_cause"`
		Impact          string   `json:"impact"`
		Severity        string   `json:"severity"`
		AffectedServices []string `json:"affected_services"`
	}

	if err := json.Unmarshal([]byte(response), &result); err != nil {
		return nil, err
	}

	if !result.Correlated {
		return nil, nil
	}

	return &AlertCorrelation{
		ID:               fmt.Sprintf("corr_%d", time.Now().UnixNano()),
		Title:            result.Title,
		Alerts:           alerts,
		RootCause:        result.RootCause,
		Impact:           result.Impact,
		Severity:         result.Severity,
		StartTime:        alerts[0].Timestamp,
		AffectedServices: result.AffectedServices,
	}, nil
}

// SuppressNoise filtra alertas que são ruído
func (s *SmartAlertEngine) SuppressNoise(alerts []SmartAlert) []SmartAlert {
	filtered := make([]SmartAlert, 0)
	for _, a := range alerts {
		if !a.IsNoise && a.Confidence > 0.5 {
			filtered = append(filtered, a)
		}
	}
	return filtered
}

func (s *SmartAlertEngine) cleanOldAlerts() {
	cutoff := time.Now().Add(-s.correlationWindow)
	filtered := make([]RawAlert, 0)
	for _, a := range s.alertBuffer {
		if a.Timestamp.After(cutoff) {
			filtered = append(filtered, a)
		}
	}
	s.alertBuffer = filtered
}

func (s *SmartAlertEngine) countRecentAlerts(host string) int {
	count := 0
	for _, a := range s.alertBuffer {
		if a.Host == host {
			count++
		}
	}
	return count
}

func (s *SmartAlertEngine) getRecentAlertsForHost(host string) string {
	result := ""
	for _, a := range s.alertBuffer {
		if a.Host == host {
			result += fmt.Sprintf("- %s: %s = %.2f\n", a.Timestamp.Format("15:04:05"), a.Metric, a.Value)
		}
	}
	if result == "" {
		return "Nenhum alerta recente"
	}
	return result
}

// AlertContext contexto para processamento de alertas
type AlertContext struct {
	RecentDeploys     string
	OpenIncidents     int
	IsBusinessHours   bool
	HistoricalPattern string
	FalsePositiveRate int
}
