package router

import (
	"bookhoard/internal/database"
	"bookhoard/templates"
	"bytes"
	"encoding/json"
	"net/http"
	"strings"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgtype"
	"github.com/labstack/echo/v5"
)

func registerFiltersRoutes(cfg *Config) {
	e := cfg.Echo

	// JWT middleware for protected routes
	jwtMiddleware := createJWTMiddleware(cfg)
	protected := e.Group("/api", jwtMiddleware)

	// Saved filters routes
	filters := protected.Group("/saved-filters")
	filters.GET("", cfg.FiltersHandler.GetSavedFilters)
	filters.GET("/:id", cfg.FiltersHandler.GetSavedFilterByID)
	// POST route with HTMX support
	filters.POST("", func(c *echo.Context) error {
		// Check if HTMX request (expects HTML)
		if c.Request().Header.Get("HX-Request") == "true" {
			return handleCreateFilterHTML(c, cfg)
		}
		// Otherwise return JSON (API clients)
		return cfg.FiltersHandler.CreateSavedFilter(c)
	})
	filters.PUT("/:id", cfg.FiltersHandler.UpdateSavedFilter)
	filters.DELETE("/:id", cfg.FiltersHandler.DeleteSavedFilter)
}

// handleCreateFilterHTML renders HTML response for HTMX requests
func handleCreateFilterHTML(c *echo.Context, cfg *Config) error {
	user, ok := c.Get("user").(database.Users)
	if !ok {
		return c.String(http.StatusUnauthorized, "Unauthorized")
	}
	userUUID := uuid.UUID(user.ID.Bytes)
	// Parse form data
	var req struct {
		Name         string `form:"filter_name"`
		ResourceType string `form:"resource_type"`
	}

	if err := c.Bind(&req); err != nil {
		return c.String(http.StatusBadRequest, "Invalid request body")
	}
	if req.Name == "" || req.ResourceType == "" {
		return c.String(http.StatusBadRequest, "name and resource_type are required")
	}
	// Collect filter data from individual form fields (via hx-include)
	filtersMap := collectFilterFormData(c)
	// Convert to JSON for database storage
	filtersJSON, err := json.Marshal(filtersMap)
	if err != nil {
		return c.String(http.StatusInternalServerError, "Failed to encode filters")
	}
	// Create filter using service layer
	filter, err := cfg.Queries.CreateSavedFilter(c.Request().Context(), database.CreateSavedFilterParams{
		UserID:       pgtype.UUID{Bytes: userUUID, Valid: true},
		Name:         req.Name,
		ResourceType: req.ResourceType,
		Filters:      filtersJSON,
	})
	if err != nil {
		errorMsg := err.Error()
		// Check for duplicate name error (wrapped or unwrapped)
		if strings.Contains(errorMsg, "filter with name") && strings.Contains(errorMsg, "already exists") {
			if c.Request().Header.Get("HX-Request") == "true" {
				return c.HTML(http.StatusConflict, `<div hx-swap-oob="innerHTML:#filter-save-error" style="color: #ef4444; padding: 0.75rem; border-radius: 0.5rem; margin-bottom: 1rem;">⚠️ Filter with this name already exists</div>`)
			}
			return c.String(http.StatusConflict, "Filter with this name already exists")
		}
		return c.String(http.StatusInternalServerError, "failed to create filter: "+errorMsg)
	}
	// Render filter item HTML to buffer
	var buf bytes.Buffer
	filterID := uuid.Must(uuid.FromBytes(filter.ID.Bytes[:]))
	err = templates.FilterItem(
		filterID.String(),
		filter.Name,
	).Render(c.Request().Context(), &buf)
	if err != nil {
		return c.HTML(http.StatusInternalServerError, `<div style="color: red;">Render error</div>`)
	}

	return c.HTML(http.StatusCreated, buf.String())
}

// collectFilterFormData extracts filter values from form fields
func collectFilterFormData(c *echo.Context) map[string]string {
	filters := make(map[string]string)

	// Collect individual form fields
	if q := c.FormValue("q"); q != "" {
		filters["q"] = q
	}
	if author := c.FormValue("author_filter"); author != "" {
		filters["author_filter"] = author
	}
	if tags := c.FormValue("tags_filter"); tags != "" {
		filters["tags_filter"] = tags
	}
	if series := c.FormValue("series_filter"); series != "" {
		filters["series_filter"] = series
	}
	if language := c.FormValue("language_filter"); language != "" {
		filters["language_filter"] = language
	}
	if yearMin := c.FormValue("year_min"); yearMin != "" {
		filters["year_min"] = yearMin
	}
	if yearMax := c.FormValue("year_max"); yearMax != "" {
		filters["year_max"] = yearMax
	}
	if hasCover := c.FormValue("has_cover"); hasCover != "" {
		filters["has_cover"] = hasCover
	}
	if libraryID := c.FormValue("library_id"); libraryID != "" {
		filters["library_id"] = libraryID
	}
	if sort := c.FormValue("sort"); sort != "" {
		filters["sort"] = sort
	}
	if limit := c.FormValue("limit"); limit != "" {
		filters["limit"] = limit
	}
	if offset := c.FormValue("offset"); offset != "" {
		filters["offset"] = offset
	}

	return filters
}
