package creditlimit

import (
	"errors"
	"fmt"
	"system-altrak/internal/dto"
	"system-altrak/internal/middleware"
	"system-altrak/pkg/utils"

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

type Handler struct {
	service CreditLimitService
}

func NewHandler(s CreditLimitService) *Handler {
	return &Handler{service: s}
}

func (h *Handler) Create(c *fiber.Ctx) error {
	var req dto.CreditLimitRequest
	if err := c.BodyParser(&req); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid requisition data structure format")
	}

	// Sanitize request data to prevent XSS and SQL injection
	middleware.SanitizeStruct(&req)

	// Use new detailed validation
	result := utils.ValidateStructDetailed(req)
	if !result.IsValid {
		return utils.ValidationErrorResponse(c, "Validation failed", result.Errors)
	}

	userID, _ := c.Locals("user_id").(uint)
	branchID, _ := c.Locals("current_branch_id").(uint)

	cl, err := h.service.Create(&req, userID, branchID)
	if err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}
	return utils.SuccessResponse(c, "Credit Limit Authorization node synchronized successfully", cl)
}

func (h *Handler) Update(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}

	var req dto.CreditLimitRequest
	if err := c.BodyParser(&req); err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid requisition data structure format")
	}

	middleware.SanitizeStruct(&req)

	result := utils.ValidateStructDetailed(req)
	if !result.IsValid {
		return utils.ValidationErrorResponse(c, "Validation failed", result.Errors)
	}

	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)

	cl, err := h.service.Update(id, &req, branchID, role)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return utils.NotFoundResponse(c, "Credit Limit Authorization node")
		}
		return utils.InternalErrorResponse(c, err.Error())
	}

	return utils.SuccessResponse(c, "Credit Limit Authorization node updated successfully", cl)
}

func (h *Handler) List(c *fiber.Ctx) error {
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)

	list, err := h.service.List(branchID, role)
	if err != nil {
		return utils.InternalErrorResponse(c, "Failed to aggregate Credit Limit registry")
	}
	return utils.SuccessResponse(c, "Authorization Matrix Retrieval: Successful", list)
}

func (h *Handler) GetOne(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	cl, err := h.service.GetByID(id, branchID, role)
	if err != nil {
		return utils.NotFoundResponse(c, "Credit Limit Authorization node")
	}
	return utils.SuccessResponse(c, "Sequence data localized successfully", cl)
}

func (h *Handler) DownloadPDF(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	buf, ref, err := h.service.GeneratePDF(id, branchID, role)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return utils.NotFoundResponse(c, "Credit Limit Authorization node")
		}
		return utils.InternalErrorResponse(c, err.Error())
	}

	c.Set("Content-Type", "application/pdf")
	c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=CL-AUTH-%s.pdf", ref))
	return c.Send(buf)
}

func (h *Handler) DownloadExcel(c *fiber.Ctx) error {
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)

	buf, err := h.service.ExportExcel(branchID, role)
	if err != nil {
		return utils.InternalErrorResponse(c, err.Error())
	}

	c.Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Set("Content-Disposition", "attachment; filename=Credit-Limit-Authorization-Registry.xlsx")
	return c.Send(buf)
}

func (h *Handler) Delete(c *fiber.Ctx) error {
	id, err := utils.ParseParamID(c, "id")
	if err != nil {
		return utils.ErrorResponse(c, fiber.StatusBadRequest, "Invalid ID parameter")
	}
	branchID, _ := c.Locals("current_branch_id").(uint)
	role, _ := c.Locals("role").(string)
	if err := h.service.Delete(id, branchID, role); err != nil {
		return utils.InternalErrorResponse(c, "Failed to purge credit limit authorization")
	}
	return utils.SuccessResponse(c, "Authorization record purged successfully", nil)
}
