package service import ( "errors" "fmt" "github.com/simpletodoapp/go-todo-app/internal/dto" "github.com/simpletodoapp/go-todo-app/internal/model" "gorm.io/gorm" ) // TodoService handles todo operations type TodoService struct { db *gorm.DB } // NewTodoService creates a new todo service func NewTodoService(db *gorm.DB) *TodoService { return &TodoService{db: db} } // GetTodos retrieves todos with optional filters and pagination func (s *TodoService) GetTodos(skip, limit int, completed *bool) ([]model.Todo, error) { var todos []model.Todo query := s.db // Apply completed filter if provided if completed != nil { query = query.Where("completed = ?", *completed) } // Apply pagination result := query.Offset(skip).Limit(limit).Find(&todos) if result.Error != nil { return nil, fmt.Errorf("error getting todos: %v", result.Error) } return todos, nil } // GetTodoByID retrieves a specific todo by ID func (s *TodoService) GetTodoByID(id uint) (*model.Todo, error) { var todo model.Todo result := s.db.First(&todo, id) if result.Error != nil { if errors.Is(result.Error, gorm.ErrRecordNotFound) { return nil, nil // Todo not found, but not an error } return nil, fmt.Errorf("error getting todo: %v", result.Error) } return &todo, nil } // CreateTodo creates a new todo func (s *TodoService) CreateTodo(todoCreate dto.TodoCreate) (*model.Todo, error) { todo := model.Todo{ Title: todoCreate.Title, Description: todoCreate.Description, Completed: todoCreate.Completed, } result := s.db.Create(&todo) if result.Error != nil { return nil, fmt.Errorf("error creating todo: %v", result.Error) } return &todo, nil } // UpdateTodo updates an existing todo func (s *TodoService) UpdateTodo(id uint, todoUpdate dto.TodoUpdate) (*model.Todo, error) { // Get existing todo todo, err := s.GetTodoByID(id) if err != nil { return nil, err } if todo == nil { return nil, nil // Not found } // Update fields if provided updates := map[string]interface{}{} if todoUpdate.Title != nil { updates["title"] = *todoUpdate.Title } if todoUpdate.Description != nil { updates["description"] = *todoUpdate.Description } if todoUpdate.Completed != nil { updates["completed"] = *todoUpdate.Completed } // Apply updates result := s.db.Model(&todo).Updates(updates) if result.Error != nil { return nil, fmt.Errorf("error updating todo: %v", result.Error) } // Refresh the todo from database return s.GetTodoByID(id) } // DeleteTodo deletes a todo by ID func (s *TodoService) DeleteTodo(id uint) (bool, error) { // Check if todo exists todo, err := s.GetTodoByID(id) if err != nil { return false, err } if todo == nil { return false, nil // Not found } // Delete the todo result := s.db.Delete(&model.Todo{}, id) if result.Error != nil { return false, fmt.Errorf("error deleting todo: %v", result.Error) } return true, nil }