package repository

import (
	"material_texture/internal/models"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type BindingRepository struct {
	db *gorm.DB
}

func NewBindingRepository(db *gorm.DB) *BindingRepository {
	return &BindingRepository{db: db}
}

// BindMaterial 绑定材质到多个group_id（幂等操作，使用upsert）
// 优化: 分批处理，避免单条 SQL 过大
func (r *BindingRepository) BindMaterial(materialID int64, groupIDs []string) error {
	const batchSize = 1000 // 每批最多 1000 条

	for i := 0; i < len(groupIDs); i += batchSize {
		end := i + batchSize
		if end > len(groupIDs) {
			end = len(groupIDs)
		}

		batch := groupIDs[i:end]
		bindings := make([]models.MaterialBinding, len(batch))
		for j, groupID := range batch {
			bindings[j] = models.MaterialBinding{
				MaterialID: materialID,
				GroupID:    groupID,
			}
		}

		// 使用 ON CONFLICT DO NOTHING 实现幂等
		if err := r.db.Clauses(clause.OnConflict{
			Columns:   []clause.Column{{Name: "material_id"}, {Name: "group_id"}},
			DoNothing: true,
		}).Create(&bindings).Error; err != nil {
			return err
		}
	}

	return nil
}

// UnbindMaterial 解绑材质与指定的group_id
func (r *BindingRepository) UnbindMaterial(materialID int64, groupIDs []string) error {
	return r.db.Where("material_id = ? AND group_id IN ?", materialID, groupIDs).
		Delete(&models.MaterialBinding{}).Error
}

// GetGroupsByMaterialID 根据材质ID获取所有关联的group_id (分页版本)
func (r *BindingRepository) GetGroupsByMaterialID(materialID int64, page, pageSize int) ([]string, int64, error) {
	var groupIDs []string
	var total int64

	db := r.db.Model(&models.MaterialBinding{}).Where("material_id = ?", materialID)

	// 获取总数
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	offset := (page - 1) * pageSize
	err := db.Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Pluck("group_id", &groupIDs).Error

	return groupIDs, total, err
}

// GetMaterialsByGroupIDs 根据多个group_id获取关联的材质（含材质详情）
func (r *BindingRepository) GetMaterialsByGroupIDs(groupIDs []string) ([]models.GroupMaterialResult, error) {
	var bindings []models.MaterialBinding

	err := r.db.Preload("Material").
		Where("group_id IN ?", groupIDs).
		Find(&bindings).Error
	if err != nil {
		return nil, err
	}

	results := make([]models.GroupMaterialResult, len(bindings))
	for i, binding := range bindings {
		results[i] = models.GroupMaterialResult{
			GroupID:  binding.GroupID,
			Material: binding.Material,
		}
	}

	return results, nil
}

// DeleteByMaterialID 删除材质的所有绑定（材质删除时级联调用）
func (r *BindingRepository) DeleteByMaterialID(materialID int64) error {
	return r.db.Where("material_id = ?", materialID).
		Delete(&models.MaterialBinding{}).Error
}
