package ai

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

// OphionCopilot é o assistente de IA para troubleshooting
type OphionCopilot struct {
	engine       *AIEngine
	contextStore map[string]*ConversationContext
}

// ConversationContext contexto da conversa
type ConversationContext struct {
	SessionID    string
	UserID       string
	Messages     []CopilotMessage
	CurrentHost  string
	CurrentIssue string
	StartedAt    time.Time
}

// CopilotMessage mensagem do copilot
type CopilotMessage struct {
	Role      string    `json:"role"` // user, assistant
	Content   string    `json:"content"`
	Timestamp time.Time `json:"timestamp"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

// CopilotResponse resposta do copilot
type CopilotResponse struct {
	Message      string                 `json:"message"`
	Actions      []SuggestedAction      `json:"actions,omitempty"`
	Queries      []SuggestedQuery       `json:"queries,omitempty"`
	RelatedDocs  []string               `json:"related_docs,omitempty"`
	Confidence   float64                `json:"confidence"`
	NeedsHuman   bool                   `json:"needs_human"`
}

// SuggestedAction ação sugerida pelo copilot
type SuggestedAction struct {
	Type        string `json:"type"` // command, script, config_change, scale, restart
	Description string `json:"description"`
	Command     string `json:"command,omitempty"`
	Risk        string `json:"risk"` // low, medium, high
	AutoExecute bool   `json:"auto_execute"`
}

// SuggestedQuery query sugerida para investigação
type SuggestedQuery struct {
	Type  string `json:"type"` // metrics, logs, traces
	Query string `json:"query"`
	Description string `json:"description"`
}

// NewOphionCopilot cria nova instância do Copilot
func NewOphionCopilot(engine *AIEngine) *OphionCopilot {
	return &OphionCopilot{
		engine:       engine,
		contextStore: make(map[string]*ConversationContext),
	}
}

// Chat processa uma mensagem do usuário
func (c *OphionCopilot) Chat(ctx context.Context, sessionID, userMessage string, systemContext SystemContext) (*CopilotResponse, error) {
	// Obter ou criar contexto da conversa
	convCtx := c.getOrCreateContext(sessionID)
	
	// Adicionar mensagem do usuário
	convCtx.Messages = append(convCtx.Messages, CopilotMessage{
		Role:      "user",
		Content:   userMessage,
		Timestamp: time.Now(),
	})

	// Construir prompt com contexto completo
	prompt := c.buildPrompt(userMessage, convCtx, systemContext)

	// Chamar IA
	response, err := c.engine.chat(ctx, prompt)
	if err != nil {
		return nil, err
	}

	// Parsear resposta
	var result CopilotResponse
	if err := json.Unmarshal([]byte(response), &result); err != nil {
		// Se não for JSON válido, retornar como mensagem simples
		result = CopilotResponse{
			Message:    response,
			Confidence: 0.7,
		}
	}

	// Adicionar resposta ao contexto
	convCtx.Messages = append(convCtx.Messages, CopilotMessage{
		Role:      "assistant",
		Content:   result.Message,
		Timestamp: time.Now(),
		Metadata: map[string]interface{}{
			"confidence": result.Confidence,
			"actions":    len(result.Actions),
		},
	})

	return &result, nil
}

// buildPrompt constrói o prompt completo
func (c *OphionCopilot) buildPrompt(userMessage string, convCtx *ConversationContext, sysCtx SystemContext) string {
	var sb strings.Builder

	sb.WriteString(`Você é o OPHION Copilot, um assistente especialista em observabilidade e troubleshooting de infraestrutura.

SUAS CAPACIDADES:
- Analisar métricas, logs e traces
- Identificar causas raiz de problemas
- Sugerir comandos e ações de correção
- Explicar conceitos de forma clara
- Correlacionar eventos de diferentes fontes

CONTEXTO DO SISTEMA:
`)

	// Adicionar contexto do sistema
	sb.WriteString(fmt.Sprintf(`
Hosts monitorados: %d
Alertas ativos: %d
Incidentes abertos: %d
Último deploy: %s
`, sysCtx.TotalHosts, sysCtx.ActiveAlerts, sysCtx.OpenIncidents, sysCtx.LastDeploy))

	// Métricas atuais
	if len(sysCtx.CurrentMetrics) > 0 {
		sb.WriteString("\nMÉTRICAS ATUAIS:\n")
		for host, metrics := range sysCtx.CurrentMetrics {
			sb.WriteString(fmt.Sprintf("- %s: CPU=%.1f%%, MEM=%.1f%%, Disco=%.1f%%\n",
				host, metrics.CPU, metrics.Memory, metrics.Disk))
		}
	}

	// Alertas recentes
	if len(sysCtx.RecentAlerts) > 0 {
		sb.WriteString("\nALERTAS RECENTES:\n")
		for _, alert := range sysCtx.RecentAlerts {
			sb.WriteString(fmt.Sprintf("- [%s] %s: %s\n", alert.Severity, alert.Host, alert.Message))
		}
	}

	// Histórico da conversa
	if len(convCtx.Messages) > 1 {
		sb.WriteString("\nHISTÓRICO DA CONVERSA:\n")
		for _, msg := range convCtx.Messages[max(0, len(convCtx.Messages)-6):] {
			sb.WriteString(fmt.Sprintf("%s: %s\n", msg.Role, msg.Content))
		}
	}

	// Pergunta atual
	sb.WriteString(fmt.Sprintf(`
PERGUNTA DO USUÁRIO:
%s

INSTRUÇÕES DE RESPOSTA:
1. Seja direto e prático
2. Se sugerir comandos, explique o que fazem
3. Indique o nível de risco das ações
4. Se não tiver certeza, diga e sugira investigações adicionais

Responda em JSON:
{
  "message": "sua resposta detalhada",
  "actions": [
    {
      "type": "command|script|config_change|scale|restart",
      "description": "o que faz",
      "command": "comando se aplicável",
      "risk": "low|medium|high",
      "auto_execute": false
    }
  ],
  "queries": [
    {
      "type": "metrics|logs|traces",
      "query": "query para investigar",
      "description": "o que vai mostrar"
    }
  ],
  "confidence": 0.0-1.0,
  "needs_human": false
}`, userMessage))

	return sb.String()
}

func (c *OphionCopilot) getOrCreateContext(sessionID string) *ConversationContext {
	if ctx, exists := c.contextStore[sessionID]; exists {
		return ctx
	}
	
	ctx := &ConversationContext{
		SessionID: sessionID,
		Messages:  []CopilotMessage{},
		StartedAt: time.Now(),
	}
	c.contextStore[sessionID] = ctx
	return ctx
}

// SystemContext contexto do sistema para o copilot
type SystemContext struct {
	TotalHosts     int
	ActiveAlerts   int
	OpenIncidents  int
	LastDeploy     string
	CurrentMetrics map[string]HostMetrics
	RecentAlerts   []AlertInfo
	RecentLogs     []string
}

// HostMetrics métricas de um host
type HostMetrics struct {
	CPU    float64
	Memory float64
	Disk   float64
}

// AlertInfo informação de alerta
type AlertInfo struct {
	Severity string
	Host     string
	Message  string
	Time     time.Time
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
