package routes

import (
	"context"
	"fmt"
	"maps"
	"net/http"
	"strings"

	"github.com/a-h/templ"
)

func render(component func(context.Context) templ.Component) func(http.ResponseWriter, *http.Request) {
	return func(writer http.ResponseWriter, req *http.Request) {
		err := component(req.Context()).Render(req.Context(), writer)
		if err != nil {
			http.Error(writer, fmt.Sprintf("can't render component: %s", err), http.StatusInternalServerError)
		}
	}
}

func normalizePath(pathSegments ...string) string {
	normalized := make([]string, len(pathSegments))

	for i, segment := range pathSegments {
		normalized[i] = strings.Trim(segment, "/")
	}

	return "/" + strings.TrimPrefix(strings.Join(normalized, "/"), "/")
}

func routesToMap(rootPath string, route *Route) RoutesMap {
	routesMap := make(RoutesMap, 0)

	optionsHandler := route.Options
	if optionsHandler == nil {
		allowed := []string{}
		if route.Get != nil {
			allowed = append(allowed, http.MethodGet)
		}
		if route.Post != nil {
			allowed = append(allowed, http.MethodPost)
		}
		if route.Put != nil {
			allowed = append(allowed, http.MethodPut)
		}
		if route.Delete != nil {
			allowed = append(allowed, http.MethodDelete)
		}
		allowed = append(allowed, http.MethodOptions)

		allowedString := strings.Join(allowed, ", ")
		optionsHandler = func(writer http.ResponseWriter, req *http.Request) {
			writer.Header().Set("Allow", allowedString)
			writer.WriteHeader(http.StatusNoContent)
		}
	}

	currentPath := normalizePath(rootPath, route.Path)
	routesMap[currentPath] = map[string]func(http.ResponseWriter, *http.Request){
		http.MethodGet:     route.Get,
		http.MethodPost:    route.Post,
		http.MethodPut:     route.Put,
		http.MethodDelete:  route.Delete,
		http.MethodOptions: optionsHandler,
	}

	for _, sub := range route.SubRoutes {
		maps.Copy(routesMap, routesToMap(currentPath, sub))
	}

	return routesMap
}