package template

import (
	"fmt"
	"os"
	"path/filepath"
	"sync"
)

var Cache *TemplateCache

type TemplateCache struct {
	mu        sync.RWMutex
	templates map[string]*Template
	basePath  string
}

func NewCache(basePath string) *TemplateCache {
	if basePath == "" {
		exe, err := os.Executable()
		if err != nil {
			basePath = "."
		} else {
			basePath = filepath.Dir(exe)
		}
	}

	return &TemplateCache{
		templates: make(map[string]*Template),
		basePath:  basePath,
	}
}

func InitializeCache(basePath string) {
	Cache = NewCache(basePath)
}

func (c *TemplateCache) Load(name string) (*Template, error) {
	c.mu.RLock()
	tmpl, exists := c.templates[name]
	c.mu.RUnlock()

	if exists {
		if err := c.checkAndReload(tmpl); err != nil {
			return nil, err
		}
		return tmpl, nil
	}

	return c.loadFromFile(name)
}

func (c *TemplateCache) loadFromFile(name string) (*Template, error) {
	filePath := filepath.Join(c.basePath, "templates", name)

	info, err := os.Stat(filePath)
	if err != nil {
		return nil, fmt.Errorf("template file not found: %s", name)
	}

	content, err := os.ReadFile(filePath)
	if err != nil {
		return nil, fmt.Errorf("failed to read template: %w", err)
	}

	tmpl := &Template{
		name:     name,
		content:  string(content),
		modTime:  info.ModTime(),
		filePath: filePath,
		cache:    c,
	}

	c.mu.Lock()
	c.templates[name] = tmpl
	c.mu.Unlock()

	return tmpl, nil
}

func (c *TemplateCache) checkAndReload(tmpl *Template) error {
	info, err := os.Stat(tmpl.filePath)
	if err != nil {
		return err
	}

	if info.ModTime().After(tmpl.modTime) {
		content, err := os.ReadFile(tmpl.filePath)
		if err != nil {
			return err
		}

		c.mu.Lock()
		tmpl.content = string(content)
		tmpl.modTime = info.ModTime()
		c.mu.Unlock()
	}

	return nil
}
