package controllers

import (
	"math"
	"strconv"
	"text/template"

	"github.com/gofiber/fiber/v2"
	"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
)

// ─── Plantillas de documento (cotización, contrato, acta, cuenta de cobro) ────

func PlantillasDocumentoView(c *fiber.Ctx) error {
	return c.Render("automatizacion/plantillas_documento", fiber.Map{
		"user":    c.Locals("user"),
		"modules": c.Locals("userModules"),
	}, "layouts/main")
}

func TarifasView(c *fiber.Ctx) error {
	return c.Render("automatizacion/tarifas", fiber.Map{
		"user":    c.Locals("user"),
		"modules": c.Locals("userModules"),
	}, "layouts/main")
}

func GetPlantillasDocumento(c *fiber.Ctx) error {
	page, _ := strconv.Atoi(c.Query("page", "1"))
	limit, _ := strconv.Atoi(c.Query("limit", "20"))
	if page < 1 {
		page = 1
	}
	offset := (page - 1) * limit
	records, total, err := models.GetAllPlantillasDocumento(limit, offset, c.Query("search"), c.Query("tipo"))
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(fiber.Map{
		"registros":  records,
		"total":      total,
		"totalPages": int(math.Ceil(float64(total) / float64(limit))),
		"page":       page,
	})
}

func GetPlantillaDocumento(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 32)
	if err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
	}
	item, err := models.GetPlantillaDocumentoByID(uint(id))
	if err != nil {
		return c.Status(404).JSON(fiber.Map{"error": "No encontrada"})
	}
	return c.JSON(item)
}

func CreatePlantillaDocumento(c *fiber.Ctx) error {
	var m models.PlantillaDocumento
	if err := c.BodyParser(&m); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": err.Error()})
	}
	if m.ContenidoHTML != "" {
		if _, err := template.New("validate").Parse(m.ContenidoHTML); err != nil {
			return c.Status(400).JSON(fiber.Map{"error": "Sintaxis inválida en el HTML: " + err.Error()})
		}
	}
	if err := models.CreatePlantillaDocumento(m); err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.Status(201).JSON(fiber.Map{"message": "Plantilla creada", "ok": true})
}

func UpdatePlantillaDocumento(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 32)
	if err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
	}
	var updates map[string]interface{}
	if err := c.BodyParser(&updates); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": err.Error()})
	}
	if html, ok := updates["contenido_html"].(string); ok && html != "" {
		if _, err := template.New("validate").Parse(html); err != nil {
			return c.Status(400).JSON(fiber.Map{"error": "Sintaxis inválida en el HTML: " + err.Error()})
		}
	}
	if err := models.UpdatePlantillaDocumento(uint(id), updates); err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(fiber.Map{"message": "Actualizado", "ok": true})
}

func DeletePlantillaDocumento(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 32)
	if err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
	}
	if err := models.DeletePlantillaDocumento(uint(id)); err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(fiber.Map{"message": "Eliminado", "ok": true})
}

// ─── Tarifas ────────────────────────────────────────────────────────────────

func GetTarifas(c *fiber.Ctx) error {
	page, _ := strconv.Atoi(c.Query("page", "1"))
	limit, _ := strconv.Atoi(c.Query("limit", "50"))
	if page < 1 {
		page = 1
	}
	offset := (page - 1) * limit
	records, total, err := models.GetAllTarifas(limit, offset, c.Query("search"), c.Query("categoria"))
	if err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(fiber.Map{
		"registros":  records,
		"total":      total,
		"totalPages": int(math.Ceil(float64(total) / float64(limit))),
		"page":       page,
	})
}

func CreateTarifa(c *fiber.Ctx) error {
	var m models.Tarifa
	if err := c.BodyParser(&m); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": err.Error()})
	}
	if err := models.CreateTarifa(m); err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.Status(201).JSON(fiber.Map{"message": "Tarifa creada", "ok": true})
}

func UpdateTarifa(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 32)
	if err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
	}
	var updates map[string]interface{}
	if err := c.BodyParser(&updates); err != nil {
		return c.Status(400).JSON(fiber.Map{"error": err.Error()})
	}
	if err := models.UpdateTarifa(uint(id), updates); err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(fiber.Map{"message": "Actualizado", "ok": true})
}

func DeleteTarifa(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 32)
	if err != nil {
		return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
	}
	if err := models.DeleteTarifa(uint(id)); err != nil {
		return c.Status(500).JSON(fiber.Map{"error": err.Error()})
	}
	return c.JSON(fiber.Map{"message": "Eliminado", "ok": true})
}
