package registry

import (
	"errors"
	"fmt"
	"net"
	"os"
	"strings"
)

func isFQDN(host string) bool {
	return strings.Count(host, ".") > 1
}

func chooseIP(ips []net.IP) net.IP {
	for _, ip := range ips {
		if !ip.IsLoopback() && !ip.IsInterfaceLocalMulticast() && !ip.IsLinkLocalUnicast() && !ip.IsLinkLocalMulticast() {
			return ip
		}
	}
	return nil
}

// getViaLookup tries to lookup whether short hostname may be resolved into IP and back into a longer one
func getViaLookup(host string) (string, error) {
	addrs, err := net.LookupIP(host)
	if err != nil {
		return "", err
	}
	if len(addrs) == 0 {
		return "", errors.New("address lookup failed")
	}
	for _, addr := range addrs {
		hosts, err := net.LookupAddr(addr.String())
		if err != nil {
			continue
		}
		for _, h := range hosts {
			h = strings.TrimSuffix(h, ".")
			if isFQDN(h) {
				return h, nil
			}
		}
	}

	if ip := chooseIP(addrs); ip != nil {
		return ip.String(), nil
	}
	return "", errors.New("lookup failed")
}

// getHostOrIP tries to fetch a publicly accessible IP address for the current host/container
func getHostOrIP() (string, error) {
	host, err := os.Hostname()
	if err != nil {
		return "", fmt.Errorf("hostname: %w", err)
	}
	if isFQDN(host) {
		return host, nil
	}

	if h, err := getViaLookup(host); err == nil {
		return h, nil
	}

	return host, nil
}