/*
** 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 forker

import (
	"errors"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

type ProcessData struct {
	ExecPath   string
	ExecParams []string
	StdoutPath string // Optional, Default os.Stdout
	StderrPath string // Optional, Default os.Stderr
	StdinBytes []byte
	StdinPipe  *io.WriteCloser

	RetPath    string // Optional, Exit/Return code file path
	ExtraFiles []*os.File

	// Platform-specific fields (optional)
	Username string
	Password string
	Domain   string // Windows-only

	// Process info
	Detached        bool
	Env             []string
	DirectExec      bool
	UsePipeStdin    bool
	UseConsoleStdin bool
}

type Forker struct {
	data ProcessData
}

var (
	ErrExecCheck = errors.New("exec check failed")
)

func New(data ProcessData) Forker {
	processor := Forker{
		data: data,
	}

	return processor
}

// ExecutableExists checks whether the given name or path refers to an existing file or command in PATH
func validateExecutable(nameOrPath string) error {
	if strings.Contains(nameOrPath, "/") || strings.Contains(nameOrPath, "\\") {
		absPath, err := filepath.Abs(nameOrPath)
		if err != nil {
			return err
		}
		_, err = os.Stat(absPath)
		return err
	}

	_, err := exec.LookPath(nameOrPath)
	return err
}
