package theme

import (
	"fmt"
	"html/template"
	"os"
	"path/filepath"
	"strings"

	"metazone.cc/metalab/internal/common"
)

// TemplateRoot 模板根目录配置
type TemplateRoot struct {
	Dir    string // 目录路径
	Prefix string // 模板名前缀（如 "admin/" 表示管理后台）
}

// LoadTemplates 加载多个根目录的 .html 模板到同一模板集
// 模板名 = prefix + 相对于 root.Dir 的相对路径
func LoadTemplates(roots ...TemplateRoot) (*template.Template, error) {
	funcMap := template.FuncMap{
		"add":        func(a, b int) int { return a + b },
		"subtract":   func(a, b int) int { return a - b },
		"formatTTL": formatTTL,
		"assetV":     common.AssetV,
		// derefUint 安全解引用 *uint 指针。
		// Go 1.26 的模板引擎在将 *uint 传给 printf/print 时不会自动解引用，
		// 导致打印指针地址而非值。通过此函数显式解引用后传给 printf。
		"derefUint": func(p *uint) uint {
			if p == nil {
				return 0
			}
			return *p
		},
	}
	t := template.New("").Funcs(funcMap)
	for _, root := range roots {
		dir := filepath.Clean(root.Dir) + string(os.PathSeparator)
		err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if info.IsDir() || filepath.Ext(path) != ".html" {
				return nil
			}
			content, err := os.ReadFile(path)
			if err != nil {
				return err
			}
			// 模板名：prefix + 相对路径
			name := root.Prefix + strings.TrimPrefix(path, dir)
			_, err = t.New(name).Parse(string(content))
			return err
		})
		if err != nil {
			return nil, err
		}
	}
	return t, nil
}

// LoadContent 读取主题内容文件（准则等），返回不转义的 template.HTML。
// 后期改为查数据库时，只需修改此函数实现，调用方不变。
func LoadContent(path string) (template.HTML, error) {
	content, err := os.ReadFile(path)
	if err != nil {
		return "", err
	}
	return template.HTML(content), nil
}

// formatTTL 将剩余分钟数格式化为人类可读的时间（如 "23 小时"、"3 天"、"15 分钟"）
func formatTTL(minutes int) string {
	if minutes <= 0 {
		return "即将过期"
	}
	if minutes < 60 {
		return fmt.Sprintf("%d 分钟", minutes)
	}
	hours := minutes / 60
	if hours < 24 {
		return fmt.Sprintf("%d 小时", hours)
	}
	days := hours / 24
	remainHours := hours % 24
	if remainHours == 0 {
		return fmt.Sprintf("%d 天", days)
	}
	return fmt.Sprintf("%d 天 %d 小时", days, remainHours)
}
