package dev.inmo.postssystem.features.files.server

import dev.inmo.postssystem.features.files.common.*
import dev.inmo.postssystem.features.files.common.storage.*
import dev.inmo.micro_utils.ktor.server.*
import dev.inmo.micro_utils.ktor.server.configurators.ApplicationRoutingConfigurator
import dev.inmo.micro_utils.repos.ktor.server.crud.configureReadStandardCrudRepoRoutes
import dev.inmo.micro_utils.repos.ktor.server.crud.configureWriteStandardCrudRepoRoutes
import io.ktor.application.call
import io.ktor.auth.authenticate
import io.ktor.response.respondBytes
import io.ktor.routing.*
import kotlinx.serialization.builtins.nullable

class FilesRoutingConfigurator(
    private val filesStorage: ReadFilesStorage,
    private val writeFilesStorage: WriteFilesStorage?,
    private val unifierRouter: UnifiedRouter
) : ApplicationRoutingConfigurator.Element {
    constructor(filesStorage: FilesStorage, unifierRouter: UnifiedRouter) : this(filesStorage, filesStorage, unifierRouter)

    override fun Route.invoke() {
        authenticate {
            route(filesRootPathPart) {
                configureReadStandardCrudRepoRoutes(
                    filesStorage,
                    MetaFileInfoStorageWrapper.serializer(),
                    MetaFileInfoStorageWrapper.serializer().nullable,
                    FileId.serializer(),
                    unifierRouter
                )
                writeFilesStorage ?.let {
                    configureWriteStandardCrudRepoRoutes(
                        writeFilesStorage,
                        FullFileInfoStorageWrapper.serializer(),
                        FullFileInfoStorageWrapper.serializer().nullable,
                        FullFileInfo.serializer(),
                        FileId.serializer(),
                        unifierRouter
                    )
                }

                unifierRouter.apply {
                    post(filesGetFilesPathPart) {
                        call.respondBytes(
                            filesStorage.getBytes(
                                uniload(FileId.serializer())
                            )
                        )
                    }
                    get(filesGetFullFileInfoPathPart) {
                        unianswer(
                            FullFileInfoStorageWrapper.serializer().nullable,
                            filesStorage.getFullFileInfo(
                                decodeUrlQueryValueOrSendError(filesFileIdParameter, FileId.serializer()) ?: return@get
                            )
                        )
                    }
                }
            }
        }
    }
}
