package com.atridad.ascently.utils

import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit

class MigrationManager(private val context: Context) {

    companion object {
        private const val TAG = "MigrationManager"
        private const val MIGRATION_PREFS = "ascently_migration_state"
        private const val MIGRATION_COMPLETED_KEY = "openclimb_to_ascently_completed"
    }

    private val migrationPrefs: SharedPreferences =
        context.getSharedPreferences(MIGRATION_PREFS, Context.MODE_PRIVATE)

    /**
     * Perform migration from OpenClimb to Ascently if needed This should be called early in app
     * startup
     */
    fun migrateIfNeeded() {
        if (migrationPrefs.getBoolean(MIGRATION_COMPLETED_KEY, false)) {
            AppLogger.d(TAG) { "Migration already completed, skipping" }
            return
        }

        AppLogger.i(TAG) { "🔄 Starting migration from OpenClimb to Ascently..." }
        var migrationCount = 0

        // Migrate SharedPreferences
        migrationCount += migrateSharedPreferences()

        // Mark migration as completed
        migrationPrefs.edit { putBoolean(MIGRATION_COMPLETED_KEY, true) }

        if (migrationCount > 0) {
            AppLogger.i(TAG) { "🎉 Migration completed! Migrated $migrationCount items from OpenClimb to Ascently" }
        } else {
            AppLogger.i(TAG) { "ℹ️ No OpenClimb data found to migrate" }
        }
    }

    /** Migrate SharedPreferences from OpenClimb naming to Ascently naming */
    private fun migrateSharedPreferences(): Int {
        var count = 0

        // Define preference file migrations
        val preferenceFileMigrations =
            listOf(
                "openclimb_data_state" to "ascently_data_state",
                "health_connect_prefs" to "health_connect_prefs", // Keep same name
                "deleted_items" to "deleted_items", // Keep same name
                "sync_preferences" to "sync_preferences", // Keep same name
            )

        for ((oldFileName, newFileName) in preferenceFileMigrations) {
            if (oldFileName != newFileName) {
                count += migratePreferenceFile(oldFileName, newFileName)
            }
        }

        // Migrate specific keys within preference files
        count += migratePreferenceKeys()

        return count
    }

    /** Migrate an entire SharedPreferences file */
    private fun migratePreferenceFile(oldFileName: String, newFileName: String): Int {
        val oldPrefs = context.getSharedPreferences(oldFileName, Context.MODE_PRIVATE)
        val newPrefs = context.getSharedPreferences(newFileName, Context.MODE_PRIVATE)

        // If old prefs exist and new prefs are empty, migrate
        if (oldPrefs.all.isNotEmpty() && newPrefs.all.isEmpty()) {
            newPrefs.edit {
                oldPrefs.all.forEach { (key, value) ->
                    when (value) {
                        is String -> putString(key, value)
                        is Int -> putInt(key, value)
                        is Long -> putLong(key, value)
                        is Float -> putFloat(key, value)
                        is Boolean -> putBoolean(key, value)
                        is Set<*> -> {
                            @Suppress("UNCHECKED_CAST")
                            putStringSet(key, value as Set<String>)
                        }
                    }
                }
            }

            // Clear old preferences
            oldPrefs.edit { clear() }

            AppLogger.d(TAG) { "Migrated preference file: $oldFileName → $newFileName (${oldPrefs.all.size} keys)" }
            return oldPrefs.all.size
        }

        return 0
    }

    /** Migrate specific keys within preference files that might contain openclimb references */
    private fun migratePreferenceKeys(): Int {
        var count = 0

        // Check for any openclimb-prefixed keys across all preference files
        val preferencesToCheck =
            listOf(
                "ascently_data_state",
                "health_connect_prefs",
                "deleted_items",
                "sync_preferences",
            )

        for (prefFileName in preferencesToCheck) {
            val prefs = context.getSharedPreferences(prefFileName, Context.MODE_PRIVATE)
            val keysToMigrate = mutableListOf<Pair<String, String>>()

            // Find keys that start with openclimb_ and should be ascently_
            prefs.all.keys.forEach { key ->
                if (key.startsWith("openclimb_")) {
                    val newKey = key.replace("openclimb_", "ascently_")
                    keysToMigrate.add(key to newKey)
                }
            }

            // Perform the key migrations
            if (keysToMigrate.isNotEmpty()) {
                prefs.edit {
                    keysToMigrate.forEach { (oldKey, newKey) ->
                        val value = prefs.all[oldKey]
                        when (value) {
                            is String -> putString(newKey, value)
                            is Int -> putInt(newKey, value)
                            is Long -> putLong(newKey, value)
                            is Float -> putFloat(newKey, value)
                            is Boolean -> putBoolean(newKey, value)
                            is Set<*> -> {
                                @Suppress("UNCHECKED_CAST")
                                putStringSet(newKey, value as Set<String>)
                            }
                        }
                        remove(oldKey)
                    }
                }

                AppLogger.d(TAG) { "Migrated ${keysToMigrate.size} keys in $prefFileName" }
                count += keysToMigrate.size
            }
        }

        return count
    }

    /** Check if migration has been completed */
    fun isMigrationCompleted(): Boolean {
        return migrationPrefs.getBoolean(MIGRATION_COMPLETED_KEY, false)
    }

    /** Reset migration state (for testing purposes) */
    fun resetMigrationState() {
        migrationPrefs.edit { putBoolean(MIGRATION_COMPLETED_KEY, false) }
        AppLogger.d(TAG) { "Migration state reset" }
    }
}
