package controllers

import (
	"math"
	"strconv"

	"github.com/gofiber/fiber/v2" //nolint:goimports
	"github.com/sujit-baniya/fiber-boilerplate/app"
	"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
	"gorm.io/gorm"
)

// RENDER
func Roles(c *fiber.Ctx) error {
	// Obtener los módulos organizados desde el contexto

	// Renderizar la vista "roles" y pasar los datos al frontend
	data := fiber.Map{
		"user":    c.Locals("user").(map[string]interface{}),
		"modules": c.Locals("userModules"),
	}

	// Renderiza la vista "roles" con el layout "layouts/main"
	if err := c.Render("roles", data, "layouts/main"); err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"message": "Error rendering template",
			"error":   err.Error(),
		})
	}
	return nil
}

// CONSULTAR TODOS LOS registroa
func GetRoles(c *fiber.Ctx) error {
	// Obtener parámetros de consulta para la paginación
	pageStr := c.Query("page", "1") // Por defecto, la página es 1
	page, err := strconv.Atoi(pageStr)
	if err != nil || page < 1 {
		page = 1
	}

	searchQuery := c.Query("search", "") // Obtener el término de búsqueda
	limit := 10                          // Número de módulos por página
	offset := (page - 1) * limit

	// Llama a AllModules con el término de búsqueda
	roles, total, err := models.AllRoles(limit, offset, searchQuery)
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"message": "Error retrieving modules",
			"error":   err.Error(),
		})
	}

	modules, err := models.AllModulesSelect()
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"message": "Error retrieving modules",
			"error":   err.Error(),
		})
	}

	// Llama a AllRoles sin el término de búsqueda para obtener todos los roles
	// submodules, err := models.AllSubmodulesSelect() // Pasamos 0 para limit y offset para obtener todos los roles
	// if err != nil {
	// 	return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
	// 		"message": "Error retrieving roles",
	// 		"error":   err.Error(),
	// 	})
	// }

	// Obtener todas las conexiones disponibles para asignar a roles
	conexiones, err := models.GetConxDbSelect("")
	if err != nil {
		conexiones = []models.ConxDb{}
	}

	// Calcular el total de páginas
	totalPages := int(math.Ceil(float64(total) / float64(limit)))

	// Envía los módulos como respuesta JSON junto con la información de paginación
	return c.JSON(fiber.Map{
		"roles":      roles,
		"modules":    modules,
		"conexiones": conexiones,
		"total":      total,      // Total de  disponibles
		"totalPages": totalPages, // Total de páginas
		"page":       page,       // Página actual
		"limit":      limit,      // Límites por página
	})
}
func UpdateRole(c *fiber.Ctx) error {
	var m models.Roles
	uid, err := strconv.ParseUint(c.Params("id"), 10, 32)
	if err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"message": "ID inválido",
			"error":   true,
		})
	}

	// Analiza el cuerpo de la solicitud
	if err := c.BodyParser(&m); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"message": "Error al analizar el cuerpo de la solicitud",
			"error":   true,
		})
	}

	// Buscar el rol actual en la base de datos
	var existingRole models.Roles
	if err := app.Http.Database.DB.Preload("Submodules").First(&existingRole, uid).Error; err != nil {
		return c.Status(fiber.StatusNotFound).JSON(fiber.Map{
			"message": "Rol no encontrado",
			"error":   true,
		})
	}

	// Eliminar todas las relaciones existentes
	if err := app.Http.Database.DB.Model(&existingRole).Association("Submodules").Clear(); err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"message": "Error al eliminar relaciones de submódulos",
			"error":   true,
		})
	}

	// Establecer el ID del rol
	m.ID = uint(uid)

	// Agregar los nuevos submódulos
	var newSubmodules []models.Submodules
	for _, submodule := range m.Submodules {
		var newSubmodule models.Submodules
		if err := app.Http.Database.DB.First(&newSubmodule, submodule.ID).Error; err == nil {
			newSubmodules = append(newSubmodules, newSubmodule)
		}
	}
	m.Submodules = newSubmodules

	// Agregar las nuevas conexiones a BD
	var newConxDBs []models.ConxDb
	for _, db := range m.ConxDBs {
		var found models.ConxDb
		if err := app.Http.Database.DB.First(&found, db.ID).Error; err == nil {
			newConxDBs = append(newConxDBs, found)
		}
	}
	m.ConxDBs = newConxDBs

	// Actualizar el rol en la base de datos
	if err := app.Http.Database.DB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&m).Error; err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"message": err.Error(),
			"error":   true,
		})
	}

	return c.Status(fiber.StatusOK).JSON(fiber.Map{
		"message": "Rol actualizado con éxito",
		"error":   false,
		"role":    m,
	})
}

func CreateRole(c *fiber.Ctx) error {
	var m models.Roles

	// Parse the request body
	if err := c.BodyParser(&m); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"message": "Error parsing request body",
			"error":   true,
		})
	}

	// Look up ConxDBs by ID
	var conxDbs []models.ConxDb
	for _, db := range m.ConxDBs {
		var found models.ConxDb
		if err := app.Http.Database.DB.First(&found, db.ID).Error; err == nil {
			conxDbs = append(conxDbs, found)
		}
	}
	m.ConxDBs = conxDbs

	// Create the role in the database
	if err := models.CreateRole(m); err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"message": err.Error(),
			"error":   true,
		})
	}

	return c.Status(fiber.StatusCreated).JSON(fiber.Map{
		"message": "Role creado correctamente",
		"error":   false,
		"role":    m,
	})
}

// ELIMINAR
func DeleteRole(c *fiber.Ctx) error {
	uid, err := strconv.ParseUint(c.Params("id"), 10, 32)
	if err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"message": "Invalid ID",
			"error":   true,
		})
	}

	if err := models.DeleteRole(uint(uid)); err != nil { // Ensure you have a function for deleting a module
		return c.JSON(fiber.Map{
			"message": err.Error(),
			"error":   true,
		})
	}
	return c.JSON(fiber.Map{
		"message": "Modulo eliminado correctamente",
		"error":   false,
	})
}
