package readlist import ( "fmt" "time" "github.com/google/uuid" "gorm.io/gorm" ) // Service handles read later operations type Service struct { db *gorm.DB } // NewService creates a new read later service func NewService(db *gorm.DB) *Service { return &Service{db: db} } // Create adds a new URL to read later func (s *Service) Create(url string) (*ReadLaterItem, error) { item := &ReadLaterItem{ ID: uuid.New().String(), URL: url, CreatedAt: time.Now(), UpdatedAt: time.Now(), } // Parse URL and extract content if err := item.ParseURL(); err != nil { return nil, fmt.Errorf("failed to parse URL: %w", err) } if err := s.db.Create(item).Error; err != nil { return nil, fmt.Errorf("failed to create read later item: %w", err) } return item, nil } // Get retrieves a read later item by ID func (s *Service) Get(id string) (*ReadLaterItem, error) { var item ReadLaterItem if err := s.db.First(&item, "id = ?", id).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, nil } return nil, fmt.Errorf("failed to get read later item: %w", err) } return &item, nil } // List retrieves all read later items func (s *Service) List(includeArchived bool) ([]ReadLaterItem, error) { var items []ReadLaterItem query := s.db.Order("created_at desc") if !includeArchived { query = query.Where("archived_at IS NULL") } if err := query.Find(&items).Error; err != nil { return nil, fmt.Errorf("failed to list read later items: %w", err) } return items, nil } // MarkRead marks an item as read func (s *Service) MarkRead(id string) error { now := time.Now() if err := s.db.Model(&ReadLaterItem{}). Where("id = ?", id). Updates(map[string]interface{}{ "read_at": &now, "updated_at": now, }).Error; err != nil { return fmt.Errorf("failed to mark item as read: %w", err) } return nil } // Archive marks an item as archived func (s *Service) Archive(id string) error { now := time.Now() if err := s.db.Model(&ReadLaterItem{}). Where("id = ?", id). Updates(map[string]interface{}{ "archived_at": &now, "updated_at": now, }).Error; err != nil { return fmt.Errorf("failed to archive item: %w", err) } return nil } // Unarchive removes the archived status from an item func (s *Service) Unarchive(id string) error { now := time.Now() if err := s.db.Model(&ReadLaterItem{}). Where("id = ?", id). Updates(map[string]interface{}{ "archived_at": nil, "updated_at": now, }).Error; err != nil { return fmt.Errorf("failed to unarchive item: %w", err) } return nil } // Delete removes a read later item func (s *Service) Delete(id string) error { if err := s.db.Delete(&ReadLaterItem{}, "id = ?", id).Error; err != nil { return fmt.Errorf("failed to delete read later item: %w", err) } return nil } // Reset deletes all read later items (for testing) func (s *Service) Reset() error { if err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&ReadLaterItem{}).Error; err != nil { return fmt.Errorf("failed to reset read later items: %w", err) } return nil }