package handlers

import (
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"fishfish/database"
	"fishfish/models"
)

func StockIn(c *gin.Context) {
	var input struct {
		ItemID   uint    `json:"item_id" binding:"required"`
		Quantity float64 `json:"quantity" binding:"required"`
		Comment  string  `json:"comment"`
	}

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

	if input.Quantity <= 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Количество должно быть положительным"})
		return
	}

	err := database.DB.Transaction(func(tx *gorm.DB) error {
		result := tx.Model(&models.Item{}).
			Where("id = ? ", input.ItemID).
			Update("stock", gorm.Expr("stock + ?", input.Quantity))

		if result.Error != nil {
			return result.Error
		}

		if result.RowsAffected == 0 {
			return fmt.Errorf("товар не найден")
		}

		movement := models.StockMovement{
			ItemID:   input.ItemID,
			Type:     "in",
			Quantity: input.Quantity,
			Reason:   "purchase",
			Comment:  input.Comment,
		}

		if err := tx.Create(&movement).Error; err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Приход оформлен"})
}

func StockOut(c *gin.Context) {
	var input struct {
		ItemID   uint    `json:"item_id" binding:"required"`
		Quantity float64 `json:"quantity" binding:"required"`
		Comment  string  `json:"comment"`
	}

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

	if input.Quantity <= 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Количество должно быть положительным"})
		return
	}

	err := database.DB.Transaction(func(tx *gorm.DB) error {
		result := tx.Model(&models.Item{}).
			Where("id = ? AND stock >= ?  ", input.ItemID, input.Quantity).
			Update("stock", gorm.Expr("stock - ?", input.Quantity))

		if result.Error != nil {
			return result.Error
		}

		if result.RowsAffected == 0 {
			return fmt.Errorf("товар не найден или не достаточно товара")
		}

		movement := models.StockMovement{
			ItemID:   input.ItemID,
			Type:     "out",
			Quantity: input.Quantity,
			Reason:   "sale",
			Comment:  input.Comment,
		}

		if err := tx.Create(&movement).Error; err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Уход оформлен"})
}

func GetStockMovements(c *gin.Context) {
	itemID := c.Query("item_id")

	var movements []models.StockMovement
	query := database.DB.Preload("Item").Order("created_at desc")

	if itemID != "" {
		query = query.Where("item_id = ?", itemID)
	}

	if err := query.Find(&movements).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Не удалось получить историю"})
		return
	}

	c.JSON(http.StatusOK, movements)
}
