package bookmark

import (
	"context"
	"tercul/internal/app/analytics"
	"tercul/internal/domain"
	"tercul/internal/platform/log"
)

// BookmarkCommands contains the command handlers for the bookmark aggregate.
type BookmarkCommands struct {
	repo         domain.BookmarkRepository
	analyticsSvc analytics.Service
}

// NewBookmarkCommands creates a new BookmarkCommands handler.
func NewBookmarkCommands(repo domain.BookmarkRepository, analyticsSvc analytics.Service) *BookmarkCommands {
	return &BookmarkCommands{
		repo:         repo,
		analyticsSvc: analyticsSvc,
	}
}

// CreateBookmarkInput represents the input for creating a new bookmark.
type CreateBookmarkInput struct {
	Name   string
	UserID uint
	WorkID uint
	Notes  string
}

// CreateBookmark creates a new bookmark.
func (c *BookmarkCommands) CreateBookmark(ctx context.Context, input CreateBookmarkInput) (*domain.Bookmark, error) {
	bookmark := &domain.Bookmark{
		Name:   input.Name,
		UserID: input.UserID,
		WorkID: input.WorkID,
		Notes:  input.Notes,
	}
	err := c.repo.Create(ctx, bookmark)
	if err != nil {
		return nil, err
	}

	if c.analyticsSvc != nil {
		go func() {
			if err := c.analyticsSvc.IncrementWorkBookmarks(context.Background(), input.WorkID); err != nil {
				log.Error(err, "failed to increment work bookmarks")
			}
		}()
	}

	return bookmark, nil
}

// UpdateBookmarkInput represents the input for updating an existing bookmark.
type UpdateBookmarkInput struct {
	ID    uint
	Name  string
	Notes string
}

// UpdateBookmark updates an existing bookmark.
func (c *BookmarkCommands) UpdateBookmark(ctx context.Context, input UpdateBookmarkInput) (*domain.Bookmark, error) {
	bookmark, err := c.repo.GetByID(ctx, input.ID)
	if err != nil {
		return nil, err
	}
	bookmark.Name = input.Name
	bookmark.Notes = input.Notes
	err = c.repo.Update(ctx, bookmark)
	if err != nil {
		return nil, err
	}
	return bookmark, nil
}

// DeleteBookmark deletes a bookmark by ID.
func (c *BookmarkCommands) DeleteBookmark(ctx context.Context, id uint) error {
	return c.repo.Delete(ctx, id)
}
