package edgecmd

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"

	"github.com/spf13/cobra"
)

// ResolveConfigPath returns the edge config path to load. Candidate order:
//  1. explicit --config flag
//  2. ./edge.yaml in the current working directory
//  3. <binary-dir>/edge.yaml beside the executable
//  4. configs/edge.yaml repo-dev fallback (only if it exists)
//
// setup uses its own /etc/iop/edge.yaml default and does not call this helper.
func ResolveConfigPath(cmd *cobra.Command) (string, error) {
	if isConfigExplicit(cmd) {
		return configFlagValue(cmd), nil
	}
	if _, err := os.Stat("edge.yaml"); err == nil {
		return "edge.yaml", nil
	}
	if exe, err := os.Executable(); err == nil {
		candidate := filepath.Join(filepath.Dir(exe), "edge.yaml")
		if _, err := os.Stat(candidate); err == nil {
			return candidate, nil
		}
	}
	if _, err := os.Stat("configs/edge.yaml"); err == nil {
		return "configs/edge.yaml", nil
	}
	return "", errors.New("no edge.yaml found: pass --config or run beside a bundle edge.yaml")
}

func isConfigExplicit(cmd *cobra.Command) bool {
	flag := cmd.Root().PersistentFlags().Lookup("config")
	return flag != nil && flag.Changed
}

func configFlagValue(cmd *cobra.Command) string {
	flag := cmd.Root().PersistentFlags().Lookup("config")
	if flag == nil {
		return ""
	}
	return flag.Value.String()
}

// ResolveEdgeLogPath returns the effective edge log path. If explicit is set
// it wins. Otherwise it falls back to <binary-dir>/logs/edge.log.
func ResolveEdgeLogPath(explicit string) (string, error) {
	if explicit != "" {
		return explicit, nil
	}
	exe, err := os.Executable()
	if err != nil {
		return "", fmt.Errorf("resolve binary: %w", err)
	}
	return filepath.Join(filepath.Dir(exe), "logs", "edge.log"), nil
}

func ResolveBootstrapArtifactDir(dir string) string {
	if dir == "" {
		dir = "artifacts"
	}
	if filepath.IsAbs(dir) {
		return dir
	}
	return filepath.Join(binaryDir(), dir)
}

// binaryDir returns the directory of the running executable. Falls back to the
// current working directory if os.Executable fails.
func binaryDir() string {
	if exe, err := os.Executable(); err == nil {
		return filepath.Dir(exe)
	}
	if wd, err := os.Getwd(); err == nil {
		return wd
	}
	return "."
}
