package cli

// Description: Structs to execute external commands.

import (
	"fmt"
	"io"
	"log"
	"os/exec"
	"strings"

	"gitlab.com/M0M097/pkg/internal/must"
)

// Executor holds the standard output and error writers for command execution.
// It can be used to run external commands and log their invocation.
type Executor struct {
	// Stdout receives the command's standard output.
	Stdout io.Writer

	// Stderr receives the command's standard error.
	Stderr io.Writer

	Log bool // If true, log the command being run
}

// Pager returns a function that displays files using a pager command like "less".
//
// The pager command is determined by the "PAGER" environment variable, or the
// provided fallbackPager if "PAGER" is not set.
func Pager(ex Executor, fallbackPager string) func(files ...string) error {
	cmd := must.SetEnvIfNotSet("PAGER", fallbackPager) + " "
	return func(files ...string) error { return ex.Run(cmd + strings.Join(files, " ")) }
}

// Run executes the given command string.
//
// The executor's Stdout and Stderr fields are used for the command's output. If
// ex.Log is true, it logs the command before execution.
func (ex Executor) Run(fullCmd string) error {
	if ex.Log {
		log.Println(fullCmd)
	}
	split := strings.Split(fullCmd, " ")
	cmd := exec.Command(split[0], split[1:]...)
	cmd.Stdout, cmd.Stderr = ex.Stdout, ex.Stderr
	err := cmd.Run()
	if err == nil {
		return nil
	}
	return fmt.Errorf("%s failed: %w", fullCmd, err)
}
