package response

import (
	"bytes"
	"fmt"
	"html/template"
	"net/http"

	"brainminder.speedtech.it/assets"
	"brainminder.speedtech.it/internal/funcs"
)

func HXFragment(fullBuf *bytes.Buffer, pagePaths []string, templateName string, data any) error {
	var err error
	var buf *bytes.Buffer
	buf, err = Fragment(pagePaths, templateName, data)
	fullBuf.Write(buf.Bytes())
	return err
}

func HXFragmentOOB(fullBuf *bytes.Buffer, pagePaths []string, templateName string, data any, div_id string) error {
	var err error
	var buf *bytes.Buffer
	var tag string = "div"
	if div_id == "message" {
		tag = "dialog"
	}
	fullBuf.WriteString(fmt.Sprintf("<%s hx-swap-oob=\"true\" id=\"%s\">", tag, div_id))
	buf, err = Fragment(pagePaths, templateName, data)
	fullBuf.Write(buf.Bytes())
	fullBuf.WriteString(fmt.Sprintf("</%s>", tag))
	return err
}

func Fragment(pagePaths []string, templateName string, data any) (*bytes.Buffer, error) {
	for i := range pagePaths {
		pagePaths[i] = "templates/" + pagePaths[i]
	}

	buf := new(bytes.Buffer)

	ts, err := template.New("").Funcs(funcs.TemplateFuncs).ParseFS(assets.EmbeddedFiles, pagePaths...)
	if err != nil {
		return buf, err
	}

	err = ts.ExecuteTemplate(buf, templateName, data)
	if err != nil {
		return buf, err
	}

	return buf, err
}

func GuestPage(w http.ResponseWriter, status int, data any, pagePaths []string, templateNames ...string) error {
	templateName := "guest"

	if len(templateNames) > 0 {
		templateName = templateNames[0]
	}
	return GuestPageWithHeaders(w, status, data, nil, pagePaths, templateName)
}

func GuestPageWithHeaders(w http.ResponseWriter, status int, data any, headers http.Header, pagePaths []string, templateName string) error {
	templateFile := templateName + ".tmpl"
	pagePaths = append(pagePaths, templateFile)

	return NamedTemplateWithHeaders(w, status, data, headers, templateName, pagePaths)
}

func Page(w http.ResponseWriter, status int, data any, pagePaths []string, templateNames ...string) error {
	templateName := "base"

	if len(templateNames) > 0 {
		templateName = templateNames[0]
	}
	return PageWithHeaders(w, status, data, nil, pagePaths, templateName)
}

func PageWithHeaders(w http.ResponseWriter, status int, data any, headers http.Header, pagePaths []string, templateName string) error {
	templateFile := templateName + ".tmpl"
	pagePaths = append(pagePaths, templateFile, "partials/sidebar.tmpl", "partials/nav.tmpl", "partials/footer.tmpl", "partials/types-list.tmpl", "partials/notebooks-list.tmpl")

	return NamedTemplateWithHeaders(w, status, data, headers, templateName, pagePaths)
}

func NamedTemplate(w http.ResponseWriter, status int, data any, templateName string, pagePaths []string) error {
	return NamedTemplateWithHeaders(w, status, data, nil, templateName, pagePaths)
}

func NamedTemplateWithHeaders(w http.ResponseWriter, status int, data any, headers http.Header, templateName string, pagePaths []string) error {
	for i := range pagePaths {
		pagePaths[i] = "templates/" + pagePaths[i]
	}

	ts, err := template.New("").Funcs(funcs.TemplateFuncs).ParseFS(assets.EmbeddedFiles, pagePaths...)
	if err != nil {
		return err
	}

	buf := new(bytes.Buffer)

	err = ts.ExecuteTemplate(buf, templateName, data)
	if err != nil {
		return err
	}

	for key, value := range headers {
		w.Header()[key] = value
	}

	w.WriteHeader(status)
	buf.WriteTo(w)

	return nil
}
