package main

import (
	"context"
	"fmt"
	"os/exec"
	"runtime"
	"strconv"
	"strings"
	"time"
)

const procMaxEntries = 200

// runProcList enumera procesos. En linux usa /proc parsing via `ps -eo`.
func runProcList(cap *Capability, args map[string]any) (any, int, error) {
	_ = cap
	_ = args
	if runtime.GOOS == "windows" {
		return runProcListWindows()
	}
	return runProcListUnix()
}

func runProcListUnix() (any, int, error) {
	if _, err := exec.LookPath("ps"); err != nil {
		return nil, -1, fmt.Errorf("ps binary not found")
	}
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	// ps -eo pid,ppid,user,comm,rss,pcpu --no-headers
	c := exec.CommandContext(ctx, "ps", "-eo", "pid,ppid,user,comm,rss,pcpu", "--no-headers")
	out, err := c.Output()
	if err != nil {
		return nil, -1, fmt.Errorf("ps: %w", err)
	}
	lines := strings.Split(string(out), "\n")
	processes := []map[string]any{}
	for _, line := range lines {
		fields := strings.Fields(line)
		if len(fields) < 6 {
			continue
		}
		pid, _ := strconv.Atoi(fields[0])
		ppid, _ := strconv.Atoi(fields[1])
		user := fields[2]
		name := fields[3]
		rss, _ := strconv.ParseInt(fields[4], 10, 64)
		cpu, _ := strconv.ParseFloat(fields[5], 64)
		processes = append(processes, map[string]any{
			"pid":     pid,
			"ppid":    ppid,
			"user":    user,
			"name":    name,
			"rss_kb":  rss,
			"cpu_pct": cpu,
		})
		if len(processes) >= procMaxEntries {
			break
		}
	}
	return map[string]any{
		"processes": processes,
		"count":     len(processes),
		"truncated": len(processes) >= procMaxEntries,
	}, 0, nil
}

func runProcListWindows() (any, int, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	c := exec.CommandContext(ctx, "tasklist", "/FO", "CSV", "/NH")
	out, err := c.Output()
	if err != nil {
		return nil, -1, fmt.Errorf("tasklist: %w", err)
	}
	lines := strings.Split(string(out), "\n")
	processes := []map[string]any{}
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if line == "" {
			continue
		}
		parts := strings.Split(line, ",")
		if len(parts) < 5 {
			continue
		}
		name := strings.Trim(parts[0], `"`)
		pid, _ := strconv.Atoi(strings.Trim(parts[1], `"`))
		processes = append(processes, map[string]any{
			"pid":  pid,
			"name": name,
		})
		if len(processes) >= procMaxEntries {
			break
		}
	}
	return map[string]any{
		"processes": processes,
		"count":     len(processes),
		"truncated": len(processes) >= procMaxEntries,
	}, 0, nil
}
