package repository

import (
	"material_texture/internal/models"

	"gorm.io/gorm"
)

type MaterialRepository struct {
	db *gorm.DB
}

func NewMaterialRepository(db *gorm.DB) *MaterialRepository {
	return &MaterialRepository{db: db}
}

// List 获取材质列表（支持分页和名称搜索）
func (r *MaterialRepository) List(query models.MaterialListQuery) ([]models.Material, int64, error) {
	var materials []models.Material
	var total int64

	db := r.db.Model(&models.Material{})

	// 名称模糊搜索
	if query.Name != "" {
		db = db.Where("name ILIKE ?", "%"+query.Name+"%")
	}

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

	// 分页查询
	offset := (query.Page - 1) * query.PageSize
	if err := db.Order("id DESC").Offset(offset).Limit(query.PageSize).Find(&materials).Error; err != nil {
		return nil, 0, err
	}

	return materials, total, nil
}

// GetByID 根据ID获取单个材质
func (r *MaterialRepository) GetByID(id int64) (*models.Material, error) {
	var material models.Material
	if err := r.db.First(&material, id).Error; err != nil {
		return nil, err
	}
	return &material, nil
}

// Create 创建材质
func (r *MaterialRepository) Create(material *models.Material) error {
	return r.db.Create(material).Error
}

// Update 更新材质 (优化: 直接 UPDATE，返回影响行数)
func (r *MaterialRepository) Update(material *models.Material) error {
	return r.db.Save(material).Error
}

// UpdateByID 根据 ID 直接更新 (优化版本，减少查询)
func (r *MaterialRepository) UpdateByID(id int64, updates map[string]interface{}) (int64, error) {
	result := r.db.Model(&models.Material{}).Where("id = ?", id).Updates(updates)
	return result.RowsAffected, result.Error
}

// UpdateByIDWithVersion 带乐观锁的更新 (防止并发覆盖)
// 只有当 version 匹配时才更新，并自动递增 version
func (r *MaterialRepository) UpdateByIDWithVersion(id int64, version int64, updates map[string]interface{}) (int64, error) {
	// 在更新中自动递增 version
	updates["version"] = gorm.Expr("version + 1")

	result := r.db.Model(&models.Material{}).
		Where("id = ? AND version = ?", id, version).
		Updates(updates)

	return result.RowsAffected, result.Error
}

// Delete 删除材质
func (r *MaterialRepository) Delete(id int64) error {
	return r.db.Delete(&models.Material{}, id).Error
}

// DeleteByID 删除材质并返回影响行数 (优化版本)
func (r *MaterialRepository) DeleteByID(id int64) (int64, error) {
	result := r.db.Delete(&models.Material{}, id)
	return result.RowsAffected, result.Error
}

// Exists 检查材质是否存在
func (r *MaterialRepository) Exists(id int64) (bool, error) {
	var count int64
	if err := r.db.Model(&models.Material{}).Where("id = ?", id).Count(&count).Error; err != nil {
		return false, err
	}
	return count > 0, nil
}
