package controllers

import (
	"fmt"
	"html/template"
	"path/filepath"
	"strconv"
	"strings"

	httpmw "trustcontact/internal/http/middleware"
	"trustcontact/internal/services"

	"github.com/gofiber/fiber/v2"
)

type UsersController struct {
	usersService *services.UsersService
}

func NewUsersController(usersService *services.UsersService) *UsersController {
	return &UsersController{usersService: usersService}
}

func (uc *UsersController) Index(c *fiber.Ctx) error {
	pageData, err := uc.queryPage(c)
	if err != nil {
		return err
	}

	viewData := map[string]any{
		"Title":      "Admin Users",
		"NavSection": "admin",
		"PageData":   pageData,
	}
	for k, v := range localsTemplateData(c) {
		viewData[k] = v
	}

	tmpl, err := template.ParseFiles(
		"web/templates/layout.html",
		"web/templates/admin/_navbar.html",
		"web/templates/partials/language_dropdown.html",
		"web/templates/public/_flash.html",
		"web/templates/admin/users/index.html",
		"web/templates/admin/users/_table.html",
	)
	if err != nil {
		return err
	}

	return executeLayout(c, tmpl, viewData)
}

func (uc *UsersController) Table(c *fiber.Ctx) error {
	pageData, err := uc.queryPage(c)
	if err != nil {
		return err
	}

	viewData := map[string]any{"PageData": pageData}
	tmpl, err := template.ParseFiles("web/templates/admin/users/_table.html")
	if err != nil {
		return err
	}

	c.Type("html", "utf-8")
	return tmpl.ExecuteTemplate(c.Response().BodyWriter(), "users_table", viewData)
}

func (uc *UsersController) Modal(c *fiber.Ctx) error {
	id := strings.TrimSpace(c.Params("id"))
	if id == "" {
		return c.Status(fiber.StatusBadRequest).SendString("invalid user id")
	}

	user, err := uc.usersService.GetByID(id)
	if err != nil {
		return err
	}
	if user == nil {
		return c.Status(fiber.StatusNotFound).SendString("user not found")
	}

	viewData := map[string]any{"User": user}
	tmpl, err := template.ParseFiles("web/templates/admin/users/_modal.html")
	if err != nil {
		return err
	}

	c.Type("html", "utf-8")
	return tmpl.ExecuteTemplate(c.Response().BodyWriter(), "users_modal", viewData)
}

func (uc *UsersController) queryPage(c *fiber.Ctx) (*services.UsersPage, error) {
	page := parseIntOrDefault(c.Query("page"), 1)
	pageSize := parseIntOrDefault(c.Query("pageSize"), 10)
	q := strings.TrimSpace(c.Query("q"))
	sort := c.Query("sort", "id")
	dir := c.Query("dir", "asc")

	pageData, err := uc.usersService.List(services.UsersQuery{
		Q:        q,
		Sort:     sort,
		Dir:      dir,
		Page:     page,
		PageSize: pageSize,
	})
	if err != nil {
		return nil, fmt.Errorf("list users: %w", err)
	}

	return pageData, nil
}

func parseIntOrDefault(value string, fallback int) int {
	parsed, err := strconv.Atoi(value)
	if err != nil || parsed <= 0 {
		return fallback
	}
	return parsed
}

func executeLayout(c *fiber.Ctx, tmpl *template.Template, viewData map[string]any) error {
	httpmw.SetTemplateData(c, "NavSection", viewData["NavSection"])
	c.Type("html", "utf-8")
	return tmpl.ExecuteTemplate(c.Response().BodyWriter(), filepath.Base("web/templates/layout.html"), viewData)
}
