package kas

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/prototool"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/pkg/kascfg"
	"google.golang.org/protobuf/proto"
)

// LoadConfigurationFile loads the configuration file.
// This function does not run any validation logic.
func LoadConfigurationFile(ctx context.Context, configFile string) (*kascfg.ConfigurationFile, error) {
	configYAML, err := os.ReadFile(configFile) //nolint: gosec
	if err != nil {
		return nil, fmt.Errorf("configuration file: %w", err)
	}
	cfg := &kascfg.ConfigurationFile{}
	err = prototool.ParseYAMLToProto(configYAML, cfg)
	if err != nil {
		return nil, err
	}
	gen := cfg.GetConfig().GetCommand()
	if gen != "" {
		genCfg, genErr := runConfigCommand(ctx, cfg.Config)
		if genErr != nil {
			return nil, fmt.Errorf("config command: %w", genErr)
		}
		proto.Merge(cfg, genCfg)
	}
	return cfg, nil
}

func runConfigCommand(ctx context.Context, cf *kascfg.ConfigCF) (*kascfg.ConfigurationFile, error) {
	cmd, args := splitCommand(cf.Command)
	genCmd := exec.CommandContext(ctx, cmd, args...) //nolint: gosec
	genCmd.Stderr = os.Stderr                        // pipe cmd's stderr into our own stderr
	genConfigYAML, err := genCmd.Output()
	if err != nil {
		return nil, err
	}
	cfg := &kascfg.ConfigurationFile{}
	err = prototool.ParseYAMLToProto(genConfigYAML, cfg)
	if err != nil {
		return nil, err
	}
	return cfg, nil
}

func splitCommand(cmd string) (string, []string) {
	cmdAndArgs := strings.Split(cmd, " ")
	return cmdAndArgs[0], cmdAndArgs[1:]
}
