package com.seven.ikar.kotlin.core.session

import com.seven.ikar.kotlin.core.model.AuthSessionDto
import com.seven.ikar.kotlin.core.network.ApiClient
import com.seven.ikar.kotlin.core.network.ApiException
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

class AuthorizedSessionManager(
    private val apiClient: ApiClient,
    private val sessionStore: SessionStore
) {
    private val refreshMutex = Mutex()

    suspend fun <T> executeAuthorized(block: suspend (AuthSessionDto) -> T): T {
        val session = sessionStore.read() ?: throw IllegalStateException("Сессия не найдена.")
        return try {
            block(session)
        } catch (error: ApiException) {
            if (error.statusCode != 401) {
                throw error
            }

            val refreshedSession = refreshSessionAfterUnauthorized(session)
            block(refreshedSession)
        }
    }

    suspend fun refreshSessionAfterUnauthorized(failedSession: AuthSessionDto): AuthSessionDto =
        refreshMutex.withLock {
            val currentSession = sessionStore.read() ?: throw IllegalStateException("Сессия не найдена.")
            if (currentSession.refreshToken != failedSession.refreshToken) {
                return@withLock currentSession
            }

            val refreshedSession = apiClient.refreshSession(failedSession.refreshToken)
            sessionStore.save(refreshedSession)
            refreshedSession
        }
}
