@ExecuteOn(TaskExecutors.IO)
    @Delete(uri = "{namespace}/files")
    @Operation(tags = {"Files"}, summary = "Delete a file or directory")
    public void delete(
        @Parameter(description = "The namespace id") @PathVariable String namespace,
        @Parameter(description = "The internal storage uri of the file / directory to delete") @QueryValue URI path
    ) throws IOException, URISyntaxException {
        ensureWritableNamespaceFile(path);

        String pathWithoutScheme = path.getPath();

        List<String> allNamespaceFilesPaths = storageInterface.allByPrefix(tenantService.resolveTenant(), NamespaceFile.of(namespace).storagePath().toUri(), true)
            .stream()
            .map(uri -> NamespaceFile.of(namespace, uri).path(true).toString())
            .collect(Collectors.toCollection(ArrayList::new));

        if (allNamespaceFilesPaths.contains(pathWithoutScheme + "/")) {
            // the given path to delete is a directory
            pathWithoutScheme = pathWithoutScheme + "/";
        }

        while (!pathWithoutScheme.equals("/")) {
            String parentFolder = pathWithoutScheme.substring(0, pathWithoutScheme.lastIndexOf('/') + 1);
            if (parentFolder.equals("/")) {
                break;
            }
            List<String> filesInParentFolder = allNamespaceFilesPaths.stream().filter(p -> p.length() > parentFolder.length() && p.startsWith(parentFolder)).toList();
            // there is more than one file in this folder so we stop the cascade deletion there
            if (filesInParentFolder.size() > 1) {
                break;
            }
            allNamespaceFilesPaths.removeIf(filesInParentFolder::contains);
            pathWithoutScheme = parentFolder.endsWith("/") ? parentFolder.substring(0, parentFolder.length() - 1) : parentFolder;
        }
        storageInterface.delete(tenantService.resolveTenant(), NamespaceFile.of(namespace, Path.of(pathWithoutScheme)).uri());
    }
@Test
    void delete() throws IOException {
        storageInterface.put(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folder/file.txt")), new ByteArrayInputStream("Hello".getBytes()));
        client.toBlocking().exchange(HttpRequest.DELETE("/api/v1/namespaces/" + NAMESPACE + "/files?path=/folder/file.txt", null));
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folder/file.txt"))), is(false));
        // Zombie folders are deleted, but not the root folder
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folder"))), is(false));
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, null)), is(true));

        storageInterface.put(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folderWithMultipleFiles/file1.txt")), new ByteArrayInputStream("Hello".getBytes()));
        storageInterface.put(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folderWithMultipleFiles/file2.txt")), new ByteArrayInputStream("Hello".getBytes()));
        client.toBlocking().exchange(HttpRequest.DELETE("/api/v1/namespaces/" + NAMESPACE + "/files?path=/folderWithMultipleFiles/file1.txt", null));
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folderWithMultipleFiles/file1.txt"))), is(false));
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folderWithMultipleFiles/file2.txt"))), is(true));
        // Since there is still one file in the folder, it should not be deleted
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folderWithMultipleFiles"))), is(true));
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, null)), is(true));

        client.toBlocking().exchange(HttpRequest.DELETE("/api/v1/namespaces/" + NAMESPACE + "/files?path=/folderWithMultipleFiles", null));
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, URI.create("/folderWithMultipleFiles/"))), is(false));
        assertThat(storageInterface.exists(null, toNamespacedStorageUri(NAMESPACE, null)), is(true));
    }