package scanner

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/Fimeg/RedFlag/aggregator-agent/internal/client"
)

// WingetPackage represents a single package from winget output
type WingetPackage struct {
	Name           string `json:"Name"`
	ID             string `json:"Id"`
	Version        string `json:"Version"`
	Available      string `json:"Available"`
	Source         string `json:"Source"`
	IsPinned       bool   `json:"IsPinned"`
	PinReason      string `json:"PinReason,omitempty"`
}

// WingetScanner scans for Windows package updates using winget
type WingetScanner struct{}

// NewWingetScanner creates a new Winget scanner
func NewWingetScanner() *WingetScanner {
	return &WingetScanner{}
}

// IsAvailable checks if winget is available on this system
func (s *WingetScanner) IsAvailable() bool {
	if runtime.GOOS != "windows" {
		return false
	}
	_, err := s.findWingetPath()
	return err == nil
}

// findWingetPath searches PATH and known system-wide install locations (F-C1-1 fix).
// This ensures winget is found when running as SYSTEM service account.
func (s *WingetScanner) findWingetPath() (string, error) {
	// 1. Check PATH first (fastest, works for user-space installs)
	if path, err := exec.LookPath("winget"); err == nil {
		return path, nil
	}

	// 2. Check known system-wide install locations (accessible to SYSTEM account)
	// TODO: winget v1.6+ required for --output json flag
	knownPaths := []string{
		`C:\Windows\System32\winget.exe`,
	}

	// 3. Glob for versioned WindowsApps directory
	globPattern := `C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*\winget.exe`
	if matches, err := filepath.Glob(globPattern); err == nil {
		knownPaths = append(knownPaths, matches...)
	}

	for _, p := range knownPaths {
		if _, err := os.Stat(p); err == nil {
			log.Printf("[INFO] [agent] [scanner] winget_found_at path=%q", p)
			return p, nil
		}
	}

	log.Printf("[INFO] [agent] [scanner] winget_not_found checked_path_and_known_locations")
	return "", fmt.Errorf("winget not found in PATH or known locations")
}

// Scan scans for available winget package updates
func (s *WingetScanner) Scan() ([]client.UpdateReportItem, error) {
	if !s.IsAvailable() {
		return nil, fmt.Errorf("winget is not available on this system")
	}

	// Try multiple approaches with proper error handling
	var lastErr error

	// Method 1: Standard winget list with JSON output
	if updates, err := s.scanWithJSON(); err == nil {
		return updates, nil
	} else {
		lastErr = err
		log.Printf("Winget JSON scan failed: %v\n", err)
	}

	// Method 2: Fallback to basic winget list without JSON
	if updates, err := s.scanWithBasicOutput(); err == nil {
		return updates, nil
	} else {
		lastErr = fmt.Errorf("both winget scan methods failed: %v (last error)", err)
		log.Printf("Winget basic scan failed: %v\n", err)
	}

	// Method 3: Attempt automatic recovery for known issues
	if isKnownWingetError(lastErr) {
		log.Printf("Attempting automatic winget recovery...\n")
		if updates, err := s.attemptWingetRecovery(); err == nil {
			log.Printf("Winget recovery successful, found %d updates\n", len(updates))
			return updates, nil
		} else {
			log.Printf("Winget recovery failed: %v\n", err)
		}

		return nil, fmt.Errorf("winget encountered a known issue (exit code %s). This may be due to Windows Update service or system configuration. Automatic recovery was attempted but failed", getExitCode(lastErr))
	}

	return nil, lastErr
}

// scanWithJSON attempts to scan using JSON output (most reliable)
func (s *WingetScanner) scanWithJSON() ([]client.UpdateReportItem, error) {
	// Run winget list command to get outdated packages
	// Using --output json for structured output
	cmd := exec.Command("winget", "list", "--outdated", "--accept-source-agreements", "--output", "json")

	// Use CombinedOutput to capture both stdout and stderr for better error handling
	output, err := cmd.CombinedOutput()
	if err != nil {
		// Check for specific exit codes that might be transient
		if isTransientError(err) {
			return nil, fmt.Errorf("winget temporary failure: %w", err)
		}
		return nil, fmt.Errorf("failed to run winget list: %w (output: %s)", err, string(output))
	}

	// Parse JSON output
	var packages []WingetPackage
	if err := json.Unmarshal(output, &packages); err != nil {
		return nil, fmt.Errorf("failed to parse winget JSON output: %w (output: %s)", err, string(output))
	}

	var updates []client.UpdateReportItem

	// Convert each package to our UpdateReportItem format
	for _, pkg := range packages {
		// Skip if no available update
		if pkg.Available == "" || pkg.Available == pkg.Version {
			continue
		}

		updateItem := s.parseWingetPackage(pkg)
		updates = append(updates, *updateItem)
	}

	return updates, nil
}

