package handlers

import (
	"strconv"

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

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

type BindingHandler struct {
	bindingRepo  *repository.BindingRepository
	materialRepo *repository.MaterialRepository
}

func NewBindingHandler(bindingRepo *repository.BindingRepository, materialRepo *repository.MaterialRepository) *BindingHandler {
	return &BindingHandler{
		bindingRepo:  bindingRepo,
		materialRepo: materialRepo,
	}
}

// BindMaterial 绑定材质到多个group_id
// POST /api/v1/materials/:id/bindings
// Body: {"group_ids": ["g1", "g2", "g3"]}
func (h *BindingHandler) BindMaterial(c *gin.Context) {
	materialID, err := strconv.ParseInt(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "invalid material id")
		return
	}

	// 检查材质是否存在
	exists, err := h.materialRepo.Exists(materialID)
	if err != nil {
		response.InternalError(c, "failed to check material")
		return
	}
	if !exists {
		response.NotFound(c, "material not found")
		return
	}

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

	if err := h.bindingRepo.BindMaterial(materialID, req.GroupIDs); err != nil {
		response.InternalError(c, "failed to bind material")
		return
	}

	response.Success(c, gin.H{
		"material_id": materialID,
		"group_ids":   req.GroupIDs,
	})
}

// UnbindMaterial 解绑材质与指定group_id
// DELETE /api/v1/materials/:id/bindings
// Body: {"group_ids": ["g1", "g2"]}
func (h *BindingHandler) UnbindMaterial(c *gin.Context) {
	materialID, err := strconv.ParseInt(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "invalid material id")
		return
	}

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

	if err := h.bindingRepo.UnbindMaterial(materialID, req.GroupIDs); err != nil {
		response.InternalError(c, "failed to unbind material")
		return
	}

	response.Success(c, gin.H{
		"material_id": materialID,
		"unbound":     req.GroupIDs,
	})
}

// GetGroupsByMaterial 获取材质关联的所有group_id (分页版本)
// GET /api/v1/materials/:id/groups?page=1&page_size=20
func (h *BindingHandler) GetGroupsByMaterial(c *gin.Context) {
	materialID, err := strconv.ParseInt(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "invalid material id")
		return
	}

	// 解析分页参数
	var query models.GroupListQuery
	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
	}

	// 检查材质是否存在
	exists, err := h.materialRepo.Exists(materialID)
	if err != nil {
		response.InternalError(c, "failed to check material")
		return
	}
	if !exists {
		response.NotFound(c, "material not found")
		return
	}

	groupIDs, total, err := h.bindingRepo.GetGroupsByMaterialID(materialID, query.Page, query.PageSize)
	if err != nil {
		response.InternalError(c, "failed to get groups")
		return
	}

	// 返回分页格式
	response.Success(c, models.GroupListResponse{
		Items:    groupIDs,
		Total:    total,
		Page:     query.Page,
		PageSize: query.PageSize,
	})
}

// GetMaterialsByGroups 根据多个group_id获取关联的材质
// POST /api/v1/groups/materials
// Body: {"group_ids": ["g1", "g2", "g3"]}
func (h *BindingHandler) GetMaterialsByGroups(c *gin.Context) {
	var req models.GroupMaterialsRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "invalid request body: "+err.Error())
		return
	}

	results, err := h.bindingRepo.GetMaterialsByGroupIDs(req.GroupIDs)
	if err != nil {
		response.InternalError(c, "failed to get materials")
		return
	}

	response.Success(c, results)
}
