package like import ( "context" "errors" "tercul/internal/app/analytics" "tercul/internal/domain" "tercul/internal/platform/log" "github.com/google/uuid" ) // LikeCommands contains the command handlers for the like aggregate. type LikeCommands struct { repo domain.LikeRepository analyticsSvc analytics.Service } // NewLikeCommands creates a new LikeCommands handler. func NewLikeCommands(repo domain.LikeRepository, analyticsSvc analytics.Service) *LikeCommands { return &LikeCommands{ repo: repo, analyticsSvc: analyticsSvc, } } // CreateLikeInput represents the input for creating a new like. type CreateLikeInput struct { UserID uuid.UUID WorkID *uuid.UUID TranslationID *uuid.UUID CommentID *uuid.UUID } // CreateLike creates a new like and increments the relevant counter. func (c *LikeCommands) CreateLike(ctx context.Context, input CreateLikeInput) (*domain.Like, error) { like := &domain.Like{ UserID: input.UserID, WorkID: input.WorkID, TranslationID: input.TranslationID, CommentID: input.CommentID, } err := c.repo.Create(ctx, like) if err != nil { return nil, err } // After creating the like, increment the appropriate counter. if c.analyticsSvc != nil { if input.WorkID != nil { go func() { if err := c.analyticsSvc.IncrementWorkLikes(context.Background(), *input.WorkID); err != nil { log.Error(err, "failed to increment work likes") } }() } if input.TranslationID != nil { go func() { if err := c.analyticsSvc.IncrementTranslationLikes(context.Background(), *input.TranslationID); err != nil { log.Error(err, "failed to increment translation likes") } }() } // Assuming there's a counter for comment likes, which is a reasonable feature to add. // if input.CommentID != nil { // go c.analyticsSvc.IncrementCommentLikes(context.Background(), *input.CommentID) // } } return like, nil } // DeleteLike deletes a like by ID and decrements the relevant counter. func (c *LikeCommands) DeleteLike(ctx context.Context, id uuid.UUID) error { // First, get the like to determine what it was attached to. like, err := c.repo.GetByID(ctx, id) if err != nil { // If the like doesn't exist, we can't decrement anything, but we shouldn't fail. // The end result (the like is gone) is the same. if errors.Is(err, domain.ErrEntityNotFound) { return nil } return err } // Now, delete the like. err = c.repo.Delete(ctx, id) if err != nil { return err } // After deleting the like, decrement the appropriate counter in the background. if c.analyticsSvc != nil { if like.WorkID != nil { go func() { if err := c.analyticsSvc.DecrementWorkLikes(context.Background(), *like.WorkID); err != nil { log.Error(err, "failed to decrement work likes") } }() } if like.TranslationID != nil { go func() { if err := c.analyticsSvc.DecrementTranslationLikes(context.Background(), *like.TranslationID); err != nil { log.Error(err, "failed to decrement translation likes") } }() } } return nil }