package utils

import (
	"bufio"
	"context"
	"os/exec"

	"github.com/go-pay/errgroup"
	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"
)

// ExecCommand executes a command and streams its output in real-time
func ExecCommand(name string, args ...string) error {
	log.Infof("Executing command: %s %v", name, args)
	cmd := exec.Command(name, args...)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return errors.Wrap(err, "stdout pipe error")
	}

	stderr, err := cmd.StderrPipe()
	if err != nil {
		return errors.Wrap(err, "stderr pipe error")
	}

	if err := cmd.Start(); err != nil {
		return errors.Wrap(err, "command start error")
	}

	var eg errgroup.Group
	eg.Go(func(ctx context.Context) error {
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			log.Info(scanner.Text())
		}
		return nil
	})

	eg.Go(func(ctx context.Context) error {
		scanner := bufio.NewScanner(stderr)
		for scanner.Scan() {
			log.Error(scanner.Text())
		}
		return nil
	})

	if err := cmd.Wait(); err != nil {
		return errors.Wrap(err, "command wait error")
	}

	if err := eg.Wait(); err != nil {
		return errors.Wrap(err, "command wait error")
	}

	return nil
}

// ExecCommandOutput executes a command and returns its output
func ExecCommandOutput(name string, args ...string) ([]byte, error) {
	log.Infof("Executing command: %s %v", name, args)
	cmd := exec.Command(name, args...)
	output, err := cmd.Output()
	if err != nil {
		return nil, errors.Wrapf(err, "failed to execute command: %s", name)
	}
	return output, nil
}