// scanWithBasicOutput falls back to parsing text output
func (s *WingetScanner) scanWithBasicOutput() ([]client.UpdateReportItem, error) {
	cmd := exec.Command("winget", "list", "--outdated", "--accept-source-agreements")
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to run winget list basic: %w", err)
	}

	// Simple text parsing fallback
	return s.parseWingetTextOutput(string(output))
}

// parseWingetTextOutput parses winget text output using column-position parsing (F-C1-2 fix).
// Handles package names with spaces by using the header separator line to determine column widths.
func (s *WingetScanner) parseWingetTextOutput(output string) ([]client.UpdateReportItem, error) {
	var updates []client.UpdateReportItem
	lines := strings.Split(output, "\n")

	// Find the separator line to determine column positions
	separatorIdx := -1
	for i, line := range lines {
		trimmed := strings.TrimSpace(line)
		if len(trimmed) > 5 && strings.Count(trimmed, "-") > len(trimmed)/2 {
			separatorIdx = i
			break
		}
	}

	if separatorIdx < 1 || separatorIdx >= len(lines)-1 {
		// Fall back to simple parsing if no separator found
		return s.parseWingetTextSimple(output)
	}

	// Parse column positions from the header line
	// Column headers are separated by 2+ spaces
	headerLine := lines[separatorIdx-1]

	// Find column start positions by locating header keywords
	colNames := []string{"Name", "Id", "Version", "Available"}
	colStarts := make([]int, 0, len(colNames))
	for _, name := range colNames {
		idx := strings.Index(headerLine, name)
		if idx >= 0 {
			colStarts = append(colStarts, idx)
		}
	}

	if len(colStarts) < 3 {
		// Not enough columns found, fall back
		return s.parseWingetTextSimple(output)
	}

	// Parse data lines
	for i := separatorIdx + 1; i < len(lines); i++ {
		line := lines[i]
		if strings.TrimSpace(line) == "" {
			continue
		}

		// Extract columns by position
		var cols []string
		for j, start := range colStarts {
			if start >= len(line) {
				cols = append(cols, "")
				continue
			}
			end := len(line)
			if j+1 < len(colStarts) {
				end = colStarts[j+1]
				if end > len(line) {
					end = len(line)
				}
			}
			cols = append(cols, strings.TrimSpace(line[start:end]))
		}

		if len(cols) < 3 {
			continue
		}

		// Column order: Name, [Id], Version, Available
		pkgName := cols[0]
		currentVersion := cols[len(cols)-2]
		availableVersion := cols[len(cols)-1]

		if availableVersion == currentVersion || availableVersion == "Unknown" || availableVersion == "" {
			continue
		}

		update := client.UpdateReportItem{
			PackageType:        "winget",
			PackageName:        pkgName,
			CurrentVersion:     currentVersion,
			AvailableVersion:   availableVersion,
			Severity:           s.determineSeverityFromName(pkgName),
			RepositorySource:   "winget",
			PackageDescription: fmt.Sprintf("Update available for %s", pkgName),
			Metadata: map[string]interface{}{
				"package_manager": "winget",
				"detected_via":    "text_parser",
			},
		}
		updates = append(updates, update)
	}

	return updates, nil
}

