package admin

import (
	"embed"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"time"
)

//go:embed templates/*.html static/*
var assetsFS embed.FS

// pageData is the common envelope passed to every rendered page.
type pageData struct {
	Username string
	CSRF     string
	Active   string // nav key for highlight
	Flash    string
	Data     any
}

// renderer holds the parsed template set.
type renderer struct {
	pages map[string]*template.Template
}

var tmplFuncs = template.FuncMap{
	"fmtTime": func(t time.Time) string {
		if t.IsZero() {
			return "-"
		}
		return t.UTC().Format("2006-01-02 15:04:05Z")
	},
}

// newRenderer parses base.html with each page template into its own set.
func newRenderer() (*renderer, error) {
	pages := map[string][]string{
		"login":     {"templates/login.html"},
		"dashboard": {"templates/base.html", "templates/dashboard.html"},
		"codes":     {"templates/base.html", "templates/codes.html"},
		"nodes":     {"templates/base.html", "templates/nodes.html"},
		"audit":     {"templates/base.html", "templates/audit.html"},
	}
	r := &renderer{pages: make(map[string]*template.Template, len(pages))}
	for name, files := range pages {
		t, err := template.New("").Funcs(tmplFuncs).ParseFS(assetsFS, files...)
		if err != nil {
			return nil, fmt.Errorf("admin.newRenderer parse %s: %w", name, err)
		}
		r.pages[name] = t
	}
	return r, nil
}

// render writes the named page. The login page renders itself; all others
// render through the "base" layout.
func (r *renderer) render(w http.ResponseWriter, name string, data pageData) {
	t, ok := r.pages[name]
	if !ok {
		http.Error(w, "template not found", http.StatusInternalServerError)
		return
	}
	root := "base"
	if name == "login" {
		root = "login"
	}
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	if err := t.ExecuteTemplate(w, root, data); err != nil {
		// Header may already be written; log via stderr only.
		fmt.Fprintf(io.Discard, "render error: %v", err)
	}
}
