// monorepo/cloud/maplefile-backend/internal/maplefile/usecase/filemetadata/count_files.go package filemetadata import ( "context" "go.uber.org/zap" "github.com/gocql/gocql" "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config" dom_collection "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/domain/collection" dom_file "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/domain/file" "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/httperror" ) // CountFilesResponse contains the file count for a user type CountFilesResponse struct { TotalFiles int `json:"total_files"` } type CountUserFilesUseCase interface { Execute(ctx context.Context, userID gocql.UUID) (*CountFilesResponse, error) } type countUserFilesUseCaseImpl struct { config *config.Configuration logger *zap.Logger fileRepo dom_file.FileMetadataRepository collectionRepo dom_collection.CollectionRepository } func NewCountUserFilesUseCase( config *config.Configuration, logger *zap.Logger, fileRepo dom_file.FileMetadataRepository, collectionRepo dom_collection.CollectionRepository, ) CountUserFilesUseCase { logger = logger.Named("CountUserFilesUseCase") return &countUserFilesUseCaseImpl{config, logger, fileRepo, collectionRepo} } func (uc *countUserFilesUseCaseImpl) Execute(ctx context.Context, userID gocql.UUID) (*CountFilesResponse, error) { // // STEP 1: Validation. // e := make(map[string]string) if userID.String() == "" { e["user_id"] = "User ID is required" } if len(e) != 0 { uc.logger.Warn("Failed validating count user files", zap.Any("error", e)) return nil, httperror.NewForBadRequest(&e) } // // STEP 2: Get accessible collections for the user. // // Get collections using the efficient filtered query filterOptions := dom_collection.CollectionFilterOptions{ UserID: userID, IncludeOwned: true, IncludeShared: true, } collectionResult, err := uc.collectionRepo.GetCollectionsWithFilter(ctx, filterOptions) if err != nil { uc.logger.Error("Failed to get accessible collections for file count", zap.String("user_id", userID.String()), zap.Error(err)) return nil, err } // Extract collection IDs allCollections := collectionResult.GetAllCollections() accessibleCollectionIDs := make([]gocql.UUID, 0, len(allCollections)) for _, collection := range allCollections { accessibleCollectionIDs = append(accessibleCollectionIDs, collection.ID) } uc.logger.Debug("Found accessible collections for file counting", zap.String("user_id", userID.String()), zap.Int("owned_collections", len(collectionResult.OwnedCollections)), zap.Int("shared_collections", len(collectionResult.SharedCollections)), zap.Int("total_accessible", len(accessibleCollectionIDs))) // // STEP 3: Count files in accessible collections. // fileCount, err := uc.fileRepo.CountFilesByUser(ctx, userID, accessibleCollectionIDs) if err != nil { uc.logger.Error("Failed to count files for user", zap.String("user_id", userID.String()), zap.Int("accessible_collections", len(accessibleCollectionIDs)), zap.Error(err)) return nil, err } response := &CountFilesResponse{ TotalFiles: fileCount, } uc.logger.Debug("Successfully counted user files", zap.String("user_id", userID.String()), zap.Int("accessible_collections", len(accessibleCollectionIDs)), zap.Int("total_files", fileCount)) return response, nil }