package sql import ( "context" "gorm.io/gorm" "tercul/internal/domain/work" ) type workRepository struct { domain.BaseRepository[domain.Work] db *gorm.DB } // NewWorkRepository creates a new WorkRepository. func NewWorkRepository(db *gorm.DB) work.WorkRepository { return &workRepository{ BaseRepository: NewBaseRepositoryImpl[domain.Work](db), db: db, } } // FindByTitle finds works by title (partial match) func (r *workRepository) FindByTitle(ctx context.Context, title string) ([]domain.Work, error) { var works []domain.Work if err := r.db.WithContext(ctx).Where("title LIKE ?", "%"+title+"%").Find(&works).Error; err != nil { return nil, err } return works, nil } // FindByAuthor finds works by author ID func (r *workRepository) FindByAuthor(ctx context.Context, authorID uint) ([]domain.Work, error) { var works []domain.Work if err := r.db.WithContext(ctx).Joins("JOIN work_authors ON work_authors.work_id = works.id"). Where("work_authors.author_id = ?", authorID). Find(&works).Error; err != nil { return nil, err } return works, nil } // FindByCategory finds works by category ID func (r *workRepository) FindByCategory(ctx context.Context, categoryID uint) ([]domain.Work, error) { var works []domain.Work if err := r.db.WithContext(ctx).Joins("JOIN work_categories ON work_categories.work_id = works.id"). Where("work_categories.category_id = ?", categoryID). Find(&works).Error; err != nil { return nil, err } return works, nil } // FindByLanguage finds works by language with pagination func (r *workRepository) FindByLanguage(ctx context.Context, language string, page, pageSize int) (*domain.PaginatedResult[domain.Work], error) { if page < 1 { page = 1 } if pageSize < 1 { pageSize = 20 } var works []domain.Work var totalCount int64 // Get total count if err := r.db.WithContext(ctx).Model(&domain.Work{}).Where("language = ?", language).Count(&totalCount).Error; err != nil { return nil, err } // Calculate offset offset := (page - 1) * pageSize // Get paginated data if err := r.db.WithContext(ctx).Where("language = ?", language). Offset(offset).Limit(pageSize). Find(&works).Error; err != nil { return nil, err } // Calculate total pages totalPages := int(totalCount) / pageSize if int(totalCount)%pageSize > 0 { totalPages++ } hasNext := page < totalPages hasPrev := page > 1 return &domain.PaginatedResult[domain.Work]{ Items: works, TotalCount: totalCount, Page: page, PageSize: pageSize, TotalPages: totalPages, HasNext: hasNext, HasPrev: hasPrev, }, nil } // GetWithTranslations gets a work with its translations func (r *workRepository) GetWithTranslations(ctx context.Context, id uint) (*domain.Work, error) { return r.FindWithPreload(ctx, []string{"Translations"}, id) } // ListWithTranslations lists works with their translations func (r *workRepository) ListWithTranslations(ctx context.Context, page, pageSize int) (*domain.PaginatedResult[domain.Work], error) { if page < 1 { page = 1 } if pageSize < 1 { pageSize = 20 } var works []domain.Work var totalCount int64 // Get total count if err := r.db.WithContext(ctx).Model(&domain.Work{}).Count(&totalCount).Error; err != nil { return nil, err } // Calculate offset offset := (page - 1) * pageSize // Get paginated data with preloaded translations if err := r.db.WithContext(ctx).Preload("Translations"). Offset(offset).Limit(pageSize). Find(&works).Error; err != nil { return nil, err } // Calculate total pages totalPages := int(totalCount) / pageSize if int(totalCount)%pageSize > 0 { totalPages++ } hasNext := page < totalPages hasPrev := page > 1 return &domain.PaginatedResult[domain.Work]{ Items: works, TotalCount: totalCount, Page: page, PageSize: pageSize, TotalPages: totalPages, HasNext: hasNext, HasPrev: hasPrev, }, nil }