package work import ( "context" "errors" "tercul/internal/domain" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" "github.com/google/uuid" ) // WorkQueries contains the query handlers for the work aggregate. type WorkQueries struct { repo domain.WorkRepository tracer trace.Tracer } // NewWorkQueries creates a new WorkQueries handler. func NewWorkQueries(repo domain.WorkRepository) *WorkQueries { return &WorkQueries{ repo: repo, tracer: otel.Tracer("work.queries"), } } // GetWorkByID retrieves a work by ID. func (q *WorkQueries) GetWorkByID(ctx context.Context, id uuid.UUID) (*WorkDTO, error) { ctx, span := q.tracer.Start(ctx, "GetWorkByID") defer span.End() if id == uuid.Nil { return nil, errors.New("invalid work ID") } work, err := q.repo.GetByID(ctx, id) if err != nil { return nil, err } if work == nil { return nil, nil } return &WorkDTO{ ID: work.ID, Title: work.Title, Language: work.Language, }, nil } // ListWorks returns a paginated list of works. func (q *WorkQueries) ListWorks(ctx context.Context, page, pageSize int) (*domain.PaginatedResult[WorkDTO], error) { ctx, span := q.tracer.Start(ctx, "ListWorks") defer span.End() paginatedWorks, err := q.repo.List(ctx, page, pageSize) if err != nil { return nil, err } workDTOs := make([]WorkDTO, len(paginatedWorks.Items)) for i, work := range paginatedWorks.Items { workDTOs[i] = WorkDTO{ ID: work.ID, Title: work.Title, Language: work.Language, } } return &domain.PaginatedResult[WorkDTO]{ Items: workDTOs, TotalCount: paginatedWorks.TotalCount, Page: paginatedWorks.Page, PageSize: paginatedWorks.PageSize, TotalPages: paginatedWorks.TotalPages, }, nil } // GetWorkWithTranslations retrieves a work with its translations. func (q *WorkQueries) GetWorkWithTranslations(ctx context.Context, id uuid.UUID) (*domain.Work, error) { ctx, span := q.tracer.Start(ctx, "GetWorkWithTranslations") defer span.End() if id == uuid.Nil { return nil, errors.New("invalid work ID") } return q.repo.GetWithTranslations(ctx, id) } // FindWorksByTitle finds works by title. func (q *WorkQueries) FindWorksByTitle(ctx context.Context, title string) ([]domain.Work, error) { ctx, span := q.tracer.Start(ctx, "FindWorksByTitle") defer span.End() if title == "" { return nil, errors.New("title cannot be empty") } return q.repo.FindByTitle(ctx, title) } // FindWorksByAuthor finds works by author ID. func (q *WorkQueries) FindWorksByAuthor(ctx context.Context, authorID uuid.UUID) ([]domain.Work, error) { ctx, span := q.tracer.Start(ctx, "FindWorksByAuthor") defer span.End() if authorID == uuid.Nil { return nil, errors.New("invalid author ID") } return q.repo.FindByAuthor(ctx, authorID) } // FindWorksByCategory finds works by category ID. func (q *WorkQueries) FindWorksByCategory(ctx context.Context, categoryID uuid.UUID) ([]domain.Work, error) { ctx, span := q.tracer.Start(ctx, "FindWorksByCategory") defer span.End() if categoryID == uuid.Nil { return nil, errors.New("invalid category ID") } return q.repo.FindByCategory(ctx, categoryID) } // FindWorksByLanguage finds works by language. func (q *WorkQueries) FindWorksByLanguage(ctx context.Context, language string, page, pageSize int) (*domain.PaginatedResult[domain.Work], error) { ctx, span := q.tracer.Start(ctx, "FindWorksByLanguage") defer span.End() if language == "" { return nil, errors.New("language cannot be empty") } return q.repo.FindByLanguage(ctx, language, page, pageSize) } // ListByCollectionID finds works by collection ID. func (q *WorkQueries) ListByCollectionID(ctx context.Context, collectionID uuid.UUID) ([]domain.Work, error) { ctx, span := q.tracer.Start(ctx, "ListByCollectionID") defer span.End() if collectionID == uuid.Nil { return nil, errors.New("invalid collection ID") } return q.repo.ListByCollectionID(ctx, collectionID) }