// codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/repo/user/delete.go
package user

import (
	"context"
	"fmt"

	"github.com/gocql/gocql"
	"go.uber.org/zap"

	"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/validation"
)

func (impl userStorerImpl) DeleteByID(ctx context.Context, id gocql.UUID) error {
	// First, get the user to know all the data we need to delete
	user, err := impl.GetByID(ctx, id)
	if err != nil {
		return fmt.Errorf("failed to get user for deletion: %w", err)
	}
	if user == nil {
		return nil // User doesn't exist, nothing to delete
	}

	batch := impl.session.NewBatch(gocql.LoggedBatch).WithContext(ctx)

	// Delete from all user tables
	batch.Query(`DELETE FROM users_by_id WHERE id = ?`, id)
	batch.Query(`DELETE FROM users_by_email WHERE email = ?`, user.Email)

	// Delete from verification code table if user has verification code
	// Note: We delete by scanning since verification_code is the partition key
	// This is acceptable for GDPR deletion (rare operation, thorough cleanup)
	if user.SecurityData != nil && user.SecurityData.Code != "" {
		batch.Query(`DELETE FROM users_by_verification_code WHERE verification_code = ?`, user.SecurityData.Code)
	}

	// Delete all user sessions
	// Note: sessions_by_user_id is partitioned by user_id, so this is efficient
	batch.Query(`DELETE FROM sessions_by_user_id WHERE user_id = ?`, id)

	// Execute the batch
	if err := impl.session.ExecuteBatch(batch); err != nil {
		impl.logger.Error("Failed to delete user",
			zap.String("user_id", id.String()),
			zap.Error(err))
		return fmt.Errorf("failed to delete user: %w", err)
	}

	impl.logger.Info("User deleted successfully",
		zap.String("user_id", id.String()),
		zap.String("email", validation.MaskEmail(user.Email)))

	return nil
}

func (impl userStorerImpl) DeleteByEmail(ctx context.Context, email string) error {
	// First get the user by email to get the ID
	user, err := impl.GetByEmail(ctx, email)
	if err != nil {
		return fmt.Errorf("failed to get user by email for deletion: %w", err)
	}
	if user == nil {
		return nil // User doesn't exist
	}

	// Delete by ID
	return impl.DeleteByID(ctx, user.ID)
}