// parseWingetTextSimple is the legacy simple parser for outputs without clear column headers
func (s *WingetScanner) parseWingetTextSimple(output string) ([]client.UpdateReportItem, error) {
	var updates []client.UpdateReportItem
	lines := strings.Split(output, "\n")

	for _, line := range lines {
		line = strings.TrimSpace(line)
		if strings.HasPrefix(line, "Name") || strings.HasPrefix(line, "-") || line == "" {
			continue
		}

		fields := strings.Fields(line)
		if len(fields) >= 3 {
			pkgName := fields[0]
			currentVersion := fields[len(fields)-2]
			availableVersion := fields[len(fields)-1]

			if availableVersion == currentVersion || availableVersion == "Unknown" {
				continue
			}

			update := client.UpdateReportItem{
				PackageType:        "winget",
				PackageName:        pkgName,
				CurrentVersion:     currentVersion,
				AvailableVersion:   availableVersion,
				Severity:           s.determineSeverityFromName(pkgName),
				RepositorySource:   "winget",
				PackageDescription: fmt.Sprintf("Update available for %s", pkgName),
				Metadata: map[string]interface{}{
					"package_manager": "winget",
					"detected_via":    "text_parser",
				},
			}
			updates = append(updates, update)
		}
	}

	return updates, nil
}

// isTransientError checks if the error might be temporary
func isTransientError(err error) bool {
	if err == nil {
		return false
	}

	errStr := err.Error()
	// Common transient error patterns
	transientPatterns := []string{
		"network error",
		"timeout",
		"connection refused",
		"temporary failure",
		"service unavailable",
	}

	for _, pattern := range transientPatterns {
		if strings.Contains(strings.ToLower(errStr), pattern) {
			return true
		}
	}

	return false
}

// isKnownWingetError checks for known Winget issues
func isKnownWingetError(err error) bool {
	if err == nil {
		return false
	}

	errStr := err.Error()
	// Check for the specific exit code 0x8a150002
	if strings.Contains(errStr, "2316632066") || strings.Contains(errStr, "0x8a150002") {
		return true
	}

	// Other known Winget issues
	knownPatterns := []string{
		"winget is not recognized",
		"windows package manager",
		"windows app installer",
		"restarting your computer",
	}

	for _, pattern := range knownPatterns {
		if strings.Contains(strings.ToLower(errStr), pattern) {
			return true
		}
	}

	return false
}

// getExitCode extracts exit code from error if available
func getExitCode(err error) string {
	if err == nil {
		return "unknown"
	}

	// Try to extract exit code from error message
	errStr := err.Error()
	if strings.Contains(errStr, "exit status") {
		// Extract exit status number
		parts := strings.Fields(errStr)
		for i, part := range parts {
			if part == "status" && i+1 < len(parts) {
				return parts[i+1]
			}
		}
	}

	return "unknown"
}

// determineSeverityFromName provides basic severity detection for fallback
func (s *WingetScanner) determineSeverityFromName(name string) string {
	lowerName := strings.ToLower(name)

	// Security tools get higher priority
	if strings.Contains(lowerName, "antivirus") ||
	   strings.Contains(lowerName, "security") ||
	   strings.Contains(lowerName, "defender") ||
	   strings.Contains(lowerName, "firewall") {
		return "critical"
	}

	// Browsers and communication tools get high priority
	if strings.Contains(lowerName, "firefox") ||
	   strings.Contains(lowerName, "chrome") ||
	   strings.Contains(lowerName, "edge") ||
	   strings.Contains(lowerName, "browser") {
		return "high"
	}

	return "moderate"
}

// parseWingetPackage converts a WingetPackage to our UpdateReportItem format
func (s *WingetScanner) parseWingetPackage(pkg WingetPackage) *client.UpdateReportItem {
	// Determine severity based on package type and source
	severity := s.determineSeverity(pkg)

	// Categorize the package type
	packageCategory := s.categorizePackage(pkg.Name, pkg.Source)

	// Create metadata with winget-specific information
	metadata := map[string]interface{}{
		"package_id":     pkg.ID,
		"source":         pkg.Source,
		"category":       packageCategory,
		"is_pinned":      pkg.IsPinned,
		"pin_reason":     pkg.PinReason,
		"package_manager": "winget",
	}

	// Add additional metadata based on package source
	if pkg.Source == "winget" {
		metadata["repository_type"] = "community"
	} else if pkg.Source == "msstore" {
		metadata["repository_type"] = "microsoft_store"
	} else {
		metadata["repository_type"] = "custom"
	}

	// Create the update report item
	updateItem := &client.UpdateReportItem{
		PackageType:      "winget",
		PackageName:      pkg.Name,
		CurrentVersion:   pkg.Version,
		AvailableVersion: pkg.Available,
		Severity:         severity,
		RepositorySource: pkg.Source,
		Metadata:         metadata,
	}

	// Add description if available (would need additional winget calls)
	// For now, we'll use the package name as description
	updateItem.PackageDescription = fmt.Sprintf("Update available for %s from %s", pkg.Name, pkg.Source)

	return updateItem
}

