// Package templates provides embedded HTML templates for the RouteWatch application
package templates

import (
	_ "embed"
	"html/template"
	"net/url"
	"sync"
	"time"
)

//go:embed status.html
var statusHTML string

//go:embed as_detail.html
var asDetailHTML string

//go:embed prefix_detail.html
var prefixDetailHTML string

//go:embed prefix_length.html
var prefixLengthHTML string

// Templates contains all parsed templates
type Templates struct {
	Status       *template.Template
	ASDetail     *template.Template
	PrefixDetail *template.Template
	PrefixLength *template.Template
}

var (
	//nolint:gochecknoglobals // Singleton pattern for templates
	defaultTemplates *Templates
	//nolint:gochecknoglobals // Singleton pattern for templates
	once sync.Once
)

const (
	hoursPerDay  = 24
	daysPerMonth = 30
)

// timeSince returns a human-readable duration since the given time
func timeSince(t time.Time) string {
	duration := time.Since(t)
	if duration < time.Minute {
		return "just now"
	}
	if duration < time.Hour {
		minutes := int(duration.Minutes())
		if minutes == 1 {
			return "1 minute ago"
		}

		return duration.Truncate(time.Minute).String() + " ago"
	}
	if duration < hoursPerDay*time.Hour {
		hours := int(duration.Hours())
		if hours == 1 {
			return "1 hour ago"
		}

		return duration.Truncate(time.Hour).String() + " ago"
	}
	days := int(duration.Hours() / hoursPerDay)
	if days == 1 {
		return "1 day ago"
	}
	if days < daysPerMonth {
		return duration.Truncate(hoursPerDay*time.Hour).String() + " ago"
	}

	return t.Format("2006-01-02")
}

// initTemplates parses all embedded templates
func initTemplates() {
	var err error

	defaultTemplates = &Templates{}

	// Create common template functions
	funcs := template.FuncMap{
		"timeSince": timeSince,
		"urlEncode": url.QueryEscape,
	}

	// Parse status template
	defaultTemplates.Status, err = template.New("status").Parse(statusHTML)
	if err != nil {
		panic("failed to parse status template: " + err.Error())
	}

	// Parse AS detail template
	defaultTemplates.ASDetail, err = template.New("asDetail").Funcs(funcs).Parse(asDetailHTML)
	if err != nil {
		panic("failed to parse AS detail template: " + err.Error())
	}

	// Parse prefix detail template
	defaultTemplates.PrefixDetail, err = template.New("prefixDetail").Funcs(funcs).Parse(prefixDetailHTML)
	if err != nil {
		panic("failed to parse prefix detail template: " + err.Error())
	}

	// Parse prefix length template
	defaultTemplates.PrefixLength, err = template.New("prefixLength").Funcs(funcs).Parse(prefixLengthHTML)
	if err != nil {
		panic("failed to parse prefix length template: " + err.Error())
	}
}

// Get returns the singleton Templates instance
func Get() *Templates {
	once.Do(initTemplates)

	return defaultTemplates
}

// StatusTemplate returns the parsed status template
func StatusTemplate() *template.Template {
	return Get().Status
}

// ASDetailTemplate returns the parsed AS detail template
func ASDetailTemplate() *template.Template {
	return Get().ASDetail
}

// PrefixDetailTemplate returns the parsed prefix detail template
func PrefixDetailTemplate() *template.Template {
	return Get().PrefixDetail
}

// PrefixLengthTemplate returns the parsed prefix length template
func PrefixLengthTemplate() *template.Template {
	return Get().PrefixLength
}
