package network

import (
	"net"
	"os"
	"testing"

	"github.com/miekg/dns"
	"gotest.tools/v3/assert"
)

const DNSRespAddr = "10.11.12.13"

// WriteTempResolvConf writes a resolv.conf that only contains a single
// nameserver line, with address addr.
// It returns the name of the temp file. The temp file will be deleted
// automatically by a t.Cleanup().
func WriteTempResolvConf(t *testing.T, addr string) string {
	t.Helper()
	// Not using t.TempDir() here because in rootless mode, while the temporary
	// directory gets mode 0777, it's a subdir of an 0700 directory owned by root.
	// So, it's not accessible by the daemon.
	f, err := os.CreateTemp("", "resolv.conf")
	assert.NilError(t, err)
	t.Cleanup(func() { os.Remove(f.Name()) })
	err = f.Chmod(0644)
	assert.NilError(t, err)
	f.Write([]byte("nameserver " + addr + "\n"))
	return f.Name()
}

// StartDaftDNS starts and returns a really, really daft DNS server that only
// responds to type-A requests, and always with address dnsRespAddr.
// The DNS server will be stopped automatically by a t.Cleanup().
func StartDaftDNS(t *testing.T, addr string) {
	serveDNS := func(w dns.ResponseWriter, query *dns.Msg) {
		if query.Question[0].Qtype == dns.TypeA {
			resp := &dns.Msg{}
			resp.SetReply(query)
			answer := &dns.A{
				Hdr: dns.RR_Header{
					Name:   query.Question[0].Name,
					Rrtype: dns.TypeA,
					Class:  dns.ClassINET,
					Ttl:    600,
				},
			}
			answer.A = net.ParseIP(DNSRespAddr)
			resp.Answer = append(resp.Answer, answer)
			_ = w.WriteMsg(resp)
		}
	}

	conn, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   net.ParseIP(addr),
		Port: 53,
	})
	assert.NilError(t, err)

	server := &dns.Server{Handler: dns.HandlerFunc(serveDNS), PacketConn: conn}
	go func() {
		_ = server.ActivateAndServe()
	}()

	t.Cleanup(func() { server.Shutdown() })
}
