// internal/repositories/category_repo.go
package repositories

import (
	"errors"
	"lost-and-found/internal/models"

	"gorm.io/gorm"
)

type CategoryRepository struct {
	db *gorm.DB
}

func NewCategoryRepository(db *gorm.DB) *CategoryRepository {
	return &CategoryRepository{db: db}
}

// Create creates a new category
func (r *CategoryRepository) Create(category *models.Category) error {
	return r.db.Create(category).Error
}

// FindByID finds category by ID
func (r *CategoryRepository) FindByID(id uint) (*models.Category, error) {
	var category models.Category
	err := r.db.First(&category, id).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("category not found")
		}
		return nil, err
	}
	return &category, nil
}

// FindBySlug finds category by slug
func (r *CategoryRepository) FindBySlug(slug string) (*models.Category, error) {
	var category models.Category
	err := r.db.Where("slug = ?", slug).First(&category).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("category not found")
		}
		return nil, err
	}
	return &category, nil
}

// FindAll returns all categories
func (r *CategoryRepository) FindAll() ([]models.Category, error) {
	var categories []models.Category
	err := r.db.Order("name ASC").Find(&categories).Error
	return categories, err
}

// Update updates category data
func (r *CategoryRepository) Update(category *models.Category) error {
	return r.db.Save(category).Error
}

// Delete soft deletes a category
func (r *CategoryRepository) Delete(id uint) error {
	return r.db.Delete(&models.Category{}, id).Error
}

// GetCategoryWithItemCount gets category with item count
func (r *CategoryRepository) GetCategoryWithItemCount(id uint) (*models.Category, int64, error) {
	category, err := r.FindByID(id)
	if err != nil {
		return nil, 0, err
	}

	var count int64
	if err := r.db.Model(&models.Item{}).Where("category_id = ?", id).Count(&count).Error; err != nil {
		return nil, 0, err
	}

	return category, count, nil
}

// GetAllWithItemCount gets all categories with item counts
func (r *CategoryRepository) GetAllWithItemCount() ([]models.CategoryResponse, error) {
	var categories []models.Category
	if err := r.db.Order("name ASC").Find(&categories).Error; err != nil {
		return nil, err
	}

	var responses []models.CategoryResponse
	for _, cat := range categories {
		var count int64
		if err := r.db.Model(&models.Item{}).Where("category_id = ?", cat.ID).Count(&count).Error; err != nil {
			return nil, err
		}

		response := cat.ToResponse()
		response.ItemCount = count
		responses = append(responses, response)
	}

	return responses, nil
}