package com.swoosh.microblog.data

import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.swoosh.microblog.data.model.GhostAccount
import java.util.UUID

class AccountManager private constructor(
    private val prefs: SharedPreferences,
    private val shouldMigrate: Boolean = true
) {

    private val gson = Gson()

    companion object {
        const val KEY_ACCOUNTS = "ghost_accounts"
        const val KEY_ACTIVE_ACCOUNT_ID = "active_account_id"
        const val MAX_ACCOUNTS = 5

        // Legacy keys for migration
        private const val LEGACY_KEY_GHOST_URL = "ghost_url"
        private const val LEGACY_KEY_ADMIN_API_KEY = "admin_api_key"
        private const val KEY_MIGRATION_DONE = "multi_account_migration_done"

        private fun createEncryptedPrefs(context: Context): SharedPreferences {
            val masterKey = MasterKey.Builder(context)
                .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                .build()

            return EncryptedSharedPreferences.create(
                context,
                "swoosh_secure_prefs",
                masterKey,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            )
        }
    }

    constructor(context: Context) : this(createEncryptedPrefs(context), shouldMigrate = true)

    /** Constructor for testing with plain SharedPreferences */
    constructor(prefs: SharedPreferences) : this(prefs, shouldMigrate = true)

    init {
        if (shouldMigrate) {
            migrateIfNeeded()
        }
    }

    private fun migrateIfNeeded() {
        if (prefs.getBoolean(KEY_MIGRATION_DONE, false)) return

        val legacyUrl = prefs.getString(LEGACY_KEY_GHOST_URL, null)
        val legacyKey = prefs.getString(LEGACY_KEY_ADMIN_API_KEY, null)

        if (!legacyUrl.isNullOrBlank() && !legacyKey.isNullOrBlank()) {
            val account = GhostAccount(
                id = UUID.randomUUID().toString(),
                name = extractBlogName(legacyUrl),
                blogUrl = legacyUrl,
                apiKey = legacyKey,
                isActive = true,
                colorIndex = 0
            )
            val accounts = listOf(account)
            saveAccountsList(accounts)
            prefs.edit().putString(KEY_ACTIVE_ACCOUNT_ID, account.id).apply()

            // Remove legacy keys
            prefs.edit()
                .remove(LEGACY_KEY_GHOST_URL)
                .remove(LEGACY_KEY_ADMIN_API_KEY)
                .apply()
        }

        prefs.edit().putBoolean(KEY_MIGRATION_DONE, true).apply()
    }

    fun getAccounts(): List<GhostAccount> {
        val json = prefs.getString(KEY_ACCOUNTS, null) ?: return emptyList()
        val type = object : TypeToken<List<GhostAccount>>() {}.type
        return try {
            val accounts: List<GhostAccount> = gson.fromJson(json, type)
            val activeId = prefs.getString(KEY_ACTIVE_ACCOUNT_ID, null)
            accounts.map { it.copy(isActive = it.id == activeId) }
        } catch (e: Exception) {
            emptyList()
        }
    }

    fun getActiveAccount(): GhostAccount? {
        val activeId = prefs.getString(KEY_ACTIVE_ACCOUNT_ID, null) ?: return null
        return getAccounts().find { it.id == activeId }
    }

    fun addAccount(name: String, blogUrl: String, apiKey: String): Result<GhostAccount> {
        val accounts = getAccounts()
        if (accounts.size >= MAX_ACCOUNTS) {
            return Result.failure(IllegalStateException("Maximum of $MAX_ACCOUNTS accounts reached"))
        }

        val colorIndex = nextAvailableColorIndex(accounts)
        val account = GhostAccount(
            id = UUID.randomUUID().toString(),
            name = name.ifBlank { extractBlogName(blogUrl) },
            blogUrl = blogUrl,
            apiKey = apiKey,
            isActive = true,
            colorIndex = colorIndex
        )

        val updatedAccounts = accounts + account
        saveAccountsList(updatedAccounts)
        setActiveAccount(account.id)

        return Result.success(account)
    }

    fun removeAccount(id: String): Boolean {
        val accounts = getAccounts().toMutableList()
        val removed = accounts.removeAll { it.id == id }
        if (!removed) return false

        saveAccountsList(accounts)

        // If the removed account was active, switch to first available
        val activeId = prefs.getString(KEY_ACTIVE_ACCOUNT_ID, null)
        if (activeId == id) {
            val nextAccount = accounts.firstOrNull()
            if (nextAccount != null) {
                setActiveAccount(nextAccount.id)
            } else {
                prefs.edit().remove(KEY_ACTIVE_ACCOUNT_ID).apply()
            }
        }

        return true
    }

    fun setActiveAccount(id: String): Boolean {
        val accounts = getAccounts()
        if (accounts.none { it.id == id }) return false
        prefs.edit().putString(KEY_ACTIVE_ACCOUNT_ID, id).apply()
        return true
    }

    fun updateAccount(id: String, name: String? = null, blogUrl: String? = null, apiKey: String? = null, avatarUrl: String? = null): Boolean {
        val accounts = getAccounts().toMutableList()
        val index = accounts.indexOfFirst { it.id == id }
        if (index == -1) return false

        val current = accounts[index]
        accounts[index] = current.copy(
            name = name ?: current.name,
            blogUrl = blogUrl ?: current.blogUrl,
            apiKey = apiKey ?: current.apiKey,
            avatarUrl = avatarUrl ?: current.avatarUrl
        )

        saveAccountsList(accounts)
        return true
    }

    val isConfigured: Boolean
        get() = getActiveAccount() != null

    val hasAnyAccount: Boolean
        get() = getAccounts().isNotEmpty()

    fun clearAll() {
        prefs.edit()
            .remove(KEY_ACCOUNTS)
            .remove(KEY_ACTIVE_ACCOUNT_ID)
            .remove(KEY_MIGRATION_DONE)
            .apply()
    }

    private fun saveAccountsList(accounts: List<GhostAccount>) {
        // Strip isActive before saving since it's derived from KEY_ACTIVE_ACCOUNT_ID
        val toSave = accounts.map { it.copy(isActive = false) }
        val json = gson.toJson(toSave)
        prefs.edit().putString(KEY_ACCOUNTS, json).apply()
    }

    private fun nextAvailableColorIndex(accounts: List<GhostAccount>): Int {
        val usedIndices = accounts.map { it.colorIndex }.toSet()
        for (i in 0 until GhostAccount.ACCOUNT_COLORS.size) {
            if (i !in usedIndices) return i
        }
        return accounts.size % GhostAccount.ACCOUNT_COLORS.size
    }

    internal fun extractBlogName(url: String): String {
        return try {
            val cleaned = url.trim()
                .removePrefix("https://")
                .removePrefix("http://")
                .removeSuffix("/")
            val host = cleaned.split("/").first()
            // Remove common suffixes
            host.removeSuffix(".ghost.io")
                .removeSuffix(".com")
                .removeSuffix(".org")
                .removeSuffix(".net")
                .replaceFirstChar { it.uppercase() }
        } catch (e: Exception) {
            "My Blog"
        }
    }
}