// determineSeverity determines the severity of a package update based on various factors
func (s *WingetScanner) determineSeverity(pkg WingetPackage) string {
	name := strings.ToLower(pkg.Name)
	source := strings.ToLower(pkg.Source)

	// Security tools get higher priority
	if strings.Contains(name, "antivirus") ||
	   strings.Contains(name, "security") ||
	   strings.Contains(name, "firewall") ||
	   strings.Contains(name, "malware") ||
	   strings.Contains(name, "defender") ||
	   strings.Contains(name, "crowdstrike") ||
	   strings.Contains(name, "sophos") ||
	   strings.Contains(name, "symantec") {
		return "critical"
	}

	// Browsers and communication tools get high priority
	if strings.Contains(name, "firefox") ||
	   strings.Contains(name, "chrome") ||
	   strings.Contains(name, "edge") ||
	   strings.Contains(name, "browser") ||
	   strings.Contains(name, "zoom") ||
	   strings.Contains(name, "teams") ||
	   strings.Contains(name, "slack") ||
	   strings.Contains(name, "discord") {
		return "high"
	}

	// Development tools
	if strings.Contains(name, "visual studio") ||
	   strings.Contains(name, "vscode") ||
	   strings.Contains(name, "git") ||
	   strings.Contains(name, "docker") ||
	   strings.Contains(name, "nodejs") ||
	   strings.Contains(name, "python") ||
	   strings.Contains(name, "java") ||
	   strings.Contains(name, "powershell") {
		return "moderate"
	}

	// Microsoft Store apps might be less critical
	if source == "msstore" {
		return "low"
	}

	// Default severity
	return "moderate"
}

// categorizePackage categorizes the package based on name and source
func (s *WingetScanner) categorizePackage(name, source string) string {
	lowerName := strings.ToLower(name)

	// Development tools
	if strings.Contains(lowerName, "visual studio") ||
	   strings.Contains(lowerName, "vscode") ||
	   strings.Contains(lowerName, "intellij") ||
	   strings.Contains(lowerName, "sublime") ||
	   strings.Contains(lowerName, "notepad++") ||
	   strings.Contains(lowerName, "git") ||
	   strings.Contains(lowerName, "docker") ||
	   strings.Contains(lowerName, "nodejs") ||
	   strings.Contains(lowerName, "python") ||
	   strings.Contains(lowerName, "java") ||
	   strings.Contains(lowerName, "rust") ||
	   strings.Contains(lowerName, "go") ||
	   strings.Contains(lowerName, "github") ||
	   strings.Contains(lowerName, "postman") ||
	   strings.Contains(lowerName, "wireshark") {
		return "development"
	}

	// Security tools
	if strings.Contains(lowerName, "antivirus") ||
	   strings.Contains(lowerName, "security") ||
	   strings.Contains(lowerName, "firewall") ||
	   strings.Contains(lowerName, "malware") ||
	   strings.Contains(lowerName, "defender") ||
	   strings.Contains(lowerName, "crowdstrike") ||
	   strings.Contains(lowerName, "sophos") ||
	   strings.Contains(lowerName, "symantec") ||
	   strings.Contains(lowerName, "vpn") ||
	   strings.Contains(lowerName, "1password") ||
	   strings.Contains(lowerName, "bitwarden") ||
	   strings.Contains(lowerName, "lastpass") {
		return "security"
	}

	// Browsers
	if strings.Contains(lowerName, "firefox") ||
	   strings.Contains(lowerName, "chrome") ||
	   strings.Contains(lowerName, "edge") ||
	   strings.Contains(lowerName, "opera") ||
	   strings.Contains(lowerName, "brave") ||
	   strings.Contains(lowerName, "vivaldi") ||
	   strings.Contains(lowerName, "browser") {
		return "browser"
	}

	// Communication tools
	if strings.Contains(lowerName, "zoom") ||
	   strings.Contains(lowerName, "teams") ||
	   strings.Contains(lowerName, "slack") ||
	   strings.Contains(lowerName, "discord") ||
	   strings.Contains(lowerName, "telegram") ||
	   strings.Contains(lowerName, "whatsapp") ||
	   strings.Contains(lowerName, "skype") ||
	   strings.Contains(lowerName, "outlook") {
		return "communication"
	}

	// Media and entertainment
	if strings.Contains(lowerName, "vlc") ||
	   strings.Contains(lowerName, "spotify") ||
	   strings.Contains(lowerName, "itunes") ||
	   strings.Contains(lowerName, "plex") ||
	   strings.Contains(lowerName, "kodi") ||
	   strings.Contains(lowerName, "obs") ||
	   strings.Contains(lowerName, "streamlabs") {
		return "media"
	}

	// Productivity tools
	if strings.Contains(lowerName, "microsoft office") ||
	   strings.Contains(lowerName, "word") ||
	   strings.Contains(lowerName, "excel") ||
	   strings.Contains(lowerName, "powerpoint") ||
	   strings.Contains(lowerName, "adobe") ||
	   strings.Contains(lowerName, "photoshop") ||
	   strings.Contains(lowerName, "acrobat") ||
	   strings.Contains(lowerName, "notion") ||
	   strings.Contains(lowerName, "obsidian") ||
	   strings.Contains(lowerName, "typora") {
		return "productivity"
	}

	// System utilities
	if strings.Contains(lowerName, "7-zip") ||
	   strings.Contains(lowerName, "winrar") ||
	   strings.Contains(lowerName, "ccleaner") ||
	   strings.Contains(lowerName, "process") ||
	   strings.Contains(lowerName, "task manager") ||
	   strings.Contains(lowerName, "cpu-z") ||
	   strings.Contains(lowerName, "gpu-z") ||
	   strings.Contains(lowerName, "hwmonitor") {
		return "utility"
	}

	// Gaming
	if strings.Contains(lowerName, "steam") ||
	   strings.Contains(lowerName, "epic") ||
	   strings.Contains(lowerName, "origin") ||
	   strings.Contains(lowerName, "uplay") ||
	   strings.Contains(lowerName, "gog") ||
	   strings.Contains(lowerName, "discord") { // Discord is also gaming
		return "gaming"
	}

	// Default category
	return "application"
}

