package controllers

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

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

type ShockBrandSpecsController struct {
	queries *catalogue.Queries
}

func NewShockBrandSpecsController(queries *catalogue.Queries) *ShockBrandSpecsController {
	return &ShockBrandSpecsController{queries: queries}
}

func (ctrl *ShockBrandSpecsController) GetShockBrandSpecsByVehicleModelYear(c *gin.Context) {
	modelYearIDStr := c.Param("model_year_id")
	modelYearID, err := strconv.Atoi(modelYearIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid model year id"})
		return
	}

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

func (ctrl *ShockBrandSpecsController) GetShockBrandSpecsById(c *gin.Context) {
	specIDStr := c.Param("id")
	if specIDStr == "" {
		specIDStr = c.Param("spec_id")
	}
	specID, err := strconv.Atoi(specIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid spec id"})
		return
	}

	spec, err := ctrl.queries.GetShockBrandSpecsById(c.Request.Context(), int32(specID))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "specification not found"})
		return
	}
	c.JSON(http.StatusOK, spec)
}

type CreateShockBrandSpecRequest struct {
	PartNumber            string `json:"part_number"`
	Product               string `json:"product"`
	Serie                 string `json:"serie"`
	Quantity              int16  `json:"quantity"`
	Tier                  string `json:"tier"`
	Position              string `json:"position"`
	Accesories           string `json:"accesories"`
	ExtendedLong         int32  `json:"extended_long"`
	CompressedLong      int32  `json:"compressed_long"`
	Extension            int32  `json:"extension"`
	SuperiorMount         string `json:"superior_mount"`
	InferiorMount         string `json:"inferior_mount"`
	ImageProduct         string `json:"image_product"`
	VehicleAttrs        string `json:"vehicle_attrs"`
	Notes                string `json:"notes"`
	TechnicalSheet      string `json:"technical_sheet"`
	FkIdVehicleModelYear int32 `json:"fk_id_vehicle_model_year"`
	FkIdShockBrand      int32 `json:"fk_id_shock_brand"`
}

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

	spec, err := ctrl.queries.CreateShockBrandSpec(c.Request.Context(), catalogue.CreateShockBrandSpecParams{
		PartNumber:            pgtype.Text{String: req.PartNumber, Valid: req.PartNumber != ""},
		Product:               pgtype.Text{String: req.Product, Valid: req.Product != ""},
		Serie:                 pgtype.Text{String: req.Serie, Valid: req.Serie != ""},
		Quantity:             pgtype.Int2{Int16: int16(req.Quantity), Valid: req.Quantity != 0},
		Tier:                  pgtype.Text{String: req.Tier, Valid: req.Tier != ""},
		Position:              pgtype.Text{String: req.Position, Valid: req.Position != ""},
		Accesories:           pgtype.Text{String: req.Accesories, Valid: req.Accesories != ""},
		ExtendedLong:         pgtype.Int4{Int32: req.ExtendedLong, Valid: req.ExtendedLong != 0},
		CompressedLong:      pgtype.Int4{Int32: req.CompressedLong, Valid: req.CompressedLong != 0},
		Extension:            pgtype.Int4{Int32: req.Extension, Valid: req.Extension != 0},
		SuperiorMount:        pgtype.Text{String: req.SuperiorMount, Valid: req.SuperiorMount != ""},
		InferiorMount:        pgtype.Text{String: req.InferiorMount, Valid: req.InferiorMount != ""},
		ImageProduct:        pgtype.Text{String: req.ImageProduct, Valid: req.ImageProduct != ""},
		VehicleAttrs:        pgtype.Text{String: req.VehicleAttrs, Valid: req.VehicleAttrs != ""},
		Notes:                pgtype.Text{String: req.Notes, Valid: req.Notes != ""},
		TechnicalSheet:       pgtype.Text{String: req.TechnicalSheet, Valid: req.TechnicalSheet != ""},
		FkIdVehicleModelYear:  pgtype.Int4{Int32: req.FkIdVehicleModelYear, Valid: req.FkIdVehicleModelYear != 0},
		FkIdShockBrand:       pgtype.Int4{Int32: req.FkIdShockBrand, Valid: req.FkIdShockBrand != 0},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, spec)
}

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

