package controllers

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

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

type LegBrandSpecsController struct {
	queries *catalogue.Queries
}

func NewLegBrandSpecsController(queries *catalogue.Queries) *LegBrandSpecsController {
	return &LegBrandSpecsController{queries: queries}
}

func (ctrl *LegBrandSpecsController) GetLegBrandSpecsByVehicleModelYear(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.GetLegBrandSpecsByVehicleModelYear(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 *LegBrandSpecsController) GetLegBrandSpecsById(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.GetLegBrandSpecsById(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 CreateLegBrandSpecRequest 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"`
	FkIdLegBrand         int32  `json:"fk_id_leg_brand"`
}

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

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

func (ctrl *LegBrandSpecsController) ListLegBrandSpecs(c *gin.Context) {
	limit, offset := parsePagination(c)
	search := parseSearch(c)
	specs, err := ctrl.queries.ListLegBrandSpecs(c.Request.Context(), catalogue.ListLegBrandSpecsParams{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 UpdateLegBrandSpecRequest 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"`
	FkIdLegBrand          int32  `json:"fk_id_leg_brand"`
	Years                 string `json:"years"`
	YearsRange            string `json:"years_range"`
}

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

	spec, err := ctrl.queries.UpdateLegBrandSpec(c.Request.Context(), catalogue.UpdateLegBrandSpecParams{
		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},
		FkIdLegBrand:         pgtype.Int4{Int32: req.FkIdLegBrand, Valid: req.FkIdLegBrand != 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 *LegBrandSpecsController) DeleteLegBrandSpec(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.DeleteLegBrandSpec(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"})
}
