package dev.inmo.postssystem.services.posts.client import dev.inmo.micro_utils.common.* import dev.inmo.micro_utils.ktor.client.UnifiedRequester import dev.inmo.micro_utils.ktor.client.tempUpload import dev.inmo.micro_utils.ktor.common.buildStandardUrl import dev.inmo.micro_utils.ktor.common.encodeHex import dev.inmo.micro_utils.repos.ktor.common.crud.createRouting import dev.inmo.micro_utils.repos.ktor.common.crud.updateRouting import dev.inmo.micro_utils.repos.ktor.common.one_to_many.removeRoute import dev.inmo.postssystem.features.common.common.FileBasedInputProvider import dev.inmo.postssystem.features.common.common.SimpleInputProvider import dev.inmo.postssystem.features.content.common.* import dev.inmo.postssystem.features.files.common.FileId import dev.inmo.postssystem.features.posts.common.PostId import dev.inmo.postssystem.features.posts.common.RegisteredPost import dev.inmo.postssystem.services.posts.common.* import io.ktor.client.request.forms.InputProvider import io.ktor.client.request.forms.formData import io.ktor.client.request.headers import io.ktor.client.request.post import io.ktor.http.HttpHeaders import kotlinx.serialization.builtins.* import kotlinx.serialization.modules.polymorphic class ClientWritePostsService( private val baseUrl: String, client: HttpClient ) : WritePostsService { private val root = buildStandardUrl(baseUrl, postsRootPath) // private val unifiedRequester = UnifiedRequester( // unifiedRequester.client, // unifiedRequester.serialFormat.createWithSerializerModuleExtension { // polymorphic(Content::class) { // subclass(BinaryContent::class, BinaryContentSerializer(TempFileIdentifierInputProvider::class, TempFileIdentifierInputProvider.serializer())) // } // } // ) private val contentEitherSerializer = EitherSerializer(ContentId.serializer(), ContentSerializer) private val contentsEitherSerializer = ListSerializer(contentEitherSerializer) private val contentsSerializer = ListSerializer(ContentSerializer) private val createFullPath = buildStandardUrl( root, createRouting ) private val removeFullPath = buildStandardUrl( root, removeRoute ) private val tempUploadFullPath = buildStandardUrl( root, postsCreateTempPathPart ) private suspend fun prepareContent(content: Content): Content? { return (content as? BinaryContent) ?.let { when (val provider = it.inputProvider) { is FileBasedInputProvider -> { val fileId = client.tempUpload( tempUploadFullPath, provider.file ) println(fileId) it.copy(inputProvider = TempFileIdentifierInputProvider(FileId(fileId.string))) } is TempFileIdentifierInputProvider -> it else -> return@prepareContent null } } ?: content } override suspend fun create(newPost: FullNewPost): RegisteredPost? { val mappedContent = newPost.content.mapNotNull { prepareContent(it) } val mappedPost = newPost.copy( content = mappedContent ) return unifiedRequester.unipost( createFullPath, contentsSerializer to mappedPost.content, RegisteredPost.serializer().nullable ) } override suspend fun update( postId: PostId, content: List> ): RegisteredPost? { val mappedContent = content.mapNotNull { it.mapOnSecond { content -> prepareContent(content) ?.either() ?: return@mapNotNull null } ?: it } return unifiedRequester.unipost( buildStandardUrl( root, updateRouting, postsPostIdParameter to unifiedRequester.encodeUrlQueryValue(PostId.serializer(), postId) ), contentsEitherSerializer to mappedContent, RegisteredPost.serializer().nullable ) } override suspend fun remove(postId: PostId) = unifiedRequester.unipost( removeFullPath, PostId.serializer() to postId, Unit.serializer() ) }