//go:build windows
// +build windows

/*
** Job Arranger for ZABBIX
** Copyright (C) 2025 Daiwa Institute of Research Ltd. All Rights Reserved.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

package agentutils

import (
	"fmt"
	"os"

	"golang.org/x/sys/windows"
)

// KillProcessIfExists attempts to kill the process with the given PID if it exists.
// It works on both Linux and Windows.
func KillProcessIfExists(pid int) error {
	if pid <= 0 {
		return fmt.Errorf("invalid PID: %d", pid)
	}

	process, err := os.FindProcess(pid)
	if err != nil {
		return fmt.Errorf("failed to find process: %v", err)
	}

	// Platform-specific behavior
	return killWindows(process)
}

// killWindows sends the kill signal on Windows
func killWindows(p *os.Process) error {
	if err := p.Kill(); err != nil {
		return fmt.Errorf("failed to kill process %d: %v", p.Pid, err)
	}
	return nil
}

// ProcessExists checks whether a process with the given PID exists on Windows.
func ProcessExists(pid int) bool {
	if pid <= 0 {
		return false
	}

	// PROCESS_QUERY_LIMITED_INFORMATION is enough to validate the PID
	const PROCESS_QUERY_LIMITED_INFORMATION = 0x1000

	handle, err := windows.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
	if err != nil {
		// ERROR_INVALID_PARAMETER => no such PID
		if err == windows.ERROR_INVALID_PARAMETER {
			return false
		}
		// ERROR_ACCESS_DENIED => the process exists but we can't open it
		if err == windows.ERROR_ACCESS_DENIED {
			return true
		}
		// other errors: treat as "does not exist"
		return false
	}

	// Successfully opened → process definitely exists
	windows.CloseHandle(handle)
	return true
}
