package repositories

import (
	"strings"

	"gorm.io/gorm"

	"github.com/treytartt/honeydue-api/internal/models"
)

// TaskTemplateRepository handles database operations for task templates
type TaskTemplateRepository struct {
	db *gorm.DB
}

// NewTaskTemplateRepository creates a new task template repository
func NewTaskTemplateRepository(db *gorm.DB) *TaskTemplateRepository {
	return &TaskTemplateRepository{db: db}
}

// GetAll returns all active task templates ordered by category and display order
func (r *TaskTemplateRepository) GetAll() ([]models.TaskTemplate, error) {
	var templates []models.TaskTemplate
	err := r.db.
		Preload("Category").
		Preload("Frequency").
		Where("is_active = ?", true).
		Order("display_order ASC, title ASC").
		Find(&templates).Error
	return templates, err
}

// GetByCategory returns all active templates for a specific category
func (r *TaskTemplateRepository) GetByCategory(categoryID uint) ([]models.TaskTemplate, error) {
	var templates []models.TaskTemplate
	err := r.db.
		Preload("Category").
		Preload("Frequency").
		Where("is_active = ? AND category_id = ?", true, categoryID).
		Order("display_order ASC, title ASC").
		Find(&templates).Error
	return templates, err
}

// Search searches templates by title and tags
func (r *TaskTemplateRepository) Search(query string) ([]models.TaskTemplate, error) {
	var templates []models.TaskTemplate
	escaped := escapeLikeWildcards(strings.ToLower(query))
	searchTerm := "%" + escaped + "%"

	err := r.db.
		Preload("Category").
		Preload("Frequency").
		Where("is_active = ? AND (LOWER(title) LIKE ? OR LOWER(tags) LIKE ?)", true, searchTerm, searchTerm).
		Order("display_order ASC, title ASC").
		Limit(20). // Limit search results
		Find(&templates).Error
	return templates, err
}

// GetByID returns a single template by ID
func (r *TaskTemplateRepository) GetByID(id uint) (*models.TaskTemplate, error) {
	var template models.TaskTemplate
	err := r.db.
		Preload("Category").
		Preload("Frequency").
		First(&template, id).Error
	if err != nil {
		return nil, err
	}
	return &template, nil
}

// Create creates a new task template
func (r *TaskTemplateRepository) Create(template *models.TaskTemplate) error {
	return r.db.Create(template).Error
}

// Update updates an existing task template
func (r *TaskTemplateRepository) Update(template *models.TaskTemplate) error {
	return r.db.Omit("Category", "Frequency").Save(template).Error
}

// Delete hard deletes a task template
func (r *TaskTemplateRepository) Delete(id uint) error {
	return r.db.Delete(&models.TaskTemplate{}, id).Error
}

// GetAllIncludingInactive returns all templates including inactive ones (for admin)
func (r *TaskTemplateRepository) GetAllIncludingInactive() ([]models.TaskTemplate, error) {
	var templates []models.TaskTemplate
	err := r.db.
		Preload("Category").
		Preload("Frequency").
		Order("display_order ASC, title ASC").
		Find(&templates).Error
	return templates, err
}

// Count returns the total count of active templates
func (r *TaskTemplateRepository) Count() (int64, error) {
	var count int64
	err := r.db.Model(&models.TaskTemplate{}).Where("is_active = ?", true).Count(&count).Error
	return count, err
}

// GetGroupedByCategory returns templates grouped by category name
func (r *TaskTemplateRepository) GetGroupedByCategory() (map[string][]models.TaskTemplate, error) {
	templates, err := r.GetAll()
	if err != nil {
		return nil, err
	}

	result := make(map[string][]models.TaskTemplate)
	for _, t := range templates {
		categoryName := "Uncategorized"
		if t.Category != nil {
			categoryName = t.Category.Name
		}
		result[categoryName] = append(result[categoryName], t)
	}

	return result, nil
}
