package lima

import (
	"bytes"
	"fmt"

	"github.com/abiosoft/colima/config"
	"github.com/abiosoft/colima/environment/vm/lima/limautil"
)

const (
	localhostAddr = "127.0.0.1"
	gatewayAddr   = "192.168.5.2"
)

var dnsHosts = map[string]string{
	"host.docker.internal": gatewayAddr,
	"host.lima.internal":   gatewayAddr,
}

func hasDnsmasq(l *limaVM) bool {
	// check if dnsmasq is installed
	return l.RunQuiet("sh", "-c", `apt list | grep 'dnsmasq\/' | grep '\[installed'`) == nil
}

func (l *limaVM) setupDNS(conf config.Config) error {
	if !hasDnsmasq(l) {
		// older image still using systemd-resolved
		// ignore
		return nil
	}

	internalIP := limautil.InternalIPAddress(config.CurrentProfile().ID)

	// extra dns entries
	dnsHosts["colima.internal"] = internalIP
	if (conf.Hostname) != "" {
		dnsHosts[conf.Hostname] = localhostAddr
	}

	var buf bytes.Buffer

	// generate dns hosts
	fmt.Fprintln(&buf, "# Generated by Colima")
	fmt.Fprintln(&buf, "# Do not edit this file manually")
	fmt.Fprintln(&buf)
	for k, v := range dnsHosts {
		fmt.Fprintf(&buf, "address=/%s/%s", k, v)
		fmt.Fprintln(&buf)
	}
	fmt.Fprintln(&buf) // for cleaner output

	// generate dns servers
	dnsServers := []string{gatewayAddr}
	if len(conf.Network.DNSResolvers) > 0 {
		dnsServers = nil
		for _, dns := range conf.Network.DNSResolvers {
			dnsServers = append(dnsServers, dns.String())
		}
	}
	for _, dns := range dnsServers {
		fmt.Fprintf(&buf, "server=%s", dns)
		fmt.Fprintln(&buf)
	}
	fmt.Fprintln(&buf) // for cleaner output

	// set dnsmasq listening interface and address
	fmt.Fprintln(&buf, "interface=eth0")
	fmt.Fprintln(&buf, "listen-address="+internalIP)
	fmt.Fprintln(&buf, "bind-interfaces")

	// ensure dnsmasq config directory exists
	if err := l.RunQuiet("sudo", "mkdir", "-p", "/etc/dnsmasq.d"); err != nil {
		return fmt.Errorf("failed to create dnsmasq config directory: %w", err)
	}

	// write config to dnsmasq directory
	if err := l.Write("/etc/dnsmasq.d/01-colima.conf", buf.Bytes()); err != nil {
		return fmt.Errorf("failed to write dnsmasq config: %w", err)
	}

	// remove existing resolv.conf file
	if err := l.RunQuiet("sudo", "rm", "-f", "/etc/resolv.conf"); err != nil {
		return fmt.Errorf("failed to remove existing resolv.conf: %w", err)
	}

	// replace resolv.conf with a custom one
	resolvConf := fmt.Sprintf("# Generated by Colima\n\nnameserver %s\n", internalIP)
	if err := l.Write("/etc/resolv.conf", []byte(resolvConf)); err != nil {
		return fmt.Errorf("failed to write resolv.conf: %w", err)
	}

	// restart dnsmasq service to apply changes
	if err := l.RunQuiet("sudo", "systemctl", "restart", "dnsmasq"); err != nil {
		return fmt.Errorf("failed to restart dnsmasq service: %w", err)
	}

	return nil
}
