package controllers

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

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

type BrakeBrandSpecsController struct {
	queries *catalogue.Queries
}

func NewBrakeBrandSpecsController(queries *catalogue.Queries) *BrakeBrandSpecsController {
	return &BrakeBrandSpecsController{queries: queries}
}

func (ctrl *BrakeBrandSpecsController) GetBrakeBrandSpecsByVehicleModelYear(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.GetBrakeBrandSpecsByVehicleModelYear(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 *BrakeBrandSpecsController) GetBrakeBrandSpecsById(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.GetBrakeBrandSpecsById(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 CreateBrakeBrandSpecRequest struct {
	PartNumber             string `json:"part_number"`
	Product                string `json:"product"`
	Serie                  string `json:"serie"`
	Tier                   string `json:"tier"`
	Quantity               int32  `json:"quantity"`
	Position               string `json:"position"`
	Fmsi                   string `json:"fmsi"`
	IncludesHardware       string `json:"includes_hardware"`
	ImageProduct           string `json:"image_product"`
	VehicleAttrs           string `json:"vehicle_attrs"`
	ImageProductDimentions string `json:"image_product_dimentions"`
	TechnicalSheet         string `json:"technical_sheet"`
	FkIdVehicleModelYear   int32  `json:"fk_id_vehicle_model_year"`
	FkIdBrakeBrand        int32  `json:"fk_id_brake_brand"`
}

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

	spec, err := ctrl.queries.CreateBrakeBrandSpec(c.Request.Context(), catalogue.CreateBrakeBrandSpecParams{
		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 != ""},
		Tier:                  pgtype.Text{String: req.Tier, Valid: req.Tier != ""},
		Quantity:              pgtype.Int4{Int32: req.Quantity, Valid: req.Quantity != 0},
		Position:              pgtype.Text{String: req.Position, Valid: req.Position != ""},
		Fmsi:                  pgtype.Text{String: req.Fmsi, Valid: req.Fmsi != ""},
		IncludesHardware:       pgtype.Text{String: req.IncludesHardware, Valid: req.IncludesHardware != ""},
		ImageProduct:          pgtype.Text{String: req.ImageProduct, Valid: req.ImageProduct != ""},
		VehicleAttrs:          pgtype.Text{String: req.VehicleAttrs, Valid: req.VehicleAttrs != ""},
		ImageProductDimentions:  pgtype.Text{String: req.ImageProductDimentions, Valid: req.ImageProductDimentions != ""},
		TechnicalSheet:        pgtype.Text{String: req.TechnicalSheet, Valid: req.TechnicalSheet != ""},
		FkIdVehicleModelYear:  pgtype.Int4{Int32: req.FkIdVehicleModelYear, Valid: req.FkIdVehicleModelYear != 0},
		FkIdBrakeBrand:        pgtype.Int4{Int32: req.FkIdBrakeBrand, Valid: req.FkIdBrakeBrand != 0},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, spec)
}

func (ctrl *BrakeBrandSpecsController) ListBrakeBrandSpecs(c *gin.Context) {
	limit, offset := parsePagination(c)
	search := parseSearch(c)
	specs, err := ctrl.queries.ListBrakeBrandSpecs(c.Request.Context(), catalogue.ListBrakeBrandSpecsParams{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 UpdateBrakeBrandSpecRequest struct {
	PartNumber             string `json:"part_number"`
	Product                string `json:"product"`
	Serie                  string `json:"serie"`
	Tier                   string `json:"tier"`
	Quantity               int32  `json:"quantity"`
	Position               string `json:"position"`
	Fmsi                   string `json:"fmsi"`
	IncludesHardware       string `json:"includes_hardware"`
	ImageProduct           string `json:"image_product"`
	VehicleAttrs           string `json:"vehicle_attrs"`
	ImageProductDimentions string `json:"image_product_dimentions"`
	TechnicalSheet         string `json:"technical_sheet"`
	FkIdVehicleModelYear   int32  `json:"fk_id_vehicle_model_year"`
	FkIdBrakeBrand         int32  `json:"fk_id_brake_brand"`
	Years                  string `json:"years"`
	YearsRange             string `json:"years_range"`
}

func (ctrl *BrakeBrandSpecsController) UpdateBrakeBrandSpec(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 UpdateBrakeBrandSpecRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	spec, err := ctrl.queries.UpdateBrakeBrandSpec(c.Request.Context(), catalogue.UpdateBrakeBrandSpecParams{
		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 != ""},
		Tier:                   pgtype.Text{String: req.Tier, Valid: req.Tier != ""},
		Quantity:               pgtype.Int4{Int32: req.Quantity, Valid: req.Quantity != 0},
		Position:               pgtype.Text{String: req.Position, Valid: req.Position != ""},
		Fmsi:                   pgtype.Text{String: req.Fmsi, Valid: req.Fmsi != ""},
		IncludesHardware:       pgtype.Text{String: req.IncludesHardware, Valid: req.IncludesHardware != ""},
		ImageProduct:           pgtype.Text{String: req.ImageProduct, Valid: req.ImageProduct != ""},
		VehicleAttrs:           pgtype.Text{String: req.VehicleAttrs, Valid: req.VehicleAttrs != ""},
		ImageProductDimentions: pgtype.Text{String: req.ImageProductDimentions, Valid: req.ImageProductDimentions != ""},
		TechnicalSheet:         pgtype.Text{String: req.TechnicalSheet, Valid: req.TechnicalSheet != ""},
		FkIdVehicleModelYear:   pgtype.Int4{Int32: req.FkIdVehicleModelYear, Valid: req.FkIdVehicleModelYear != 0},
		FkIdBrakeBrand:         pgtype.Int4{Int32: req.FkIdBrakeBrand, Valid: req.FkIdBrakeBrand != 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 *BrakeBrandSpecsController) DeleteBrakeBrandSpec(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.DeleteBrakeBrandSpec(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"})
}
