package openwrt

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"github.com/nextdns/nextdns/config"
	"github.com/nextdns/nextdns/router/internal"
)

type Router struct {
	DNSMasqPath     string
	ListenPort      string
	ClientReporting bool

	savedForwarders string
}

func New() (*Router, bool) {
	if r, err := internal.ReadOsRelease(); err != nil || r["ID"] != "openwrt" {
		return nil, false
	}
	return &Router{
		DNSMasqPath: "/tmp/dnsmasq.d/nextdns.conf",
		ListenPort:  "5342",
	}, true
}

func (r *Router) Configure(c *config.Config) error {
	c.Listen = "127.0.0.1:" + r.ListenPort
	r.ClientReporting = c.ReportClientInfo
	return nil
}

func (r *Router) Setup() (err error) {
	r.savedForwarders, err = uci("get", "dhcp.@dnsmasq[0].server")
	if err != nil {
		if !errors.Is(err, uciErrEntryNotFound) {
			return err
		}
	} else {
		if _, err = uci("delete", "dhcp.@dnsmasq[0].server"); err != nil {
			return err
		}
		if _, err = uci("commit"); err != nil {
			return err
		}
	}

	if err := internal.WriteTemplate(r.DNSMasqPath, tmpl, r, 0644); err != nil {
		return err
	}

	// Restart dnsmasq service to apply changes.
	if err := exec.Command("/etc/init.d/dnsmasq", "restart").Run(); err != nil {
		return fmt.Errorf("dnsmasq restart: %v", err)
	}

	return nil
}

func (r *Router) Restore() error {
	// Restore forwarders
	if r.savedForwarders != "" {
		for _, f := range strings.Split(r.savedForwarders, " ") {
			if _, err := uci("add_list", "dhcp.@dnsmasq[0].server="+f); err != nil {
				return err
			}
		}
		if _, err := uci("commit"); err != nil {
			return err
		}
	}

	// Remove the custom dnsmasq config
	_ = os.Remove(r.DNSMasqPath)

	// Restart dnsmasq service to apply changes.
	if err := exec.Command("/etc/init.d/dnsmasq", "restart").Run(); err != nil {
		return fmt.Errorf("dnsmasq restart: %v", err)
	}
	return nil
}

var tmpl = `# Configuration generated by NextDNS
no-resolv
server=127.0.0.1#{{.ListenPort}}
{{- if .ClientReporting}}
add-mac
add-subnet=32,128
{{- end}}
`
