package controllers

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

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

type VehicleModelYearController struct {
	queries *catalogue.Queries
}

func NewVehicleModelYearController(queries *catalogue.Queries) *VehicleModelYearController {
	return &VehicleModelYearController{queries: queries}
}

func (ctrl *VehicleModelYearController) GetVehicleModelYearsByBrand(c *gin.Context) {
	brandIDStr := c.Param("brand_id")
	brandID, err := strconv.Atoi(brandIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid brand id"})
		return
	}

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

func (ctrl *VehicleModelYearController) GetVehicleModelYearsByType(c *gin.Context) {
	typeIDStr := c.Param("type_id")
	typeID, err := strconv.Atoi(typeIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid type id"})
		return
	}

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

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

type CreateVehicleModelYearRequest struct {
	Model             string `json:"model" binding:"required"`
	FkIdVehicleBrand int32  `json:"fk_id_vehicle_brand"`
	FkIdVehicleType  int32  `json:"fk_id_vehicle_type"`
}

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

	year, err := ctrl.queries.CreateVehicleModelYear(c.Request.Context(), catalogue.CreateVehicleModelYearParams{
		Model:            pgtype.Text{String: req.Model, Valid: true},
		FkIdVehicleBrand: pgtype.Int4{Int32: req.FkIdVehicleBrand, Valid: req.FkIdVehicleBrand != 0},
		FkIdVehicleType:  pgtype.Int4{Int32: req.FkIdVehicleType, Valid: req.FkIdVehicleType != 0},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusCreated, year)
}

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

	year, err := ctrl.queries.GetVehicleModelYearById(c.Request.Context(), int32(id))
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "vehicle model year not found"})
		return
	}
	c.JSON(http.StatusOK, year)
}

type UpdateVehicleModelYearRequest struct {
	Model            string `json:"model" binding:"required"`
	FkIdVehicleBrand int32  `json:"fk_id_vehicle_brand"`
	FkIdVehicleType  int32  `json:"fk_id_vehicle_type"`
}

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

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

	year, err := ctrl.queries.UpdateVehicleModelYear(c.Request.Context(), catalogue.UpdateVehicleModelYearParams{
		ID:              int32(id),
		Model:           pgtype.Text{String: req.Model, Valid: true},
		FkIdVehicleBrand: pgtype.Int4{Int32: req.FkIdVehicleBrand, Valid: req.FkIdVehicleBrand != 0},
		FkIdVehicleType:  pgtype.Int4{Int32: req.FkIdVehicleType, Valid: req.FkIdVehicleType != 0},
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, year)
}

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

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