// Copyright (c) 2024 RethinkDNS and its authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package dns53

import (
	"errors"
	"net/netip"

	x "github.com/celzero/firestack/intra/backend"
	"github.com/celzero/firestack/intra/dnsx"
	"github.com/celzero/firestack/intra/log"
	"github.com/celzero/firestack/intra/xdns"
	"github.com/miekg/dns"
)

var errStubTransport = errors.New("dns: stub transport")

// TODO: Keep a context here so that queries can be canceled.
type errorer struct {
	id     string
	ipport string
}

var _ dnsx.Transport = (*errorer)(nil)

// NewErrorerTransport returns a DNS transport that always errors out on queries.
func NewErrorerTransport(id string) *errorer {
	t := &errorer{
		id:     id, // typically, dnsx.Fixed
		ipport: "127.3.3.3:33",
	}
	log.I("errorer(%s) setup: %s", t.ID(), t.GetAddr())
	return t
}

func (t *errorer) Query(_ string, q *dns.Msg, smm *x.DNSSummary) (*dns.Msg, error) {
	smm.Latency = 0
	smm.RData = xdns.GetInterestingRData(nil)
	smm.RCode = xdns.Rcode(nil)
	smm.RTtl = xdns.RTtl(nil)
	smm.Server = t.GetAddr().V()
	smm.Status = t.Status()
	smm.Msg = errStubTransport.Error()

	return nil, errStubTransport
}

func (t *errorer) ID() *x.Gostr {
	return x.StrOf(t.id)
}

func (*errorer) Type() *x.Gostr {
	return x.StrOf(dnsx.DNS53)
}

func (*errorer) P50() int64 {
	return 0
}

func (t *errorer) GetAddr() *x.Gostr {
	return x.StrOf(t.ipport)
}

func (t *errorer) GetRelay() x.Proxy {
	return nil
}

func (t *errorer) IPPorts() []netip.AddrPort {
	return dnsx.NoIPPort
}

func (*errorer) Status() int {
	return x.ClientError
}

func (*errorer) Stop() error {
	return nil
}
