package com.prodhack.moscow2025.data.data_providers.api

import android.util.Log
import com.prodhack.moscow2025.common.Constants
import com.prodhack.moscow2025.data.data_providers.localInfo.AuthorizationDataStore
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.HttpRequestRetry
import io.ktor.client.plugins.auth.Auth
import io.ktor.client.plugins.auth.providers.BearerTokens
import io.ktor.client.plugins.auth.providers.bearer
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.defaultRequest
import io.ktor.client.plugins.logging.ANDROID
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import org.koin.core.annotation.Single


// Configuration Ktor client for request to API
@Single
class ApiKtorClient(authorizationDataStore: AuthorizationDataStore) {

	val client = HttpClient(OkHttp) {
		install(Logging) {
			logger = Logger.ANDROID
			level = LogLevel.ALL
		}
		install(HttpRequestRetry) {
			retryOnServerErrors(maxRetries = 3)
			exponentialDelay()
		}
		install(ContentNegotiation) {
			json(Json {
				prettyPrint = true
				isLenient = true
				ignoreUnknownKeys = true
			})
		}
		defaultRequest {
			url(Constants.BASE_API_URL)
		}
		install(Auth) {
			bearer {
//				sendWithoutRequest { request ->
//					val segments = request.url.pathSegments
//
//					val endpointsWithoutAuth = listOf(
//						"sign_in",
//						"sign_up"
//					)
//
//					endpointsWithoutAuth.any { segments.contains(it) }.not()
//				}
				loadTokens {
					return@loadTokens authorizationDataStore.token.first()
						.toBearerTokens().also {
							Log.d("ApiKtorClient", it.accessToken)
						}
				}
				refreshTokens {
					CoroutineScope(Dispatchers.IO).launch {
						authorizationDataStore.clearToken()
					}

					return@refreshTokens null
				}
			}
		}
	}

	val authClient = HttpClient(OkHttp) {
		install(Logging) {
			logger = Logger.ANDROID
			level = LogLevel.ALL
		}
		install(HttpRequestRetry) {
			retryOnServerErrors(maxRetries = 3)
			exponentialDelay()
		}
		install(ContentNegotiation) {
			json(Json {
				prettyPrint = true
				isLenient = true
				ignoreUnknownKeys = true
			})
		}
		defaultRequest {
			url(Constants.BASE_API_URL)
		}
	}

	private fun String.toBearerTokens(): BearerTokens {
		return BearerTokens(this, null)
	}
}
