package ctrld

import (
	"net"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

// AbsHomeDir returns the absolute path to given filename using home directory as root dir.
func AbsHomeDir(filename string) string {
	dir, err := UserHomeDir()
	if err != nil {
		return filename
	}
	return filepath.Join(dir, filename)
}

func dirWritable(dir string) (bool, error) {
	f, err := os.CreateTemp(dir, "")
	if err != nil {
		return false, err
	}
	defer os.Remove(f.Name())
	return true, f.Close()
}

// UserHomeDir returns the home directory for user who is running ctrld.
func UserHomeDir() (string, error) {
	// viper will expand for us.
	if runtime.GOOS == "windows" {
		// If we're on windows, use the install path for this.
		exePath, err := os.Executable()
		if err != nil {
			return "", err
		}

		return filepath.Dir(exePath), nil
	}
	dir := "/etc/controld"
	if err := os.MkdirAll(dir, 0750); err != nil {
		return os.UserHomeDir() // fallback to user home directory
	}
	if ok, _ := dirWritable(dir); !ok {
		return os.UserHomeDir()
	}
	return dir, nil
}

// SavedStaticDnsSettingsFilePath returns the file path where the static DNS settings
// for the provided interface are saved.
//
// The caller must ensure iface is non-nil.
func SavedStaticDnsSettingsFilePath(iface *net.Interface) string {
	// The file is stored in the user home directory under a hidden file.
	return AbsHomeDir(".dns_" + iface.Name)
}

// SavedStaticNameserversAndPath returns the stored static nameservers for the given interface,
// and the absolute path to file that stored the settings.
//
// The caller must ensure iface is non-nil.
func SavedStaticNameserversAndPath(iface *net.Interface) ([]string, string) {
	file := SavedStaticDnsSettingsFilePath(iface)
	data, err := os.ReadFile(file)
	if err != nil || len(data) == 0 {
		return nil, file
	}
	saveValues := strings.Split(string(data), ",")
	var ns []string
	for _, v := range saveValues {
		// Skip any IP that is loopback
		if ip := net.ParseIP(v); ip != nil && ip.IsLoopback() {
			continue
		}
		ns = append(ns, v)
	}
	return ns, file
}

// SavedStaticNameservers is like SavedStaticNameserversAndPath, but only returns the static nameservers.
func SavedStaticNameservers(iface *net.Interface) []string {
	nss, _ := SavedStaticNameserversAndPath(iface)
	return nss
}
