package metrics

import (
	"context"
	"fmt"
	"strconv"
	"time"

	"github.com/pkg/errors"
)

// PrometheusClient represents a Prometheus API client
type PrometheusClient interface {
	Query(ctx context.Context, query string) ([]MetricValue, error)
}

// MetricValue represents a metric value
type MetricValue struct {
	Value     float64
	Timestamp time.Time
	Labels    map[string]string
}

// Collector collects metrics for VMs
type Collector struct {
	client PrometheusClient
	cache  map[string]cachedMetric
}

type cachedMetric struct {
	value     []MetricValue
	timestamp time.Time
	ttl       time.Duration
}

// NewCollector creates a new metrics collector
func NewCollector(client PrometheusClient) *Collector {
	return &Collector{
		client: client,
		cache:  make(map[string]cachedMetric),
	}
}

// GetVMCPUUtilization gets CPU utilization for a VM
func (c *Collector) GetVMCPUUtilization(ctx context.Context, vmID int, node string) (float64, error) {
	// Query Prometheus for VM CPU utilization
	// This would use the pve-exporter metrics
	query := fmt.Sprintf(`avg(pve_vm_cpu_usage{vm="%d",node="%s"})`, vmID, node)
	
	values, err := c.queryWithCache(ctx, query, 30*time.Second)
	if err != nil {
		return 0, errors.Wrap(err, "failed to query CPU utilization")
	}

	if len(values) == 0 {
		return 0, fmt.Errorf("no CPU metrics found for VM %d", vmID)
	}

	return values[0].Value, nil
}

// GetVMMemoryUtilization gets memory utilization for a VM
func (c *Collector) GetVMMemoryUtilization(ctx context.Context, vmID int, node string) (float64, error) {
	query := fmt.Sprintf(`avg(pve_vm_memory_usage{vm="%d",node="%s"})`, vmID, node)
	
	values, err := c.queryWithCache(ctx, query, 30*time.Second)
	if err != nil {
		return 0, errors.Wrap(err, "failed to query memory utilization")
	}

	if len(values) == 0 {
		return 0, fmt.Errorf("no memory metrics found for VM %d", vmID)
	}

	return values[0].Value, nil
}

// GetCustomMetric gets a custom metric value
func (c *Collector) GetCustomMetric(ctx context.Context, query string) ([]MetricValue, error) {
	return c.queryWithCache(ctx, query, 60*time.Second)
}

// GetAverageMetric gets average metric value across multiple VMs
func (c *Collector) GetAverageMetric(
	ctx context.Context,
	vmIDs []int,
	node string,
	metricType string,
) (float64, error) {
	var total float64
	var count int

	for _, vmID := range vmIDs {
		var value float64
		var err error

		switch metricType {
		case "CPU":
			value, err = c.GetVMCPUUtilization(ctx, vmID, node)
		case "MEMORY":
			value, err = c.GetVMMemoryUtilization(ctx, vmID, node)
		default:
			return 0, fmt.Errorf("unsupported metric type: %s", metricType)
		}

		if err != nil {
			continue // Skip VMs without metrics
		}

		total += value
		count++
	}

	if count == 0 {
		return 0, fmt.Errorf("no metrics available for any VM")
	}

	return total / float64(count), nil
}

// queryWithCache queries Prometheus with caching
func (c *Collector) queryWithCache(
	ctx context.Context,
	query string,
	ttl time.Duration,
) ([]MetricValue, error) {
	// Check cache
	if cached, ok := c.cache[query]; ok {
		if time.Since(cached.timestamp) < cached.ttl {
			return cached.value, nil
		}
	}

	// Query Prometheus
	values, err := c.client.Query(ctx, query)
	if err != nil {
		return nil, err
	}

	// Update cache
	c.cache[query] = cachedMetric{
		value:     values,
		timestamp: time.Now(),
		ttl:       ttl,
	}

	return values, nil
}

// ParseThreshold parses a threshold string (e.g., "80" or "80%")
func ParseThreshold(threshold string) (float64, error) {
	if len(threshold) == 0 {
		return 0, fmt.Errorf("empty threshold")
	}

	// Remove % if present
	valueStr := threshold
	if threshold[len(threshold)-1] == '%' {
		valueStr = threshold[:len(threshold)-1]
	}

	value, err := strconv.ParseFloat(valueStr, 64)
	if err != nil {
		return 0, errors.Wrap(err, "failed to parse threshold")
	}

	// If % was present, ensure value is between 0-100
	if threshold[len(threshold)-1] == '%' {
		if value < 0 || value > 100 {
			return 0, fmt.Errorf("threshold must be between 0 and 100")
		}
	}

	return value, nil
}

