package collector

import (
	"os/exec"
	"strings"
)

type PendingUpdate struct {
	Package    string `json:"package"`
	CurrentVer string `json:"current_version"`
	NewVer     string `json:"new_version"`
}

type UpdateInfo struct {
	UpdateAvailable bool            `json:"update_available"`
	PendingCount    int             `json:"pending_count"`
	Updates         []PendingUpdate `json:"updates"`
	OPNsenseUpdate  string          `json:"opnsense_update,omitempty"` // z.B. "26.1.2 -> 26.1.2_5"
}

// CollectUpdates prueft ob Updates verfuegbar sind
func CollectUpdates() UpdateInfo {
	info := UpdateInfo{}

	// 1. OPNsense Core Update pruefen
	// opnsense-update -c: exit 0 = kein Update, exit 1 = Update verfuegbar (mit Versions-Info auf stdout)
	if out, err := exec.Command("/usr/local/sbin/opnsense-update", "-c").CombinedOutput(); err != nil {
		// Exit 1 = Update verfuegbar
		outStr := strings.TrimSpace(string(out))
		if outStr != "" {
			info.OPNsenseUpdate = outStr
			info.UpdateAvailable = true
		}
	}

	// 2. Paket-Updates pruefen via pkg upgrade -n (dry-run)
	out, err := exec.Command("/usr/sbin/pkg", "upgrade", "-n").CombinedOutput()
	if err != nil || len(out) == 0 {
		// Bei pkg upgrade -n ist exit 1 = Updates verfuegbar
		// Trotzdem stdout parsen
	}

	content := string(out)

	// Zeilen mit ":" im UPGRADED-Block parsen
	// Format: "\tpackage: old_version -> new_version"
	inUpgradeBlock := false
	for _, line := range strings.Split(content, "\n") {
		trimmed := strings.TrimSpace(line)

		if strings.Contains(trimmed, "packages to be UPGRADED") ||
			strings.Contains(trimmed, "will be affected") {
			inUpgradeBlock = true
			continue
		}

		if inUpgradeBlock && strings.Contains(trimmed, "->") {
			// Format: "package: old -> new"
			parts := strings.SplitN(trimmed, ":", 2)
			if len(parts) == 2 {
				pkg := strings.TrimSpace(parts[0])
				versions := strings.TrimSpace(parts[1])

				arrowParts := strings.SplitN(versions, "->", 2)
				if len(arrowParts) == 2 {
					update := PendingUpdate{
						Package:    pkg,
						CurrentVer: strings.TrimSpace(arrowParts[0]),
						NewVer:     strings.TrimSpace(arrowParts[1]),
					}
					info.Updates = append(info.Updates, update)
					info.UpdateAvailable = true
				}
			}
		}

		// Block endet bei Leerzeile oder "Number of packages"
		if inUpgradeBlock && (trimmed == "" || strings.HasPrefix(trimmed, "Number of")) {
			if strings.HasPrefix(trimmed, "Number of") {
				continue
			}
			inUpgradeBlock = false
		}
	}

	info.PendingCount = len(info.Updates)
	return info
}