// GetPackageDetails retrieves detailed information about a specific winget package
func (s *WingetScanner) GetPackageDetails(packageID string) (*client.UpdateReportItem, error) {
	if !s.IsAvailable() {
		return nil, fmt.Errorf("winget is not available on this system")
	}

	// Run winget show command to get detailed package information
	cmd := exec.Command("winget", "show", "--id", packageID, "--output", "json")
	output, err := cmd.Output()
	if err != nil {
		return nil, fmt.Errorf("failed to run winget show: %w", err)
	}

	// Parse JSON output (winget show outputs a single package object)
	var pkg WingetPackage
	if err := json.Unmarshal(output, &pkg); err != nil {
		return nil, fmt.Errorf("failed to parse winget show output: %w", err)
	}

	// Convert to UpdateReportItem format
	updateItem := s.parseWingetPackage(pkg)
	return updateItem, nil
}

// GetInstalledPackages retrieves all installed packages via winget
func (s *WingetScanner) GetInstalledPackages() ([]WingetPackage, error) {
	if !s.IsAvailable() {
		return nil, fmt.Errorf("winget is not available on this system")
	}

	// Run winget list command to get all installed packages
	cmd := exec.Command("winget", "list", "--output", "json")
	output, err := cmd.Output()
	if err != nil {
		return nil, fmt.Errorf("failed to run winget list: %w", err)
	}

	// Parse JSON output
	var packages []WingetPackage
	if err := json.Unmarshal(output, &packages); err != nil {
		return nil, fmt.Errorf("failed to parse winget JSON output: %w", err)
	}

	return packages, nil
}

