package restricted

import (
	"strconv"

	"git.ma-al.com/goc_daniel/b2b/app/config"
	"git.ma-al.com/goc_daniel/b2b/app/model"
	"git.ma-al.com/goc_daniel/b2b/app/service/productService"
	"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
	"git.ma-al.com/goc_daniel/b2b/app/utils/localeExtractor"
	"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
	"git.ma-al.com/goc_daniel/b2b/app/utils/query/query_params"
	"git.ma-al.com/goc_daniel/b2b/app/utils/response"
	"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
	"github.com/gofiber/fiber/v3"
)

type ProductsHandler struct {
	productService *productService.ProductService
	config         *config.Config
}

// NewListProductsHandler creates a new ListProductsHandler instance
func NewProductsHandler() *ProductsHandler {
	productService := productService.New()
	return &ProductsHandler{
		productService: productService,
		config:         config.Get(),
	}
}

func ProductsHandlerRoutes(r fiber.Router) fiber.Router {
	handler := NewProductsHandler()

	r.Get("/:id/:country_id/:quantity", handler.GetProductJson)
	r.Get("/list", handler.ListProducts)

	return r
}

func (h *ProductsHandler) GetProductJson(c fiber.Ctx) error {
	idStr := c.Params("id")

	p_id_product, err := strconv.Atoi(idStr)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	country_idStr := c.Params("country_id")

	b2b_id_country, err := strconv.Atoi(country_idStr)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	quantityStr := c.Params("quantity")

	p_quantity, err := strconv.Atoi(quantityStr)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	customer, ok := localeExtractor.GetCustomer(c)
	if !ok || customer == nil {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
	}
	productJson, err := h.productService.GetJSON(p_id_product, int(customer.LangID), int(customer.ID), b2b_id_country, p_quantity)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	return c.JSON(response.Make(&productJson, 1, i18n.T_(c, response.Message_OK)))
}

func (h *ProductsHandler) ListProducts(c fiber.Ctx) error {
	paging, filters, err := query_params.ParseFilters[model.Product](c, columnMappingListProducts)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	id_lang, ok := localeExtractor.GetLangID(c)
	if !ok {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
	}

	list, err := h.productService.Find(id_lang, paging, filters)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	return c.JSON(response.Make(&list.Items, int(list.Count), i18n.T_(c, response.Message_OK)))
}

var columnMappingListProducts map[string]string = map[string]string{
	"product_id":    "ps.id_product",
	"name":          "pl.name",
	"reference":     "p.reference",
	"category_name": "cl.name",
	"category_id":   "cp.id_category",
	"quantity":      "sa.quantity",
}
