package controllers

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

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

type DiskStockController struct {
	queries *catalogue.Queries
}

func NewDiskStockController(queries *catalogue.Queries) *DiskStockController {
	return &DiskStockController{queries: queries}
}

func (ctrl *DiskStockController) GetDiskStocksByDiskSpec(c *gin.Context) {
	diskSpecIDStr := c.Param("disk_spec_id")
	diskSpecID, err := strconv.Atoi(diskSpecIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid disk spec id"})
		return
	}

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

func (ctrl *DiskStockController) GetDiskStocks(c *gin.Context) {
	limit, offset := parsePagination(c)
	search := parseSearch(c)
	stocks, err := ctrl.queries.GetDiskStocks(c.Request.Context(), catalogue.GetDiskStocksParams{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 CreateDiskStockRequest struct {
	Quantity  int32 `json:"quantity" binding:"required"`
	FkIdDiskk int32 `json:"fk_id_disk" binding:"required"`
}

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

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

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

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

type UpdateDiskStockRequest struct {
	Quantity  int32 `json:"quantity" binding:"required"`
	FkIdDiskk int32 `json:"fk_id_disk"`
}

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

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

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

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

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