package main

import (
	"context"
	"fmt"
	"runtime"
	"strings"
	"time"
)

func collectHardware(totalRAM uint64, disks []DiskStatus) HardwareInfo {
	if runtime.GOOS != "darwin" {
		return HardwareInfo{
			Model:       "Unknown",
			CPUModel:    runtime.GOARCH,
			TotalRAM:    humanBytes(totalRAM),
			DiskSize:    "Unknown",
			OSVersion:   runtime.GOOS,
			RefreshRate: "",
		}
	}

	// Model and CPU from system_profiler.
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	var model, cpuModel, osVersion, refreshRate string

	out, err := runCmd(ctx, "system_profiler", "SPHardwareDataType")
	if err == nil {
		for line := range strings.Lines(out) {
			lower := strings.ToLower(strings.TrimSpace(line))
			// Prefer "Model Name" over "Model Identifier".
			if strings.Contains(lower, "model name:") {
				parts := strings.Split(line, ":")
				if len(parts) == 2 {
					model = strings.TrimSpace(parts[1])
				}
			}
			if strings.Contains(lower, "chip:") {
				parts := strings.Split(line, ":")
				if len(parts) == 2 {
					cpuModel = strings.TrimSpace(parts[1])
				}
			}
			if strings.Contains(lower, "processor name:") && cpuModel == "" {
				parts := strings.Split(line, ":")
				if len(parts) == 2 {
					cpuModel = strings.TrimSpace(parts[1])
				}
			}
		}
	}

	ctx2, cancel2 := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel2()
	out2, err := runCmd(ctx2, "sw_vers", "-productVersion")
	if err == nil {
		osVersion = "macOS " + strings.TrimSpace(out2)
	}

	// Get refresh rate from display info (use mini detail to keep it fast).
	ctx3, cancel3 := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel3()
	out3, err := runCmd(ctx3, "system_profiler", "-detailLevel", "mini", "SPDisplaysDataType")
	if err == nil {
		refreshRate = parseRefreshRate(out3)
	}

	diskSize := "Unknown"
	if len(disks) > 0 {
		diskSize = humanBytes(disks[0].Total)
	}

	return HardwareInfo{
		Model:       model,
		CPUModel:    cpuModel,
		TotalRAM:    humanBytes(totalRAM),
		DiskSize:    diskSize,
		OSVersion:   osVersion,
		RefreshRate: refreshRate,
	}
}

// parseRefreshRate extracts the highest refresh rate from system_profiler display output.
func parseRefreshRate(output string) string {
	maxHz := 0

	for line := range strings.Lines(output) {
		lower := strings.ToLower(line)
		// Look for patterns like "@ 60Hz", "@ 60.00Hz", or "Refresh Rate: 120 Hz".
		if strings.Contains(lower, "hz") {
			fields := strings.Fields(lower)
			for i, field := range fields {
				if field == "hz" && i > 0 {
					if hz := parseInt(fields[i-1]); hz > maxHz && hz < 500 {
						maxHz = hz
					}
					continue
				}
				if numStr, ok := strings.CutSuffix(field, "hz"); ok {
					if numStr == "" && i > 0 {
						numStr = fields[i-1]
					}
					if hz := parseInt(numStr); hz > maxHz && hz < 500 {
						maxHz = hz
					}
				}
			}
		}
	}

	if maxHz > 0 {
		return fmt.Sprintf("%dHz", maxHz)
	}
	return ""
}

// parseInt safely parses an integer from a string.
func parseInt(s string) int {
	// Trim away non-numeric padding, keep digits and '.' for decimals.
	cleaned := strings.TrimSpace(s)
	cleaned = strings.TrimLeftFunc(cleaned, func(r rune) bool {
		return (r < '0' || r > '9') && r != '.'
	})
	cleaned = strings.TrimRightFunc(cleaned, func(r rune) bool {
		return (r < '0' || r > '9') && r != '.'
	})
	if cleaned == "" {
		return 0
	}
	var num int
	if _, err := fmt.Sscanf(cleaned, "%d", &num); err != nil {
		return 0
	}
	return num
}