type UpdateShockBrandSpecRequest struct {
	PartNumber            string `json:"part_number"`
	Product               string `json:"product"`
	Serie                 string `json:"serie"`
	Quantity              int16  `json:"quantity"`
	Tier                  string `json:"tier"`
	Position              string `json:"position"`
	Accesories            string `json:"accesories"`
	ExtendedLong          int32  `json:"extended_long"`
	CompressedLong        int32  `json:"compressed_long"`
	Extension             int32  `json:"extension"`
	SuperiorMount         string `json:"superior_mount"`
	InferiorMount         string `json:"inferior_mount"`
	ImageProduct          string `json:"image_product"`
	VehicleAttrs          string `json:"vehicle_attrs"`
	Notes                 string `json:"notes"`
	TechnicalSheet        string `json:"technical_sheet"`
	FkIdVehicleModelYear  int32  `json:"fk_id_vehicle_model_year"`
	FkIdShockBrand        int32  `json:"fk_id_shock_brand"`
	Years                 string `json:"years"`
	YearsRange            string `json:"years_range"`
}

func (ctrl *ShockBrandSpecsController) UpdateShockBrandSpec(c *gin.Context) {
	idStr := c.Param("id")
	if idStr == "" {
		idStr = c.Param("spec_id")
	}
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid spec id"})
		return
	}

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

	spec, err := ctrl.queries.UpdateShockBrandSpec(c.Request.Context(), catalogue.UpdateShockBrandSpecParams{
		ID:                   int32(id),
		PartNumber:           pgtype.Text{String: req.PartNumber, Valid: req.PartNumber != ""},
		Product:              pgtype.Text{String: req.Product, Valid: req.Product != ""},
		Serie:                pgtype.Text{String: req.Serie, Valid: req.Serie != ""},
		Quantity:             pgtype.Int2{Int16: req.Quantity, Valid: req.Quantity != 0},
		Tier:                 pgtype.Text{String: req.Tier, Valid: req.Tier != ""},
		Position:             pgtype.Text{String: req.Position, Valid: req.Position != ""},
		Accesories:           pgtype.Text{String: req.Accesories, Valid: req.Accesories != ""},
		ExtendedLong:         pgtype.Int4{Int32: req.ExtendedLong, Valid: req.ExtendedLong != 0},
		CompressedLong:       pgtype.Int4{Int32: req.CompressedLong, Valid: req.CompressedLong != 0},
		Extension:            pgtype.Int4{Int32: req.Extension, Valid: req.Extension != 0},
		SuperiorMount:        pgtype.Text{String: req.SuperiorMount, Valid: req.SuperiorMount != ""},
		InferiorMount:        pgtype.Text{String: req.InferiorMount, Valid: req.InferiorMount != ""},
		ImageProduct:         pgtype.Text{String: req.ImageProduct, Valid: req.ImageProduct != ""},
		VehicleAttrs:         pgtype.Text{String: req.VehicleAttrs, Valid: req.VehicleAttrs != ""},
		Notes:                pgtype.Text{String: req.Notes, Valid: req.Notes != ""},
		TechnicalSheet:       pgtype.Text{String: req.TechnicalSheet, Valid: req.TechnicalSheet != ""},
		FkIdVehicleModelYear: pgtype.Int4{Int32: req.FkIdVehicleModelYear, Valid: req.FkIdVehicleModelYear != 0},
		FkIdShockBrand:       pgtype.Int4{Int32: req.FkIdShockBrand, Valid: req.FkIdShockBrand != 0},
		Years:                pgtype.Text{String: req.Years, Valid: req.Years != ""},
		YearsRange:           pgtype.Text{String: req.YearsRange, Valid: req.YearsRange != ""},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, spec)
}

func (ctrl *ShockBrandSpecsController) DeleteShockBrandSpec(c *gin.Context) {
	idStr := c.Param("id")
	if idStr == "" {
		idStr = c.Param("spec_id")
	}
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid spec id"})
		return
	}

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