package controllers

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

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

type StrutBrandSpecsController struct {
	queries *catalogue.Queries
}

func NewStrutBrandSpecsController(queries *catalogue.Queries) *StrutBrandSpecsController {
	return &StrutBrandSpecsController{queries: queries}
}

func (ctrl *StrutBrandSpecsController) GetStrutBrandSpecsByVehicleModelYear(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.GetStrutBrandSpecsByVehicleModelYear(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 *StrutBrandSpecsController) GetStrutBrandSpecsById(c *gin.Context) {
	specIDStr := c.Param("id")
	specID, err := strconv.Atoi(specIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid spec id"})
		return
	}

	spec, err := ctrl.queries.GetStrutBrandSpecsById(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 CreateStrutBrandSpecRequest 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"`
	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"`
	FkIdStrutBrand        int32  `json:"fk_id_strut_brand"`
}

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

	spec, err := ctrl.queries.CreateStrutBrandSpec(c.Request.Context(), catalogue.CreateStrutBrandSpecParams{
		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 != ""},
		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},
		FkIdStrutBrand:       pgtype.Int4{Int32: req.FkIdStrutBrand, Valid: req.FkIdStrutBrand > 0},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, spec)
}

func (ctrl *StrutBrandSpecsController) ListStrutBrandSpecs(c *gin.Context) {
	limit, offset := parsePagination(c)
	search := parseSearch(c)
	specs, err := ctrl.queries.ListStrutBrandSpecs(c.Request.Context(), catalogue.ListStrutBrandSpecsParams{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 UpdateStrutBrandSpecRequest 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"`
	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"`
	FkIdStrutBrand        int32  `json:"fk_id_strut_brand"`
	Years                 string `json:"years"`
	YearsRange            string `json:"years_range"`
}

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

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

	spec, err := ctrl.queries.UpdateStrutBrandSpec(c.Request.Context(), catalogue.UpdateStrutBrandSpecParams{
		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 != ""},
		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},
		FkIdStrutBrand:       pgtype.Int4{Int32: req.FkIdStrutBrand, Valid: req.FkIdStrutBrand != 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 *StrutBrandSpecsController) DeleteStrutBrandSpec(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid spec id"})
		return
	}

	if _, err := ctrl.queries.DeleteStrutBrandSpec(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"})
}
