package com.rosetta.messenger.network.connection

import com.rosetta.messenger.data.MessageRepository
import com.rosetta.messenger.network.ConnectionBootstrapContext
import com.rosetta.messenger.network.ProtocolState

class ProtocolAccountSessionCoordinator(
    private val stateStore: ProtocolLifecycleStateStore,
    private val syncCoordinator: SyncCoordinator,
    private val authBootstrapCoordinator: AuthBootstrapCoordinator,
    private val presenceTypingService: PresenceTypingService,
    private val deviceRuntimeService: DeviceRuntimeService,
    private val getMessageRepository: () -> MessageRepository?,
    private val getProtocolState: () -> ProtocolState,
    private val isProtocolAuthenticated: () -> Boolean,
    private val addLog: (String) -> Unit,
    private val shortKeyForLog: (String) -> String,
    private val clearReadyPacketQueue: (String) -> Unit,
    private val recomputeConnectionLifecycleState: (String) -> Unit,
    private val stopWaitingForNetwork: (String) -> Unit,
    private val disconnectProtocol: (clearCredentials: Boolean) -> Unit,
    private val tryRunPostAuthBootstrap: (String) -> Unit,
    private val launchVersionUpdateCheck: () -> Unit
) {
    fun handleInitializeAccount(publicKey: String, privateKey: String) {
        val normalizedPublicKey = publicKey.trim()
        val normalizedPrivateKey = privateKey.trim()
        if (normalizedPublicKey.isBlank() || normalizedPrivateKey.isBlank()) {
            addLog("⚠️ initializeAccount skipped: missing account credentials")
            return
        }

        val protocolState = getProtocolState()
        addLog(
            "🔐 initializeAccount pk=${shortKeyForLog(normalizedPublicKey)} keyLen=${normalizedPrivateKey.length} state=$protocolState"
        )
        syncCoordinator.markSyncInProgress(false)
        presenceTypingService.clear()

        val repository = getMessageRepository()
        if (repository == null) {
            addLog("❌ initializeAccount aborted: MessageRepository is not bound")
            return
        }
        repository.initialize(normalizedPublicKey, normalizedPrivateKey)

        val context = stateStore.bootstrapContext
        val sameAccount = context.accountPublicKey.equals(normalizedPublicKey, ignoreCase = true)
        if (!sameAccount) {
            clearReadyPacketQueue("account_switch")
        }

        stateStore.bootstrapContext =
            context.copy(
                accountPublicKey = normalizedPublicKey,
                accountInitialized = true,
                syncCompleted = if (sameAccount) context.syncCompleted else false,
                ownProfileResolved = if (sameAccount) context.ownProfileResolved else false
            )
        recomputeConnectionLifecycleState("account_initialized")

        val shouldResync = syncCoordinator.shouldResyncAfterAccountInit() || isProtocolAuthenticated()
        if (shouldResync) {
            syncCoordinator.clearResyncRequired()
            syncCoordinator.clearRequestState()
            addLog("🔄 Account initialized (${shortKeyForLog(normalizedPublicKey)}) -> force sync")
            syncCoordinator.requestSynchronize()
        }
        if (isProtocolAuthenticated() && authBootstrapCoordinator.isBootstrapPending()) {
            tryRunPostAuthBootstrap("account_initialized")
        }

        launchVersionUpdateCheck()
    }

    fun handleDisconnect(reason: String, clearCredentials: Boolean) {
        stopWaitingForNetwork(reason)
        disconnectProtocol(clearCredentials)
        getMessageRepository()?.clearInitialization()
        presenceTypingService.clear()
        deviceRuntimeService.clear()
        syncCoordinator.resetForDisconnect()
        stateStore.clearLastSubscribedToken()
        stateStore.cancelOwnProfileFallbackTimeout()
        authBootstrapCoordinator.reset()
        stateStore.bootstrapContext = ConnectionBootstrapContext()
        clearReadyPacketQueue("disconnect:$reason")
        recomputeConnectionLifecycleState("disconnect:$reason")
    }
}
