package html

import (
	"bytes"
	"fmt"
	"io/fs"
	"net/http"
	"os"

	"github.com/rs/zerolog/log"
	"source.gleipnir.technology/Gleipnir/nidus-sync/config"
)

// The filesystem being used
var templates templateSystem

type templateSystem interface {
	loadAll() error
	renderOrError(http.ResponseWriter, string, interface{})
}

type templateSystemDisk struct {
	sourceFS fs.FS
}

func LoadTemplates() error {
	_, err := os.Stat("html/template")
	if err == nil && !config.IsProductionEnvironment() {
		templates = templateSystemDisk{
			sourceFS: os.DirFS("./html/template"),
		}
	} else {
		templates, err = newTemplateSystemEmbed()
		if err != nil {
			return fmt.Errorf("Failed to load embedded templates: %w", err)
		}
	}
	return nil
}

func (ts templateSystemDisk) loadAll() error {
	return nil
}
func (ts templateSystemDisk) renderOrError(w http.ResponseWriter, template_name string, context interface{}) {
	t, err := parseTemplate(ts.sourceFS, template_name)
	if err != nil {
		log.Error().Err(err).Str("template_name", template_name).Msg("Failed to parse template")
		RespondError(w, "Failed to parse template", err, http.StatusInternalServerError)
		return
	}
	buf := &bytes.Buffer{}
	err = t.Execute(buf, context)
	if err != nil {
		log.Error().Err(err).Str("name", template_name).Msg("Failed to render template")
		RespondError(w, "Failed to render template", err, http.StatusInternalServerError)
		return
	}
	_, err = buf.WriteTo(w)
	if err != nil {
		log.Error().Err(err).Msg("failed to write buffer")
	}
}

/*
	func addSVGTemplates(fsys fs.FS, templ *template.Template) error {
		svgs, err := fs.ReadDir(fsys, ".")
		if err != nil {
			log.Warn().Msg("Failed to read svg directory")
			return nil
		}
		for _, svg := range svgs {
			content, err := fs.ReadFile(fsys, svg.Name())
			if err != nil {
				return fmt.Errorf("Failed to read svg '%s' from embedded filesystem: %w", svg, err)
			}
			svg_name := svg.Name()
			svg_template := fmt.Sprintf("{{define \"%s\"}}%s{{end}}", svg_name, string(content))
			svg_t, err := template.New(svg_name).Parse(svg_template)
			if err != nil {
				return fmt.Errorf("Failed to parse svg '%s' from embedded filesystem: %v", svg, err)
			}
			_, err = templ.AddParseTree(svg_t.Name(), svg_t.Tree)
			if err != nil {
				return fmt.Errorf("Failed to add svg '%s' to embedded template: %v", svg, err)
			}
			//log.Debug().Str("name", svg_name).Msg("add svg template")
		}
		return nil
	}

	func executeTemplate(w io.Writer, data any) error {
		if bt.template == nil {
			name := path.Base(bt.files[0])
			templ, err := parseFromDisk(bt.subdir, bt.files)
			if err != nil {
				return fmt.Errorf("Failed to parse template file: %w", err)
			}
			if templ == nil {
				w.Write([]byte("Failed to read from disk: "))
				return errors.New("Template parsing failed")
			}
			//log.Debug().Str("name", templ.Name()).Msg("Parsed template")
			return templ.ExecuteTemplate(w, name, data)
		} else {
			name := path.Base(bt.files[0])
			return bt.template.ExecuteTemplate(w, name, data)
		}
	}

	func parseEmbedded(embeddedFiles embed.FS, subdir string, files []string) *template.Template {
		funcMap := makeFuncMap()
		// Remap the file names to embedded paths
		embeddedFilePaths := make([]string, 0)
		for _, f := range files {
			embeddedFilePaths = append(embeddedFilePaths, strings.TrimPrefix(f, subdir))
		}
		name := path.Base(embeddedFilePaths[0])
		log.Debug().Str("name", name).Strs("paths", embeddedFilePaths).Msg("Parsing embedded template")
		t, err := template.New(name).Funcs(funcMap).ParseFS(embeddedFiles, embeddedFilePaths...)
		if err != nil {
			panic(fmt.Sprintf("Failed to parse embedded template %s: %v", name, err))
		}
		svg_fs, err := fs.Sub(embeddedFiles, "template/svg")
		if err != nil {
			panic(fmt.Sprintf("Failed to read static/svg: %v", err))
		}
		err = addSVGTemplates(svg_fs, t)
		if err != nil {
			panic(fmt.Sprintf("Failed to add SVG templates: %v", err))
		}
		return t
	}

	func parseFromDisk(subdir string, files []string) (*template.Template, error) {
		funcMap := makeFuncMap()
		name := path.Base(files[0])
		//log.Debug().Str("name", name).Strs("files", files).Msg("parsing from disk")
		templ, err := template.New(name).Funcs(funcMap).ParseFiles(files...)
		if err != nil {
			return nil, fmt.Errorf("Failed to parse %s: %w", files, err)
		}
		fsys := os.DirFS(subdir + "/template/svg")
		err = addSVGTemplates(fsys, templ)
		if err != nil {
			return nil, fmt.Errorf("Failed to add SVGs from disk: %w", err)
		}
		return templ, nil
	}
*/
