package controllers

import (
	"catalogue.midpdsa.com/src/db/catalogue"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"

	"github.com/jackc/pgx/v5/pgtype"
)

type BrakeStockController struct {
	queries *catalogue.Queries
}

func NewBrakeStockController(queries *catalogue.Queries) *BrakeStockController {
	return &BrakeStockController{queries: queries}
}

func (ctrl *BrakeStockController) GetBrakeStocksByBrakekSpec(c *gin.Context) {
	brakeSpecIDStr := c.Param("brake_spec_id")
	brakeSpecID, err := strconv.Atoi(brakeSpecIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid brake spec id"})
		return
	}

	stocks, err := ctrl.queries.GetBrakekStocksByBrakeSpec(c.Request.Context(), pgtype.Int4{Int32: int32(brakeSpecID), Valid: true})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, stocks)
}

func (ctrl *BrakeStockController) GetBrakeStockById(c *gin.Context) {
	brakeStockIDStr := c.Param("id")
	if brakeStockIDStr == "" {
		brakeStockIDStr = c.Param("brake_stock_id")
	}
	brakeStockID, err := strconv.Atoi(brakeStockIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid brake stock id"})
		return
	}

	stock, err := ctrl.queries.GetBrakeStocks(c.Request.Context(), int32(brakeStockID))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "brake stock not found"})
		return
	}
	c.JSON(http.StatusOK, stock)
}

type CreateBrakeStockRequest struct {
	Quantity  int32 `json:"quantity" binding:"required"`
	FkIdBrake int32 `json:"fk_id_brake" binding:"required"`
}

func (ctrl *BrakeStockController) CreateBrakeStock(c *gin.Context) {
	var req CreateBrakeStockRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	stock, err := ctrl.queries.CreateBrakeStock(c.Request.Context(), catalogue.CreateBrakeStockParams{
		Quantity: pgtype.Int4{Int32: req.Quantity, Valid: true},
		FkIdBrake: pgtype.Int4{Int32: req.FkIdBrake, Valid: true},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, stock)
}

func (ctrl *BrakeStockController) ListBrakeStocks(c *gin.Context) {
	limit, offset := parsePagination(c)
	search := parseSearch(c)
	stocks, err := ctrl.queries.ListBrakeStocks(c.Request.Context(), catalogue.ListBrakeStocksParams{Limit: limit, Offset: offset, Search: search})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, stocks)
}

type UpdateBrakeStockRequest struct {
	Quantity  int32 `json:"quantity" binding:"required"`
	FkIdBrake int32 `json:"fk_id_brake"`
}

func (ctrl *BrakeStockController) UpdateBrakeStock(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid brake stock id"})
		return
	}

	var req UpdateBrakeStockRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	stock, err := ctrl.queries.UpdateBrakeStock(c.Request.Context(), catalogue.UpdateBrakeStockParams{
		ID:       int32(id),
		Quantity: pgtype.Int4{Int32: req.Quantity, Valid: true},
		FkIdBrake: pgtype.Int4{Int32: req.FkIdBrake, Valid: req.FkIdBrake != 0},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, stock)
}

func (ctrl *BrakeStockController) DeleteBrakeStock(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid brake stock id"})
		return
	}

	if _, err := ctrl.queries.DeleteBrakeStock(c.Request.Context(), int32(id)); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "brake stock deleted"})
}
