package cluster

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

	"github.com/rs/zerolog/log"
)

type cmdOption func(*exec.Cmd)

func withArgs(args ...string) cmdOption {
	return func(cmd *exec.Cmd) {
		cmd.Args = append([]string{"kubectl"}, args...)
	}
}

func withEnv(env ...string) cmdOption {
	return func(cmd *exec.Cmd) {
		cmd.Env = append(os.Environ(), env...)
	}
}

func withStdin(rdr io.Reader) cmdOption {
	return func(cmd *exec.Cmd) {
		cmd.Stdin = rdr
	}
}

func withStdout(w io.Writer) cmdOption {
	return func(cmd *exec.Cmd) {
		cmd.Stdout = w
	}
}

func withWorkingDir(wd string) cmdOption {
	return func(cmd *exec.Cmd) {
		cmd.Dir = wd
	}
}

func run(ctx context.Context, name string, options ...cmdOption) error {
	cmd := commandContext(ctx, name)
	for _, o := range options {
		o(cmd)
	}
	if cmd.Stderr == nil {
		stderr, err := cmd.StderrPipe()
		if err != nil {
			return fmt.Errorf("failed to create stderr pipe for %s: %w", name, err)
		}
		go cmdLogger(stderr)
		defer stderr.Close()
	}
	if cmd.Stdout == nil {
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			return fmt.Errorf("failed to create stdout pipe for %s: %w", name, err)
		}
		go cmdLogger(stdout)
		defer stdout.Close()
	}

	log.Debug().Strs("args", cmd.Args).Msgf("running %s", name)
	return cmd.Run()
}

func cmdLogger(rdr io.Reader) {
	s := bufio.NewScanner(rdr)
	for s.Scan() {
		log.Debug().Msg(s.Text())
	}
}