package restricted

import (
	"encoding/json"
	"fmt"

	"git.ma-al.com/goc_daniel/b2b/app/service/meiliService"
	searchservice "git.ma-al.com/goc_daniel/b2b/app/service/searchService"
	"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"
)

type MeiliSearchHandler struct {
	meiliService  *meiliService.MeiliService
	searchService *searchservice.SearchService
}

func NewMeiliSearchHandler() *MeiliSearchHandler {
	return &MeiliSearchHandler{
		meiliService:  meiliService.New(),
		searchService: searchservice.New(),
	}
}

func MeiliSearchHandlerRoutes(r fiber.Router) fiber.Router {
	handler := NewMeiliSearchHandler()

	r.Get("/create-index", handler.CreateIndex)
	r.Post("/search", handler.Search)
	r.Post("/settings", handler.GetSettings)

	return r
}

func (h *MeiliSearchHandler) CreateIndex(c fiber.Ctx) error {
	id_lang, ok := c.Locals("langID").(uint)
	if !ok {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
	}

	err := h.meiliService.CreateIndex(id_lang)
	if err != nil {
		fmt.Printf("CreateIndex error: %v\n", err)
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	nothing := ""
	return c.JSON(response.Make(&nothing, 0, i18n.T_(c, response.Message_OK)))
}

func (h *MeiliSearchHandler) Search(c fiber.Ctx) error {
	id_lang, ok := c.Locals("langID").(uint)
	if !ok {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
	}

	index := meiliService.GetIndexName(id_lang)

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

	result, err := h.searchService.Search(index, c.Body(), id_lang)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	if h.searchService.IsIndexNotFound(result.Body) {
		if createErr := h.meiliService.CreateIndex(id_lang); createErr == nil {
			result, err = h.searchService.Search(index, c.Body(), id_lang)
			if err != nil {
				return c.Status(responseErrors.GetErrorStatus(err)).
					JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
			}
		}
	}

	return c.Status(result.StatusCode).Send(result.Body)
}

func (h *MeiliSearchHandler) GetSettings(c fiber.Ctx) error {
	id_lang, ok := c.Locals("langID").(uint)
	if !ok {
		return c.Status(responseErrors.GetErrorStatus(responseErrors.ErrBadAttribute)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadAttribute)))
	}

	index := meiliService.GetIndexName(id_lang)

	result, err := h.searchService.GetIndexSettings(index)
	if err != nil {
		return c.Status(responseErrors.GetErrorStatus(err)).
			JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
	}

	return c.Status(result.StatusCode).Send(result.Body)
}
