package lxc

import (
	"fmt"
	"time"

	"clicd/internal/config"
)

// IsExpired checks if a container has passed its expiration date
func IsExpired(c config.Container) bool {
	return isContainerExpired(c, time.Now())
}

// StopExpiredContainers stops running containers whose expiration date has passed.
func (m *Manager) StopExpiredContainers(now time.Time) {
	for _, container := range config.AppConfig.Containers {
		if container.IsKVM() || !isContainerExpired(container, now) {
			continue
		}

		status, err := m.GetContainerStatus(container.LxcName())
		if err != nil {
			status = container.Status
		}
		if status != "running" {
			continue
		}

		fmt.Printf("Container %s (ID=%d) expired at %s, stopping...\n", container.Name, container.ID, container.ExpiresAt)
		if err := m.StopContainer(container.ID); err != nil {
			fmt.Printf("Warning: failed to stop expired container %s: %v\n", container.Name, err)
		}
	}
}

// StartExpiryScanner runs a background loop that tracks traffic & stops expired/over-traffic containers every 30 seconds
func (m *Manager) StartExpiryScanner() {
	go func() {
		for {
			time.Sleep(30 * time.Second)
			now := time.Now()
			m.AccumulateTraffic() // track network traffic deltas
			m.StopExpiredContainers(now)
			m.StopTrafficExceededContainers(now)
		}
	}()
}

// StopTrafficExceededContainers stops running containers that have exceeded their monthly traffic limit
func (m *Manager) StopTrafficExceededContainers(now time.Time) {
	currentMonth := now.Format("2006-01")
	saved := false
	for i := range config.AppConfig.Containers {
		c := &config.AppConfig.Containers[i]
		if c.IsKVM() || c.Status != "running" {
			continue
		}

		// Reset traffic if new month
		if c.TrafficResetDate != currentMonth {
			c.TrafficUsedRX = 0
			c.TrafficUsedTX = 0
			c.TrafficResetDate = currentMonth
			saved = true
			continue
		}

		// Check traffic limits
		if isTrafficExceeded(*c) {
			fmt.Printf("Container %s (ID=%d) exceeded traffic limit, stopping...\n", c.Name, c.ID)
			if err := m.StopContainer(c.ID); err != nil {
				fmt.Printf("Warning: failed to stop traffic-exceeded container %s: %v\n", c.Name, err)
			}
		}
	}
	if saved {
		config.SaveConfig()
	}
}

func isTrafficExceeded(c config.Container) bool {
	if c.TrafficMode == "in_out" {
		inLimit := int64(c.TrafficInGB) * 1073741824
		outLimit := int64(c.TrafficOutGB) * 1073741824
		if inLimit > 0 && c.TrafficUsedRX >= inLimit {
			return true
		}
		if outLimit > 0 && c.TrafficUsedTX >= outLimit {
			return true
		}
		return false
	}
	totalLimit := int64(c.MonthlyTrafficGB) * 1073741824
	return totalLimit > 0 && (c.TrafficUsedRX+c.TrafficUsedTX) >= totalLimit
}

// ResetTraffic resets traffic counters for a container
func (m *Manager) ResetTraffic(id int) error {
	c := config.FindContainer(id)
	if c == nil {
		return fmt.Errorf("container not found: %d", id)
	}
	c.TrafficUsedRX = 0
	c.TrafficUsedTX = 0
	c.TrafficResetDate = time.Now().Format("2006-01")
	config.SaveConfig()
	return nil
}

// IsTrafficExceeded checks if a container has exceeded its traffic limit
func IsTrafficExceeded(c config.Container) bool {
	return isTrafficExceeded(c)
}

func isContainerExpired(container config.Container, now time.Time) bool {
	expiresAt, ok := ParseExpiration(container.ExpiresAt)
	return ok && !now.Before(expiresAt)
}

// ParseExpiration parses an expiration string. A YYYY-MM-DD value expires at the
// end of that local day, while RFC3339 values are treated as exact timestamps.
func ParseExpiration(value string) (time.Time, bool) {
	if value == "" {
		return time.Time{}, false
	}

	if parsed, err := time.Parse(time.RFC3339, value); err == nil {
		return parsed, true
	}

	if parsed, err := time.ParseInLocation("2006-01-02", value, time.Local); err == nil {
		return parsed.Add(24 * time.Hour), true
	}

	return time.Time{}, false
}
