package com.github.nullptroma.wallenc.app.auth

import android.content.Context
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import com.github.nullptroma.wallenc.domain.vault.vaults.yandex.YandexRegistration
import com.github.nullptroma.wallenc.vault.contract.CloudBrand
import com.github.nullptroma.wallenc.vault.contract.RemoteVaultAuthenticator
import com.github.nullptroma.wallenc.vault.contract.VaultLinkFailure
import com.github.nullptroma.wallenc.vault.contract.VaultLinkOutcome
import com.yandex.authsdk.YandexAuthLoginOptions
import com.yandex.authsdk.YandexAuthOptions
import com.yandex.authsdk.YandexAuthResult
import com.yandex.authsdk.YandexAuthSdk
import com.yandex.authsdk.internal.strategy.LoginType
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Императивный вход через Yandex Auth SDK: [registerWith] в [ComponentActivity.onCreate],
 * [unregister] в [ComponentActivity.onDestroy], чтобы синглтон не держал [ActivityResultLauncher]
 * дольше жизни Activity.
 *
 * При смене конфигурации новая Activity может вызвать [registerWith] до [unregister] старой —
 * тогда владелец и launcher обновляются; [unregister] для уже неактуального экземпляра — no-op.
 *
 * Реализует [RemoteVaultAuthenticator] из `:vault-api`: presentation про Yandex SDK
 * ничего не знает, а получает обобщённый [VaultLinkOutcome] с готовой
 * `VaultRegistration` внутри.
 */
@Singleton
class YandexSignInService @Inject constructor(
    @ApplicationContext appContext: Context,
) : RemoteVaultAuthenticator {

    private val sdk = YandexAuthSdk.create(YandexAuthOptions(appContext, true))

    private var launcher: ActivityResultLauncher<YandexAuthLoginOptions>? = null

    private var registrationOwner: ComponentActivity? = null

    @Volatile
    private var pending: ((VaultLinkOutcome) -> Unit)? = null

    fun registerWith(activity: ComponentActivity) {
        if (registrationOwner === activity && launcher != null) return
        launcher = activity.registerForActivityResult(sdk.contract) { result ->
            val mapped = mapYandexResult(result)
            val cb = synchronized(this) {
                val p = pending
                pending = null
                p
            }
            cb?.invoke(mapped)
        }
        registrationOwner = activity
    }

    fun unregister(activity: ComponentActivity) {
        if (registrationOwner !== activity) return
        launcher = null
        registrationOwner = null
        val cb = synchronized(this) {
            val p = pending
            pending = null
            p
        }
        cb?.invoke(VaultLinkOutcome.Cancelled)
    }

    override fun beginLink(brand: CloudBrand, onResult: (VaultLinkOutcome) -> Unit) {
        if (brand != CloudBrand.YANDEX) {
            onResult(VaultLinkOutcome.Failed(VaultLinkFailure.UnsupportedBrand))
            return
        }
        val l = launcher
        if (l == null) {
            onResult(VaultLinkOutcome.Failed(VaultLinkFailure.NotRegistered))
            return
        }
        synchronized(this) { pending = onResult }
        l.launch(YandexAuthLoginOptions(LoginType.NATIVE))
    }

    private fun mapYandexResult(result: YandexAuthResult): VaultLinkOutcome = when (result) {
        is YandexAuthResult.Success ->
            VaultLinkOutcome.Success(YandexRegistration(result.token.value))
        is YandexAuthResult.Failure ->
            VaultLinkOutcome.Failed(VaultLinkFailure.AuthError)
        YandexAuthResult.Cancelled -> VaultLinkOutcome.Cancelled
    }
}
