package like import ( "context" "errors" "tercul/internal/domain" ) // LikeCommands contains the command handlers for the like aggregate. type LikeCommands struct { repo domain.LikeRepository analyticsService AnalyticsService } // AnalyticsService defines the interface for analytics operations. type AnalyticsService interface { IncrementWorkLikes(ctx context.Context, workID uint) error IncrementTranslationLikes(ctx context.Context, translationID uint) error } // NewLikeCommands creates a new LikeCommands handler. func NewLikeCommands(repo domain.LikeRepository, analyticsService AnalyticsService) *LikeCommands { return &LikeCommands{ repo: repo, analyticsService: analyticsService, } } // CreateLikeInput represents the input for creating a new like. type CreateLikeInput struct { UserID uint WorkID *uint TranslationID *uint CommentID *uint } // CreateLike creates a new like. func (c *LikeCommands) CreateLike(ctx context.Context, input CreateLikeInput) (*domain.Like, error) { if input.UserID == 0 { return nil, errors.New("user ID cannot be zero") } 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 } // Increment analytics if like.WorkID != nil { c.analyticsService.IncrementWorkLikes(ctx, *like.WorkID) } if like.TranslationID != nil { c.analyticsService.IncrementTranslationLikes(ctx, *like.TranslationID) } return like, nil } // DeleteLikeInput represents the input for deleting a like. type DeleteLikeInput struct { ID uint UserID uint // for authorization } // DeleteLike deletes a like by ID. func (c *LikeCommands) DeleteLike(ctx context.Context, input DeleteLikeInput) error { if input.ID == 0 { return errors.New("invalid like ID") } // Fetch the existing like like, err := c.repo.GetByID(ctx, input.ID) if err != nil { return err } if like == nil { return errors.New("like not found") } // Check ownership if like.UserID != input.UserID { return errors.New("unauthorized") } return c.repo.Delete(ctx, input.ID) }