package ai

import (
	"fmt"
	"time"

	"github.com/rcourtman/pulse-go-rewrite/internal/alerts"
	"github.com/rcourtman/pulse-go-rewrite/internal/models"
)

// AlertManagerAdapter adapts the alerts.Manager to the AI's AlertProvider interface
type AlertManagerAdapter struct {
	manager *alerts.Manager
}

// NewAlertManagerAdapter creates a new adapter for the alert manager
func NewAlertManagerAdapter(manager *alerts.Manager) *AlertManagerAdapter {
	return &AlertManagerAdapter{manager: manager}
}

// GetActiveAlerts returns all currently active alerts
func (a *AlertManagerAdapter) GetActiveAlerts() []AlertInfo {
	if a.manager == nil {
		return nil
	}

	activeAlerts := a.manager.GetActiveAlerts()
	result := make([]AlertInfo, 0, len(activeAlerts))

	for _, alert := range activeAlerts {
		result = append(result, convertAlertFromManager(&alert))
	}

	return result
}

// GetRecentlyResolved returns alerts resolved in the last N minutes
func (a *AlertManagerAdapter) GetRecentlyResolved(minutes int) []ResolvedAlertInfo {
	if a.manager == nil {
		return nil
	}

	resolvedAlerts := a.manager.GetRecentlyResolved()
	cutoff := time.Now().Add(-time.Duration(minutes) * time.Minute)
	result := make([]ResolvedAlertInfo, 0)

	for _, resolved := range resolvedAlerts {
		if resolved.ResolvedTime.After(cutoff) {
			info := ResolvedAlertInfo{
				AlertInfo:    convertAlertFromModels(&resolved.Alert),
				ResolvedTime: resolved.ResolvedTime,
				Duration:     formatDuration(resolved.ResolvedTime.Sub(resolved.StartTime)),
			}
			result = append(result, info)
		}
	}

	return result
}

// GetAlertsByResource returns active alerts for a specific resource
func (a *AlertManagerAdapter) GetAlertsByResource(resourceID string) []AlertInfo {
	if a.manager == nil {
		return nil
	}

	activeAlerts := a.manager.GetActiveAlerts()
	result := make([]AlertInfo, 0)

	for _, alert := range activeAlerts {
		if alert.ResourceID == resourceID {
			result = append(result, convertAlertFromManager(&alert))
		}
	}

	return result
}

// GetAlertHistory returns historical alerts for a resource
func (a *AlertManagerAdapter) GetAlertHistory(resourceID string, limit int) []ResolvedAlertInfo {
	if a.manager == nil {
		return nil
	}

	// Get from recently resolved and filter by resource
	resolvedAlerts := a.manager.GetRecentlyResolved()
	result := make([]ResolvedAlertInfo, 0)

	for _, resolved := range resolvedAlerts {
		if resolved.ResourceID == resourceID {
			info := ResolvedAlertInfo{
				AlertInfo:    convertAlertFromModels(&resolved.Alert),
				ResolvedTime: resolved.ResolvedTime,
				Duration:     formatDuration(resolved.ResolvedTime.Sub(resolved.StartTime)),
			}
			result = append(result, info)
			if len(result) >= limit {
				break
			}
		}
	}

	return result
}

// convertAlertFromManager converts an alerts.Alert to AI's AlertInfo
func convertAlertFromManager(alert *alerts.Alert) AlertInfo {
	if alert == nil {
		return AlertInfo{}
	}

	resourceType := inferResourceType(alert.Type, alert.Metadata)

	return AlertInfo{
		ID:           alert.ID,
		Type:         alert.Type,
		Level:        string(alert.Level),
		ResourceID:   alert.ResourceID,
		ResourceName: alert.ResourceName,
		ResourceType: resourceType,
		Node:         alert.Node,
		Instance:     alert.Instance,
		Message:      alert.Message,
		Value:        alert.Value,
		Threshold:    alert.Threshold,
		StartTime:    alert.StartTime,
		Duration:     formatDuration(time.Since(alert.StartTime)),
		Acknowledged: alert.Acknowledged,
	}
}

// convertAlertFromModels converts a models.Alert to AI's AlertInfo
func convertAlertFromModels(alert *models.Alert) AlertInfo {
	if alert == nil {
		return AlertInfo{}
	}

	resourceType := inferResourceType(alert.Type, nil)

	return AlertInfo{
		ID:           alert.ID,
		Type:         alert.Type,
		Level:        alert.Level,
		ResourceID:   alert.ResourceID,
		ResourceName: alert.ResourceName,
		ResourceType: resourceType,
		Node:         alert.Node,
		Instance:     alert.Instance,
		Message:      alert.Message,
		Value:        alert.Value,
		Threshold:    alert.Threshold,
		StartTime:    alert.StartTime,
		Duration:     formatDuration(time.Since(alert.StartTime)),
		Acknowledged: alert.Acknowledged,
	}
}

// inferResourceType infers resource type from alert type
func inferResourceType(alertType string, metadata map[string]interface{}) string {
	if metadata != nil {
		if rt, ok := metadata["resourceType"].(string); ok {
			return rt
		}
	}

	switch {
	case alertType == "node_offline" || alertType == "node_cpu" || alertType == "node_memory" || alertType == "node_temperature":
		return "node"
	case alertType == "storage_usage" || alertType == "storage":
		return "storage"
	case alertType == "docker_cpu" || alertType == "docker_memory" || alertType == "docker_restart" || alertType == "docker_offline":
		return "docker"
	case alertType == "host_cpu" || alertType == "host_memory" || alertType == "host_offline" || alertType == "host_disk":
		return "host"
	case alertType == "pmg" || alertType == "pmg_queue" || alertType == "pmg_quarantine":
		return "pmg"
	case alertType == "backup" || alertType == "backup_missing":
		return "backup"
	case alertType == "snapshot" || alertType == "snapshot_age":
		return "snapshot"
	default:
		return "guest"
	}
}

// formatDuration returns a human-readable duration string
func formatDuration(d time.Duration) string {
	if d < time.Minute {
		return "< 1 min"
	} else if d < time.Hour {
		mins := int(d.Minutes())
		if mins == 1 {
			return "1 min"
		}
		return fmt.Sprintf("%d mins", mins)
	} else if d < 24*time.Hour {
		hours := int(d.Hours())
		mins := int(d.Minutes()) % 60
		if mins > 0 {
			return fmt.Sprintf("%dh %dm", hours, mins)
		}
		if hours == 1 {
			return "1 hour"
		}
		return fmt.Sprintf("%d hours", hours)
	}
	days := int(d.Hours() / 24)
	hours := int(d.Hours()) % 24
	if hours > 0 {
		return fmt.Sprintf("%dd %dh", days, hours)
	}
	if days == 1 {
		return "1 day"
	}
	return fmt.Sprintf("%d days", days)
}
