package service import ( "context" "errors" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/repository" applogger "github.com/gochat/gochat/pkg/logger" ) // DraftMessageService implements business logic for DraftMessage operations. // Reference: Chatwoot app/controllers/api/v1/conversations/draft_messages_controller.rb type DraftMessageService struct { repo *repository.DraftMessageRepo conversationRepo *repository.ConversationRepo } // NewDraftMessageService creates a new DraftMessage service. func NewDraftMessageService(repo *repository.DraftMessageRepo, conversationRepo *repository.ConversationRepo) *DraftMessageService { return &DraftMessageService{repo: repo, conversationRepo: conversationRepo} } // Ready reports whether the service has its repository configured. func (s *DraftMessageService) Ready() bool { return s != nil && s.repo != nil } // List retrieves all draft messages for a conversation, optionally filtered by user. func (s *DraftMessageService) List(ctx context.Context, accountID, conversationID, userID uint) ([]model.DraftMessage, error) { // Verify conversation belongs to the account if _, err := s.conversationRepo.FindByAccountAndID(ctx, accountID, conversationID); err != nil { return nil, err } return s.repo.FindByConversationID(ctx, conversationID, userID) } // Create creates a new draft message. func (s *DraftMessageService) Create(ctx context.Context, accountID, conversationID, userID uint, content string) (*model.DraftMessage, error) { // Verify conversation belongs to the account if _, err := s.conversationRepo.FindByAccountAndID(ctx, accountID, conversationID); err != nil { return nil, err } draft := &model.DraftMessage{ ConversationID: conversationID, UserID: userID, Content: content, } if err := s.repo.Create(ctx, draft); err != nil { applogger.L().Errorf("Failed to create draft message for conversation %d: %v", conversationID, err) return nil, err } return draft, nil } // Get retrieves a draft message by ID. func (s *DraftMessageService) Get(ctx context.Context, id uint) (*model.DraftMessage, error) { return s.repo.FindByID(ctx, id) } // Update updates an existing draft message. func (s *DraftMessageService) Update(ctx context.Context, id uint, content string) (*model.DraftMessage, error) { draft, err := s.repo.FindByID(ctx, id) if err != nil { return nil, err } draft.Content = content if err := s.repo.Update(ctx, draft); err != nil { applogger.L().Errorf("Failed to update draft message %d: %v", id, err) return nil, err } return draft, nil } // Delete deletes a draft message. func (s *DraftMessageService) Delete(ctx context.Context, id uint) error { // Verify draft exists before deleting draft, err := s.repo.FindByID(ctx, id) if err != nil { applogger.L().Errorf("Draft message %d not found for deletion: %v", id, err) return err } if draft == nil { return errors.New("draft message not found") } if err := s.repo.Delete(ctx, id); err != nil { applogger.L().Errorf("Failed to delete draft message %d: %v", id, err) return err } return nil } // Search searches draft messages by content for an account using LIKE query. func (s *DraftMessageService) Search(ctx context.Context, accountID uint, query string) ([]model.DraftMessage, error) { if query == "" { return nil, errors.New("search query must not be empty") } return s.repo.SearchByContent(ctx, accountID, query) } // Count returns the total number of draft messages for an account. func (s *DraftMessageService) Count(ctx context.Context, accountID uint) (int64, error) { return s.repo.CountByAccount(ctx, accountID) }