package restricted

import (
	"strconv"

	"git.ma-al.com/goc_daniel/b2b/app/config"
	"git.ma-al.com/goc_daniel/b2b/app/service/productTranslationService"
	"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
	"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
	"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"
)

// ProductTranslationHandler handles endpoints that receive, save and translate product descriptions.
type ProductTranslationHandler struct {
	productTranslationService *productTranslationService.ProductTranslationService
	config                    *config.Config
}

// NewProductTranslationHandler creates a new ProductTranslationHandler instance
func NewProductTranslationHandler() *ProductTranslationHandler {
	productTranslationService := productTranslationService.New()
	return &ProductTranslationHandler{
		productTranslationService: productTranslationService,
		config:                    config.Get(),
	}
}

// ProductTranslationRoutes registers all product description routes
func ProductTranslationHandlerRoutes(r fiber.Router) fiber.Router {
	handler := NewProductTranslationHandler()

	r.Get("/get-product-description", handler.GetProductDescription)
	r.Post("/save-product-description", handler.SaveProductDescription)
	r.Get("/translate-product-description", handler.TranslateProductDescription)

	return r
}

// GetProductDescription returns the product description for a given product ID
func (h *ProductTranslationHandler) GetProductDescription(c fiber.Ctx) error {
	userID, ok := c.Locals("userID").(uint)
	if !ok {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
	}

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

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

	description, err := h.productTranslationService.GetProductDescription(userID, uint(productID), uint(productLangID))
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

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

// SaveProductDescription saves the description for a given product ID, in given language
func (h *ProductTranslationHandler) SaveProductDescription(c fiber.Ctx) error {
	userID, ok := c.Locals("userID").(uint)
	if !ok {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
	}

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

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

	updates := make(map[string]string)
	if err := c.Bind().Body(&updates); err != nil {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
	}

	err = h.productTranslationService.SaveProductDescription(userID, uint(productID), uint(productLangID), updates)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	return c.JSON(response.Make(nullable.GetNil(""), 0, i18n.T_(c, response.Message_OK)))
}

// TranslateProductDescription returns translated product description
func (h *ProductTranslationHandler) TranslateProductDescription(c fiber.Ctx) error {
	userID, ok := c.Locals("userID").(uint)
	if !ok {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrInvalidBody)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrInvalidBody)))
	}

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

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

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

	aiModel := c.Query("model")
	if aiModel != "OpenAI" && aiModel != "Google" {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
	}

	description, err := h.productTranslationService.TranslateProductDescription(userID, uint(productID), uint(productFromLangID), uint(productToLangID), aiModel)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

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