//go:build ignore

// err_generate generates zerr.go which houses the handler.Err method.

package main

import (
	"bytes"
	"fmt"
	"html/template"
	"log"
	"path/filepath"
	"strings"

	"codeberg.org/miekg/dns/cmd/atomdns/internal/generate"
)

const hdr = `
// Code generated by "go run err_generate.go"; DO NOT EDIT.

package %s

import (
	"errors"
	"fmt"
	"log/slog"

	"codeberg.org/miekg/dns/cmd/atomdns/internal/dnslog"
)

`

var funcmap = template.FuncMap{
	"tolower": strings.ToLower,
	"r":       func(s string) string { return strings.ToLower(s[0:1]) },
}

var ErrFunc = template.Must(template.New("errFunc").Funcs(funcmap).Parse(`
func ({{r .}} *{{.}}) Err(err error) error { return fmt.Errorf("%s: %w", {{r .}}.Key(), err) }

func ({{r .}} *{{.}}) Errf(err string) error { return fmt.Errorf("%s: %w", {{r .}}.Key(), errors.New(err)) }

func Err(err error) slog.Attr { return dnslog.Error(err) }
`))

var KeyFunc = template.Must(template.New("keyFunc").Funcs(funcmap).Parse(`
func ({{r .}} *{{.}}) Key() string { return "{{tolower .}}" }
`))

var LogVar = template.Must(template.New("logVar").Funcs(funcmap).Parse(`
{{if eq . "Log"}}
	var _log = func() *slog.Logger { return slog.Default().With("handler", "{{tolower .}}") }
{{else}}
	var log = func() *slog.Logger { return slog.Default().With("handler", "{{tolower .}}")}
{{end}}
`))

func main() {
	handlers, err := generate.Handlers()
	if err != nil {
		log.Fatal(err)
	}
	source := &bytes.Buffer{}

	for _, handler := range handlers {
		fmt.Fprintf(source, hdr, strings.ToLower(handler))
		out := filepath.Join(strings.ToLower(handler), "zerr.go")
		if err := ErrFunc.Execute(source, handler); err != nil {
			log.Fatalf("Failed to generate %s: %v", out, err)
		}
		if err := KeyFunc.Execute(source, handler); err != nil {
			log.Fatalf("Failed to generate %s: %v", out, err)
		}
		if err := LogVar.Execute(source, handler); err != nil {
			log.Fatalf("Failed to generate %s: %v", out, err)
		}
		generate.Write(source, out)
		source.Reset()
	}
}