// attemptWingetRecovery tries to fix common winget issues automatically
func (s *WingetScanner) attemptWingetRecovery() ([]client.UpdateReportItem, error) {
	log.Printf("Starting winget recovery process...\n")

	// Recovery Method 1: Reset winget sources (common fix)
	log.Printf("Attempting to reset winget sources...\n")
	if err := s.resetWingetSources(); err == nil {
		if updates, scanErr := s.scanWithJSON(); scanErr == nil {
			log.Printf("Recovery successful after source reset\n")
			return updates, nil
		}
	}

	// Recovery Method 2: Update winget itself (silent)
	log.Printf("Attempting to update winget itself...\n")
	if err := s.updateWingetSilent(); err == nil {
		// Wait a moment for winget to stabilize
		time.Sleep(2 * time.Second)
		if updates, scanErr := s.scanWithJSON(); scanErr == nil {
			log.Printf("Recovery successful after winget update\n")
			return updates, nil
		}
	}

	// Recovery Method 3: Repair Windows App Installer (winget backend)
	log.Printf("Attempting to repair Windows App Installer...\n")
	if err := s.repairWindowsAppInstaller(); err == nil {
		// Wait longer for system repairs
		time.Sleep(5 * time.Second)
		if updates, scanErr := s.scanWithJSON(); scanErr == nil {
			log.Printf("Recovery successful after Windows App Installer repair\n")
			return updates, nil
		}
	}

	// Recovery Method 4: Force refresh with admin privileges
	log.Printf("Attempting admin refresh...\n")
	if updates, err := s.scanWithAdminPrivileges(); err == nil {
		log.Printf("Recovery successful with admin privileges\n")
		return updates, nil
	}

	// If all recovery attempts failed, return the original error
	return nil, fmt.Errorf("all winget recovery attempts failed")
}

// resetWingetSources resets winget package sources
func (s *WingetScanner) resetWingetSources() error {
	// Reset winget sources silently
	cmd := exec.Command("winget", "source", "reset", "--force")
	_, err := cmd.CombinedOutput()
	if err != nil {
		log.Printf("Failed to reset winget sources: %v\n", err)
		return err
	}

	// Add default sources back
	cmd = exec.Command("winget", "source", "add", "winget", "--accept-package-agreements", "--accept-source-agreements")
	_, err = cmd.CombinedOutput()
	if err != nil {
		log.Printf("Failed to add winget source: %v\n", err)
		return err
	}

	return nil
}

// updateWingetSilent updates winget itself silently
func (s *WingetScanner) updateWingetSilent() error {
	// Update winget silently with no interaction
	cmd := exec.Command("winget", "upgrade", "--id", "Microsoft.AppInstaller", "--silent", "--accept-package-agreements", "--accept-source-agreements")
	_, err := cmd.CombinedOutput()
	if err != nil {
		log.Printf("Failed to update winget: %v\n", err)
		return err
	}
	return nil
}

// repairWindowsAppInstaller attempts to repair the Windows App Installer
func (s *WingetScanner) repairWindowsAppInstaller() error {
	// Try to repair using PowerShell
	psCmd := `Get-AppxPackage -Name "Microsoft.DesktopAppInstaller" | Repair-AppxPackage -ForceUpdateFromAnyVersion`
	cmd := exec.Command("powershell", "-ExecutionPolicy", "Bypass", "-Command", psCmd)
	_, err := cmd.CombinedOutput()
	if err != nil {
		log.Printf("Failed to repair Windows App Installer: %v\n", err)
		return err
	}
	return nil
}

// scanWithAdminPrivileges attempts to scan with elevated privileges if available
func (s *WingetScanner) scanWithAdminPrivileges() ([]client.UpdateReportItem, error) {
	// Try running with elevated privileges using PowerShell
	psCmd := `Start-Process winget -ArgumentList "list","--outdated","--accept-source-agreements" -Verb RunAs -Wait`
	cmd := exec.Command("powershell", "-ExecutionPolicy", "Bypass", "-Command", psCmd)

	// This will likely fail without actual admin privileges, but we try anyway
	_, err := cmd.CombinedOutput()
	if err != nil {
		// Fallback to regular scan with different flags
		return s.scanWithDifferentFlags()
	}

	// If admin scan succeeded, try to get the results
	return s.scanWithBasicOutput()
}

// scanWithDifferentFlags tries alternative winget flags
func (s *WingetScanner) scanWithDifferentFlags() ([]client.UpdateReportItem, error) {
	// Try different combination of flags
	flagVariations := [][]string{
		{"list", "--outdated", "--accept-source-agreements"},
		{"list", "--outdated", "--include-unknown"},
		{"list", "--outdated"},
	}

	for _, flags := range flagVariations {
		cmd := exec.Command("winget", flags...)
		output, err := cmd.CombinedOutput()
		if err == nil {
			// Try to parse the output
			if updates, parseErr := s.parseWingetTextOutput(string(output)); parseErr == nil {
				return updates, nil
			}
		}
	}

	return nil, fmt.Errorf("all flag variations failed")
}