package handlers

import (
	"html/template"
	"strconv"

	qfassets "git.mchus.pro/mchus/quoteforge"
	"git.mchus.pro/mchus/quoteforge/internal/repository"
	"git.mchus.pro/mchus/quoteforge/internal/services"
	"github.com/gin-gonic/gin"
)

type WebHandler struct {
	templates        map[string]*template.Template
	componentService *services.ComponentService
}

func NewWebHandler(_ string, componentService *services.ComponentService) (*WebHandler, error) {
	funcMap := template.FuncMap{
		"sub": func(a, b int) int { return a - b },
		"add": func(a, b int) int { return a + b },
		"mul": func(a, b int) int { return a * b },
		"div": func(a, b int) int {
			if b == 0 {
				return 0
			}
			return (a + b - 1) / b
		},
		"deref": func(f *float64) float64 {
			if f == nil {
				return 0
			}
			return *f
		},
		"jsesc": func(s string) string {
			// Escape string for safe use in JavaScript
			result := ""
			for _, r := range s {
				switch r {
				case '\\':
					result += "\\\\"
				case '\'':
					result += "\\'"
				case '"':
					result += "\\\""
				case '\n':
					result += "\\n"
				case '\r':
					result += "\\r"
				case '\t':
					result += "\\t"
				default:
					result += string(r)
				}
			}
			return result
		},
	}

	templates := make(map[string]*template.Template)
	// Load each page template with base
	simplePages := []string{"login.html", "configs.html", "projects.html", "project_detail.html", "pricelists.html", "pricelist_detail.html", "config_revisions.html"}
	for _, page := range simplePages {
		var tmpl *template.Template
		var err error
		tmpl, err = template.New("").Funcs(funcMap).ParseFS(
			qfassets.TemplatesFS,
			"web/templates/base.html",
			"web/templates/"+page,
		)
		if err != nil {
			return nil, err
		}
		templates[page] = tmpl
	}

	// Index page needs components_list.html as well
	var indexTmpl *template.Template
	var err error
	indexTmpl, err = template.New("").Funcs(funcMap).ParseFS(
		qfassets.TemplatesFS,
		"web/templates/base.html",
		"web/templates/index.html",
		"web/templates/components_list.html",
	)
	if err != nil {
		return nil, err
	}
	templates["index.html"] = indexTmpl

	// Load partial templates (no base needed)
	partials := []string{"components_list.html"}
	for _, partial := range partials {
		var tmpl *template.Template
		var err error
		tmpl, err = template.New("").Funcs(funcMap).ParseFS(
			qfassets.TemplatesFS,
			"web/templates/"+partial,
		)
		if err != nil {
			return nil, err
		}
		templates[partial] = tmpl
	}

	return &WebHandler{
		templates:        templates,
		componentService: componentService,
	}, nil
}

func (h *WebHandler) render(c *gin.Context, name string, data gin.H) {
	c.Header("Content-Type", "text/html; charset=utf-8")
	tmpl, ok := h.templates[name]
	if !ok {
		c.String(500, "Template not found: %s", name)
		return
	}
	// Execute the page template which will use base
	if err := tmpl.ExecuteTemplate(c.Writer, name, data); err != nil {
		c.String(500, "Template error: %v", err)
	}
}

func (h *WebHandler) Index(c *gin.Context) {
	// Redirect to projects page - configurator is accessed via /configurator?uuid=...
	c.Redirect(302, "/projects")
}

func (h *WebHandler) Configurator(c *gin.Context) {
	categories, _ := h.componentService.GetCategories()
	uuid := c.Query("uuid")

	filter := repository.ComponentFilter{}
	result, err := h.componentService.List(filter, 1, 20)

	data := gin.H{
		"ActivePage": "configurator",
		"Categories": categories,
		"Components": []interface{}{},
		"Total":      int64(0),
		"Page":       1,
		"PerPage":    20,
		"ConfigUUID": uuid,
	}

	if err == nil && result != nil {
		data["Components"] = result.Components
		data["Total"] = result.Total
		data["Page"] = result.Page
		data["PerPage"] = result.PerPage
	}

	h.render(c, "index.html", data)
}

func (h *WebHandler) Login(c *gin.Context) {
	h.render(c, "login.html", nil)
}

func (h *WebHandler) Configs(c *gin.Context) {
	h.render(c, "configs.html", gin.H{"ActivePage": "configs"})
}

func (h *WebHandler) Projects(c *gin.Context) {
	h.render(c, "projects.html", gin.H{"ActivePage": "projects"})
}

func (h *WebHandler) ProjectDetail(c *gin.Context) {
	h.render(c, "project_detail.html", gin.H{
		"ActivePage":  "projects",
		"ProjectUUID": c.Param("uuid"),
	})
}

func (h *WebHandler) ConfigRevisions(c *gin.Context) {
	h.render(c, "config_revisions.html", gin.H{
		"ActivePage": "configs",
		"ConfigUUID": c.Param("uuid"),
	})
}

func (h *WebHandler) Pricelists(c *gin.Context) {
	h.render(c, "pricelists.html", gin.H{"ActivePage": "pricelists"})
}

func (h *WebHandler) PricelistDetail(c *gin.Context) {
	h.render(c, "pricelist_detail.html", gin.H{"ActivePage": "pricelists"})
}

// Partials for htmx

func (h *WebHandler) ComponentsPartial(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))

	filter := repository.ComponentFilter{
		Category: c.Query("category"),
		Search:   c.Query("search"),
	}

	data := gin.H{
		"Components": []interface{}{},
		"Total":      int64(0),
		"Page":       page,
		"PerPage":    20,
	}

	result, err := h.componentService.List(filter, page, 20)
	if err == nil && result != nil {
		data["Components"] = result.Components
		data["Total"] = result.Total
		data["Page"] = result.Page
		data["PerPage"] = result.PerPage
	}

	c.Header("Content-Type", "text/html; charset=utf-8")
	if tmpl, ok := h.templates["components_list.html"]; ok {
		tmpl.ExecuteTemplate(c.Writer, "components_list.html", data)
	}
}
