package util
import (
	"fmt"
	"html/template"
	"io/fs"
	"os"
	"path/filepath"
	"slices"
	"strings"
	"management/internal/pkg/render/funcs"
	"management/internal/pkg/render/gen"
	templates "management/web/templates/manage"
)
func CreateTemplateCache(root, layout, partial, extension string) (map[string]*template.Template, error) {
	cache := make(map[string]*template.Template)
	pages, err := getFiles(root, extension)
	if err != nil {
		return nil, err
	}
	layoutAndPartial, err := getLayoutAndPartials(layout, partial, extension)
	if err != nil {
		return nil, err
	}
	for _, page := range pages {
		if strings.HasPrefix(page, layout) || strings.HasSuffix(page, partial) {
			continue
		}
		name := filepath.Base(page)
		pathArr := strings.Split(page, "/")
		dir := pathArr[len(pathArr)-2 : len(pathArr)-1]
		templateName := fmt.Sprintf("%s_%s", dir[0], name)
		ts := template.Must(template.New(templateName).Funcs(gen.Button()).Funcs(funcs.Methods()).ParseFS(templates.TemplateFS, page))
		ts, err = ts.ParseFS(templates.TemplateFS, layoutAndPartial...)
		if err != nil {
			return nil, err
		}
		cache[templateName] = ts
	}
	return cache, nil
}
func getLayoutAndPartials(layout, partial, extension string) ([]string, error) {
	layouts, err := getFiles(layout, extension)
	if err != nil {
		return nil, err
	}
	partials, err := getFiles(partial, extension)
	if err != nil {
		return nil, err
	}
	return slices.Concat(layouts, partials), nil
}
func getFiles(path string, suffix string) ([]string, error) {
	files := make([]string, 0)
	b, err := pathExists(templates.TemplateFS, path)
	if err != nil {
		return nil, err
	}
	if !b {
		return files, nil
	}
	err = fs.WalkDir(templates.TemplateFS, path, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if d.IsDir() {
			return nil
		}
		if strings.HasSuffix(path, suffix) {
			files = append(files, path)
		}
		return nil
	})
	return files, err
}
func pathExists(fs fs.FS, path string) (bool, error) {
	_, err := fs.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false, nil
		}
		return false, err
	}
	return true, err
}