package com.rosetta.messenger.data

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.*
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map

private val Context.accountDataStore: DataStore<Preferences> by preferencesDataStore(name = "account_store")

/**
 * Manages encrypted account storage using DataStore
 */
class AccountManager(private val context: Context) {
    
    companion object {
        private val CURRENT_PUBLIC_KEY = stringPreferencesKey("current_public_key")
        private val ACCOUNTS_JSON = stringPreferencesKey("accounts_json")
        private val IS_LOGGED_IN = booleanPreferencesKey("is_logged_in")
        private const val PREFS_NAME = "rosetta_account_prefs"
        private const val KEY_LAST_LOGGED = "last_logged_public_key"
        private const val KEY_LAST_LOGGED_PRIVATE_HASH = "last_logged_private_hash"
    }
    
    // Use SharedPreferences for last logged account - more reliable for immediate reads
    private val sharedPrefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
    
    val currentPublicKey: Flow<String?> = context.accountDataStore.data.map { preferences ->
        preferences[CURRENT_PUBLIC_KEY]
    }
    
    val isLoggedIn: Flow<Boolean> = context.accountDataStore.data.map { preferences ->
        preferences[IS_LOGGED_IN] ?: false
    }
    
    val accountsJson: Flow<String?> = context.accountDataStore.data.map { preferences ->
        preferences[ACCOUNTS_JSON]
    }
    
    // Synchronous read from SharedPreferences - always up to date
    fun getLastLoggedPublicKey(): String? {
        val publicKey = sharedPrefs.getString(KEY_LAST_LOGGED, null)
        return publicKey
    }

    fun getLastLoggedPrivateKeyHash(): String? {
        return sharedPrefs.getString(KEY_LAST_LOGGED_PRIVATE_HASH, null)
    }
    
    // Synchronous write to SharedPreferences
    fun setLastLoggedPublicKey(publicKey: String) {
        sharedPrefs.edit().putString(KEY_LAST_LOGGED, publicKey).commit() // commit() is synchronous
    }

    fun setLastLoggedPrivateKeyHash(privateKeyHash: String) {
        if (privateKeyHash.isBlank()) return
        sharedPrefs.edit().putString(KEY_LAST_LOGGED_PRIVATE_HASH, privateKeyHash).apply()
    }
    
    suspend fun saveAccount(account: EncryptedAccount) {
        context.accountDataStore.edit { preferences ->
            val existingJson = preferences[ACCOUNTS_JSON]
            val accounts = if (existingJson != null) {
                parseAccounts(existingJson).toMutableList()
            } else {
                mutableListOf()
            }
            
            // Remove existing account with same public key
            accounts.removeAll { it.publicKey == account.publicKey }
            accounts.add(account)
            
            preferences[ACCOUNTS_JSON] = serializeAccounts(accounts)
        }
    }
    
    suspend fun getAccount(publicKey: String): EncryptedAccount? {
        val preferences = context.accountDataStore.data.first()
        val json = preferences[ACCOUNTS_JSON]
        return if (json != null) parseAccounts(json).find { it.publicKey == publicKey } else null
    }
    
    suspend fun getAllAccounts(): List<EncryptedAccount> {
        val preferences = context.accountDataStore.data.first()
        val json = preferences[ACCOUNTS_JSON]
        return if (json != null) parseAccounts(json) else emptyList()
    }
    
    suspend fun setCurrentAccount(publicKey: String) {
        
        // ⚡ ВАЖНО: Сначала сохраняем в SharedPreferences синхронно
        setLastLoggedPublicKey(publicKey)
        
        // Потом в DataStore асинхронно (для совместимости с потоками)
        context.accountDataStore.edit { preferences ->
            preferences[CURRENT_PUBLIC_KEY] = publicKey
            preferences[IS_LOGGED_IN] = true
        }
        
    }
    
    suspend fun logout() {
        context.accountDataStore.edit { preferences ->
            preferences[IS_LOGGED_IN] = false
        }
        sharedPrefs.edit().remove(KEY_LAST_LOGGED_PRIVATE_HASH).apply()
    }
    
    /**
     * Update account username
     */
    suspend fun updateAccountUsername(publicKey: String, username: String) {
        val account = getAccount(publicKey) ?: return
        val updatedAccount = account.copy(username = username)
        saveAccount(updatedAccount)
    }
    
    /**
     * Update account name
     */
    suspend fun updateAccountName(publicKey: String, name: String) {
        val account = getAccount(publicKey) ?: return
        val updatedAccount = account.copy(name = name)
        saveAccount(updatedAccount)
    }
    
    /**
     * Delete account completely - remove from accounts list and clear login state
     */
    suspend fun deleteAccount(publicKey: String) {
        context.accountDataStore.edit { preferences ->
            // Remove from accounts list
            val existingJson = preferences[ACCOUNTS_JSON]
            if (existingJson != null) {
                val accounts = parseAccounts(existingJson).toMutableList()
                accounts.removeAll { it.publicKey == publicKey }
                preferences[ACCOUNTS_JSON] = serializeAccounts(accounts)
            }
            // Clear current login if this was the active account
            val currentKey = preferences[CURRENT_PUBLIC_KEY]
            if (currentKey == publicKey) {
                preferences[IS_LOGGED_IN] = false
                preferences.remove(CURRENT_PUBLIC_KEY)
            }
        }
        // Clear SharedPreferences if this was the last logged account
        val lastLogged = sharedPrefs.getString(KEY_LAST_LOGGED, null)
        if (lastLogged == publicKey) {
            sharedPrefs
                .edit()
                .remove(KEY_LAST_LOGGED)
                .remove(KEY_LAST_LOGGED_PRIVATE_HASH)
                .commit()
        }
    }

    suspend fun clearAll() {
        context.accountDataStore.edit { it.clear() }
        sharedPrefs
            .edit()
            .remove(KEY_LAST_LOGGED)
            .remove(KEY_LAST_LOGGED_PRIVATE_HASH)
            .apply()
    }
    
    private fun serializeAccounts(accounts: List<EncryptedAccount>): String {
        return accounts.joinToString("|||") { account ->
            "${account.publicKey}::${account.encryptedPrivateKey}::${account.encryptedSeedPhrase}::${account.name}::${account.username ?: ""}"
        }
    }
    
    private fun parseAccounts(json: String): List<EncryptedAccount> {
        if (json.isBlank()) return emptyList()
        
        return json.split("|||").mapNotNull { accountStr ->
            val parts = accountStr.split("::")
            if (parts.size >= 4) {
                EncryptedAccount(
                    publicKey = parts[0],
                    encryptedPrivateKey = parts[1],
                    encryptedSeedPhrase = parts[2],
                    name = parts[3],
                    username = parts.getOrNull(4)?.takeIf { it.isNotBlank() }
                )
            } else null
        }
    }
}

data class EncryptedAccount(
    val publicKey: String,
    val encryptedPrivateKey: String,
    val encryptedSeedPhrase: String,
    val name: String = "Account",
    val username: String? = null
)

data class DecryptedAccount(
    val publicKey: String,
    val privateKey: String,
    val seedPhrase: List<String>,
    val privateKeyHash: String,
    val name: String = "Account"
)
