package bou.amine.apps.readerforselfossv2.rest

import bou.amine.apps.readerforselfossv2.model.StatusAndData
import bou.amine.apps.readerforselfossv2.model.SuccessResponse
import io.github.aakira.napier.Napier
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.client.request.forms.*
import io.ktor.client.statement.*
import io.ktor.http.*

suspend fun responseOrSuccessIf404(r: HttpResponse?): SuccessResponse {
    return if (r != null && r.status === HttpStatusCode.NotFound) {
        SuccessResponse(true)
    } else {
        maybeResponse(r)
    }
}

suspend fun maybeResponse(r: HttpResponse?): SuccessResponse {
    return if (r != null && r.status.isSuccess()) {
        r.body()
    } else {
        if (r != null) {
            Napier.i("Error ${r.status}", tag = "maybeResponse")
        }
        SuccessResponse(false)
    }
}

suspend inline fun <reified T> bodyOrFailure(r: HttpResponse?): StatusAndData<T> {
    try {
        return if (r != null && r.status.isSuccess()) {
            StatusAndData.succes(r.body())
        } else {
            StatusAndData.error()
        }
    } catch (e: Throwable) {
        return StatusAndData.error()
    }
}

inline fun tryToRequest(
    requestType: String,
    fn: () -> HttpResponse,
): HttpResponse? {
    var response: HttpResponse? = null
    try {
        response = fn()
    } catch (ex: Exception) {
        Napier.e("Couldn't execute $requestType request", ex, "tryTo$requestType")
    }
    return response
}

suspend inline fun HttpClient.tryToGet(
    urlString: String,
    crossinline block: HttpRequestBuilder.() -> Unit = {},
): HttpResponse? =
    tryToRequest("Get") {
        return this.get {
            url(urlString)
            block()
        }
    }

suspend inline fun HttpClient.tryToPost(
    urlString: String,
    block: HttpRequestBuilder.() -> Unit = {},
): HttpResponse? =
    tryToRequest("Post") {
        return this.post {
            url(urlString)
            block()
        }
    }

suspend inline fun HttpClient.tryToDelete(
    urlString: String,
    block: HttpRequestBuilder.() -> Unit = {},
): HttpResponse? =
    tryToRequest("Delete") {
        return this.delete {
            url(urlString)
            block()
        }
    }

suspend fun HttpClient.tryToSubmitForm(
    url: String,
    formParameters: Parameters = Parameters.Empty,
    encodeInQuery: Boolean = false,
    block: HttpRequestBuilder.() -> Unit = {},
): HttpResponse? =
    tryToRequest("SubmitForm") {
        return this.submitForm(formParameters, encodeInQuery) {
            url(url)
            block()
        }
    }