package handlers

import (
	"errors"
	"strconv"

	"material_texture/internal/models"
	"material_texture/internal/repository"
	"material_texture/pkg/response"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type MaterialHandler struct {
	repo *repository.MaterialRepository
}

func NewMaterialHandler(repo *repository.MaterialRepository) *MaterialHandler {
	return &MaterialHandler{repo: repo}
}

// List 获取材质列表
// GET /api/v1/materials?page=1&page_size=20&name=xxx
func (h *MaterialHandler) List(c *gin.Context) {
	var query models.MaterialListQuery
	if err := c.ShouldBindQuery(&query); err != nil {
		response.BadRequest(c, "invalid query parameters")
		return
	}

	// 设置默认值
	if query.Page < 1 {
		query.Page = 1
	}
	if query.PageSize < 1 || query.PageSize > 100 {
		query.PageSize = 20
	}

	materials, total, err := h.repo.List(query)
	if err != nil {
		response.InternalError(c, "failed to fetch materials")
		return
	}

	response.SuccessPaged(c, materials, total, query.Page, query.PageSize)
}

// GetByID 获取单个材质详情
// GET /api/v1/materials/:id
func (h *MaterialHandler) GetByID(c *gin.Context) {
	id, err := strconv.ParseInt(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "invalid material id")
		return
	}

	material, err := h.repo.GetByID(id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			response.NotFound(c, "material not found")
			return
		}
		response.InternalError(c, "failed to fetch material")
		return
	}

	response.Success(c, material)
}

// Create 创建材质
// POST /api/v1/materials
func (h *MaterialHandler) Create(c *gin.Context) {
	var req models.MaterialRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "invalid request body: "+err.Error())
		return
	}

	material := &models.Material{
		Name:        req.Name,
		DiffuseR:    req.DiffuseR,
		DiffuseG:    req.DiffuseG,
		DiffuseB:    req.DiffuseB,
		Alpha:       req.Alpha,
		Shininess:   req.Shininess,
		SpecularR:   req.SpecularR,
		SpecularG:   req.SpecularG,
		SpecularB:   req.SpecularB,
		AmbientR:    req.AmbientR,
		AmbientG:    req.AmbientG,
		AmbientB:    req.AmbientB,
		Metallic:    req.Metallic,
		Roughness:   req.Roughness,
		Reflectance: req.Reflectance,
	}

	if err := h.repo.Create(material); err != nil {
		response.InternalError(c, "failed to create material")
		return
	}

	response.Created(c, material)
}

// Update 更新材质 (优化: 单次查询)
// PUT /api/v1/materials/:id
func (h *MaterialHandler) Update(c *gin.Context) {
	id, err := strconv.ParseInt(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "invalid material id")
		return
	}

	var req models.MaterialRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "invalid request body: "+err.Error())
		return
	}

	// 直接更新，通过 RowsAffected 判断是否存在
	updates := map[string]interface{}{
		"name":        req.Name,
		"diffuse_r":   req.DiffuseR,
		"diffuse_g":   req.DiffuseG,
		"diffuse_b":   req.DiffuseB,
		"alpha":       req.Alpha,
		"shininess":   req.Shininess,
		"specular_r":  req.SpecularR,
		"specular_g":  req.SpecularG,
		"specular_b":  req.SpecularB,
		"ambient_r":   req.AmbientR,
		"ambient_g":   req.AmbientG,
		"ambient_b":   req.AmbientB,
		"metallic":    req.Metallic,
		"roughness":   req.Roughness,
		"reflectance": req.Reflectance,
	}

	rowsAffected, err := h.repo.UpdateByID(id, updates)
	if err != nil {
		response.InternalError(c, "failed to update material")
		return
	}

	if rowsAffected == 0 {
		response.NotFound(c, "material not found")
		return
	}

	// 返回更新后的数据
	material, _ := h.repo.GetByID(id)
	response.Success(c, material)
}

// Delete 删除材质 (优化: 单次查询，通过 RowsAffected 判断)
// DELETE /api/v1/materials/:id
func (h *MaterialHandler) Delete(c *gin.Context) {
	id, err := strconv.ParseInt(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "invalid material id")
		return
	}

	// 直接删除，通过 RowsAffected 判断是否存在
	rowsAffected, err := h.repo.DeleteByID(id)
	if err != nil {
		response.InternalError(c, "failed to delete material")
		return
	}

	if rowsAffected == 0 {
		response.NotFound(c, "material not found")
		return
	}

	response.Success(c, gin.H{"id": id})
}
