package controllers

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

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

type DiskBrandSpecsController struct {
	queries *catalogue.Queries
}

func NewDiskBrandSpecsController(queries *catalogue.Queries) *DiskBrandSpecsController {
	return &DiskBrandSpecsController{queries: queries}
}

func (ctrl *DiskBrandSpecsController) GetDiskBrandSpecsByVehicleModelYear(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.GetDiskBrandSpecsByVehicleModelYear(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 *DiskBrandSpecsController) GetDiskBrandSpecsById(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.GetDiskBrandSpecsById(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 CreateDiskBrandSpecRequest 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"`
	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"`
	FkIdDiskBrand          int32  `json:"fk_id_disk_brand"`
}

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

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

func (ctrl *DiskBrandSpecsController) ListDiskBrandSpecs(c *gin.Context) {
	limit, offset := parsePagination(c)
	search := parseSearch(c)
	specs, err := ctrl.queries.ListDiskBrandSpecs(c.Request.Context(), catalogue.ListDiskBrandSpecsParams{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 UpdateDiskBrandSpecRequest struct {
	PartNumber             string `json:"part_number"`
	MipPartNumber          string `json:"mip_part_number"`
	Product                string `json:"product"`
	Serie                  string `json:"serie"`
	Tier                   string `json:"tier"`
	Quantity               int32  `json:"quantity"`
	Description            string `json:"description"`
	Type                   string `json:"type"`
	Position               string `json:"position"`
	MinThikness            string `json:"min_thikness"`
	LugNuts                string `json:"lug_nuts"`
	OgDiameter             string `json:"og_diameter"`
	MaxDiameter            string `json:"max_diameter"`
	Materials              string `json:"materials"`
	PiDiameter             string `json:"pi_diameter"`
	Height                 string `json:"height"`
	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"`
	FkIdDiskBrand          int32  `json:"fk_id_disk_brand"`
	Years                  string `json:"years"`
	YearsRange             string `json:"years_range"`
}

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

	spec, err := ctrl.queries.UpdateDiskBrandSpec(c.Request.Context(), catalogue.UpdateDiskBrandSpecParams{
		ID:                     int32(id),
		PartNumber:             pgtype.Text{String: req.PartNumber, Valid: req.PartNumber != ""},
		MipPartNumber:          pgtype.Text{String: req.MipPartNumber, Valid: req.MipPartNumber != ""},
		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},
		Description:            pgtype.Text{String: req.Description, Valid: req.Description != ""},
		Type:                   pgtype.Text{String: req.Type, Valid: req.Type != ""},
		Position:               pgtype.Text{String: req.Position, Valid: req.Position != ""},
		MinThikness:            pgtype.Text{String: req.MinThikness, Valid: req.MinThikness != ""},
		LugNuts:                pgtype.Text{String: req.LugNuts, Valid: req.LugNuts != ""},
		OgDiameter:             pgtype.Text{String: req.OgDiameter, Valid: req.OgDiameter != ""},
		MaxDiameter:            pgtype.Text{String: req.MaxDiameter, Valid: req.MaxDiameter != ""},
		Materials:              pgtype.Text{String: req.Materials, Valid: req.Materials != ""},
		PiDiameter:             pgtype.Text{String: req.PiDiameter, Valid: req.PiDiameter != ""},
		Height:                 pgtype.Text{String: req.Height, Valid: req.Height != ""},
		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},
		FkIdDiskBrand:          pgtype.Int4{Int32: req.FkIdDiskBrand, Valid: req.FkIdDiskBrand != 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 *DiskBrandSpecsController) DeleteDiskBrandSpec(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.DeleteDiskBrandSpec(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"})
}