// monorepo/cloud/backend/internal/maplefile/service/collection/find_root_collections.go
package collection

import (
	"context"

	"go.uber.org/zap"

	"github.com/gocql/gocql"
	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config"
	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config/constants"
	dom_collection "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/domain/collection"
)

type FindRootCollectionsService interface {
	Execute(ctx context.Context) (*CollectionsResponseDTO, error)
}

type findRootCollectionsServiceImpl struct {
	config *config.Configuration
	logger *zap.Logger
	repo   dom_collection.CollectionRepository
}

func NewFindRootCollectionsService(
	config *config.Configuration,
	logger *zap.Logger,
	repo dom_collection.CollectionRepository,
) FindRootCollectionsService {
	logger = logger.Named("FindRootCollectionsService")
	return &findRootCollectionsServiceImpl{
		config: config,
		logger: logger,
		repo:   repo,
	}
}

func (svc *findRootCollectionsServiceImpl) Execute(ctx context.Context) (*CollectionsResponseDTO, error) {
	//
	// STEP 1: Get user ID from context
	//
	userID, ok := ctx.Value(constants.SessionUserID).(gocql.UUID)
	if !ok {
		svc.logger.Error("Failed getting user ID from context")
		return nil, nil
	}

	//
	// STEP 2: Find root collections for the user
	//
	collections, err := svc.repo.FindRootCollections(ctx, userID)
	if err != nil {
		svc.logger.Error("Failed to find root collections",
			zap.Any("error", err),
			zap.Any("user_id", userID))
		return nil, err
	}

	//
	// STEP 3: Filter collections based on permission levels and map to DTOs
	//
	// Filter out collections where the user doesn't have at least read_only permission
	collectionsWithPermission := make([]*CollectionResponseDTO, 0, len(collections))

	for _, collection := range collections {
		// Check if user has at least read_only permission for this collection
		hasAccess, err := svc.repo.CheckAccess(ctx, collection.ID, userID, dom_collection.CollectionPermissionReadOnly)
		if err != nil {
			svc.logger.Warn("Failed to check collection access for root collection, skipping",
				zap.Error(err),
				zap.Any("collection_id", collection.ID),
				zap.Any("user_id", userID))
			continue // Skip collections where we can't verify access
		}

		if hasAccess {
			ownerEmail := getOwnerEmailFromMembers(collection)
			collectionsWithPermission = append(collectionsWithPermission,
				mapCollectionToDTO(collection, 0, ownerEmail))
		} else {
			svc.logger.Debug("User lacks permission for root collection, filtering out",
				zap.Any("collection_id", collection.ID),
				zap.Any("user_id", userID))
		}
	}

	response := &CollectionsResponseDTO{
		Collections: collectionsWithPermission,
	}

	svc.logger.Debug("Found root collections",
		zap.Int("count", len(collections)),
		zap.Any("user_id", userID))

	return response, nil
}
