package controllers

import (
	"errors"
	"nearle/repositories"
	"nearle/services"
	"net/http"
	"strconv"

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

type CatalogueController struct {
	catalogueService services.CatalogueService
}

func NewCatalogueController(catalogueService services.CatalogueService) *CatalogueController {
	return &CatalogueController{catalogueService: catalogueService}
}

func (ctl *CatalogueController) GetBrands(c *fiber.Ctx) error {
	brands, err := ctl.catalogueService.GetBrands()
	if err != nil {
		return c.JSON(fiber.Map{
			"code":    500,
			"message": "Failed to fetch catalogue brands",
			"status":  false,
		})
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": brands,
	})
}

func (ctl *CatalogueController) GetCategories(c *fiber.Ctx) error {
	brand := c.Query("brand")
	if brand == "" {
		return c.JSON(fiber.Map{
			"code":    400,
			"message": "brand is required",
			"status":  false,
		})
	}

	categories, err := ctl.catalogueService.GetCategories(brand)
	if err != nil {
		if errors.Is(err, repositories.ErrUnknownBrand) {
			return c.JSON(fiber.Map{
				"code":    400,
				"message": "Unknown brand: " + brand,
				"status":  false,
			})
		}
		return c.JSON(fiber.Map{
			"code":    500,
			"message": "Failed to fetch categories",
			"status":  false,
		})
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": categories,
	})
}

func (ctl *CatalogueController) GetProducts(c *fiber.Ctx) error {
	// brand is an optional filter: omitting it browses the entire catalogue
	// across every brand, which is the entry point for "show everything,
	// then let the store owner choose".
	brand := c.Query("brand")
	category := c.Query("category")
	keyword := c.Query("keyword")
	pageno, _ := strconv.Atoi(c.Query("pageno"))
	pagesize, _ := strconv.Atoi(c.Query("pagesize"))

	products, total, err := ctl.catalogueService.GetProducts(brand, category, keyword, pageno, pagesize)
	if err != nil {
		if errors.Is(err, repositories.ErrUnknownBrand) {
			return c.JSON(fiber.Map{
				"code":    400,
				"message": "Unknown brand: " + brand,
				"status":  false,
			})
		}
		return c.JSON(fiber.Map{
			"code":    500,
			"message": "Failed to fetch catalogue products",
			"status":  false,
		})
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"total":   total,
		"details": products,
	})
}

func (ctl *CatalogueController) GetProductBySKU(c *fiber.Ctx) error {
	brand := c.Query("brand")
	sku := c.Query("sku")
	if brand == "" || sku == "" {
		return c.JSON(fiber.Map{
			"code":    400,
			"message": "brand and sku are required",
			"status":  false,
		})
	}

	product, err := ctl.catalogueService.GetProductBySKU(brand, sku)
	if err != nil {
		if errors.Is(err, repositories.ErrUnknownBrand) {
			return c.JSON(fiber.Map{
				"code":    400,
				"message": "Unknown brand: " + brand,
				"status":  false,
			})
		}
		return c.JSON(fiber.Map{
			"code":    500,
			"message": "Failed to fetch catalogue product",
			"status":  false,
		})
	}
	if product == nil {
		return c.JSON(fiber.Map{
			"code":    404,
			"message": "Product not found",
			"status":  false,
		})
	}

	return c.JSON(fiber.Map{
		"code":    http.StatusOK,
		"message": "Success",
		"status":  true,
		"details": product,
	})
}
