package handlers

import (
	"math"
	"net/http"

	"github.com/gin-gonic/gin"

	"fishfish/database"
	"fishfish/models"
)

func getUserID(c *gin.Context) uint {
	val, _ := c.Get("user_id")
	userID, _ := val.(uint)
	return userID
}

func GetCart(c *gin.Context) {
	userID := getUserID(c)

	var cartItems []models.CartItem
	if err := database.DB.Preload("Item").Where("user_id = ?", userID).Find(&cartItems).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Не удалось получить корзину"})
		return
	}

	c.JSON(http.StatusOK, cartItems)
}

func isValidQuantity(item models.Item, quantity float64) bool {
	if item.UnitType == "piece" {
		return quantity == math.Trunc(quantity)
	}
	return true
}

func AddToCart(c *gin.Context) {
	userID := getUserID(c)

	var req struct {
		ItemID   uint    `json:"item_id" binding:"required"`
		Quantity float64 `json:"quantity" binding:"required,gt=0"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Некорректные данные"})
		return
	}

	var item models.Item

	if err := database.DB.First(&item, req.ItemID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Товар не найден"})
		return
	}

	if !isValidQuantity(item, req.Quantity) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "товар продается поштучно, дробное количество недопустимо"})
		return
	}

	if req.Quantity > item.Stock {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Недостаточно товара на складе"})
		return
	}

	var cartItem models.CartItem
	err := database.DB.Where("user_id = ? AND item_id = ?", userID, req.ItemID).First(&cartItem).Error
	if err != nil {
		cartItem = models.CartItem{
			UserID:   userID,
			ItemID:   req.ItemID,
			Quantity: req.Quantity,
		}

		database.DB.Create(&cartItem)
	} else {
		cartItem.Quantity += req.Quantity
		database.DB.Save(&cartItem)
	}

	c.JSON(http.StatusOK, gin.H{"message": "Товар добавлен в корзину"})
}

func UpdateCartItem(c *gin.Context) {
	userID := getUserID(c)
	cartItemID := c.Param("id")

	var req struct {
		Quantity float64 `json:"quantity" binding:"required,gt=0"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Некорректные данные"})
		return
	}

	var cartItem models.CartItem
	if err := database.DB.Where("id = ? AND user_id = ?", cartItemID, userID).First(&cartItem).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Позиция не найдена"})
		return
	}

	cartItem.Quantity = req.Quantity
	database.DB.Save(&cartItem)

	c.JSON(http.StatusOK, gin.H{"message": "Количество обновлено"})
}

func RemoveFromCart(c *gin.Context) {
	userID := getUserID(c)
	cartItemID := c.Param("id")

	result := database.DB.Where("id = ? AND user_id = ? ", cartItemID, userID).Delete(&models.CartItem{})
	if result.RowsAffected == 0 {
		c.JSON(http.StatusNotFound, gin.H{"error": "Позиция не найдена"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Товар удален из корзины"})
}
