package com.rosetta.messenger.data

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.core.stringSetPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

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

class PreferencesManager(private val context: Context) {

    companion object {
        // Onboarding & Theme
        val HAS_SEEN_ONBOARDING = booleanPreferencesKey("has_seen_onboarding")
        val IS_DARK_THEME = booleanPreferencesKey("is_dark_theme")
        val THEME_MODE = stringPreferencesKey("theme_mode") // "light", "dark", "auto"
        val CHAT_WALLPAPER_ID = stringPreferencesKey("chat_wallpaper_id") // empty = no wallpaper
        val CHAT_WALLPAPER_ID_LIGHT = stringPreferencesKey("chat_wallpaper_id_light")
        val CHAT_WALLPAPER_ID_DARK = stringPreferencesKey("chat_wallpaper_id_dark")

        // Notifications
        val NOTIFICATIONS_ENABLED = booleanPreferencesKey("notifications_enabled")
        val NOTIFICATION_SOUND_ENABLED = booleanPreferencesKey("notification_sound_enabled")
        val NOTIFICATION_VIBRATE_ENABLED = booleanPreferencesKey("notification_vibrate_enabled")
        val NOTIFICATION_PREVIEW_ENABLED = booleanPreferencesKey("notification_preview_enabled")
        val NOTIFICATION_AVATAR_ENABLED = booleanPreferencesKey("notification_avatar_enabled")

        // Chat Settings
        val MESSAGE_TEXT_SIZE = intPreferencesKey("message_text_size") // 0=small, 1=medium, 2=large
        val SEND_BY_ENTER = booleanPreferencesKey("send_by_enter")
        val AUTO_DOWNLOAD_PHOTOS = booleanPreferencesKey("auto_download_photos")
        val AUTO_DOWNLOAD_VIDEOS = booleanPreferencesKey("auto_download_videos")
        val AUTO_DOWNLOAD_FILES = booleanPreferencesKey("auto_download_files")
        val CAMERA_FLASH_MODE = intPreferencesKey("camera_flash_mode") // 0=off, 1=auto, 2=on

        // Privacy
        val SHOW_ONLINE_STATUS = booleanPreferencesKey("show_online_status")
        val SHOW_READ_RECEIPTS = booleanPreferencesKey("show_read_receipts")
        val SHOW_TYPING_INDICATOR = booleanPreferencesKey("show_typing_indicator")

        // Language
        val APP_LANGUAGE = stringPreferencesKey("app_language") // "en", "ru", etc.

        // Appearance / Customization (legacy global key)
        val BACKGROUND_BLUR_COLOR_ID =
                stringPreferencesKey("background_blur_color_id") // id from BackgroundBlurPresets

        // App Icon disguise: "default", "calculator", "weather", "notes"
        val APP_ICON = stringPreferencesKey("app_icon")

        // Pinned Chats (max 3)
        val PINNED_CHATS = stringSetPreferencesKey("pinned_chats") // Set of opponent public keys

        // Muted Chats (stored as "account::opponentKey")
        val MUTED_CHATS = stringSetPreferencesKey("muted_chats")
    }

    // ═════════════════════════════════════════════════════════════
    // 🎨 ONBOARDING & THEME
    // ═════════════════════════════════════════════════════════════

    val hasSeenOnboarding: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[HAS_SEEN_ONBOARDING] ?: false }

    val isDarkTheme: Flow<Boolean> =
            context.dataStore.data.map { preferences ->
                preferences[IS_DARK_THEME] ?: true // Default to dark theme like Telegram
            }

    suspend fun setHasSeenOnboarding(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[HAS_SEEN_ONBOARDING] = value }
    }

    suspend fun setDarkTheme(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[IS_DARK_THEME] = value }
    }

    // In-memory cache for instant theme switching (no DataStore disk I/O delay)
    private val _themeMode = MutableStateFlow("dark")
    private val themeModeInitScope = CoroutineScope(Dispatchers.IO)

    init {
        // Load persisted value on startup
        themeModeInitScope.launch {
            val persisted = context.dataStore.data.first()[THEME_MODE] ?: "dark"
            _themeMode.value = persisted
        }
    }

    val themeMode: Flow<String> = _themeMode

    suspend fun setThemeMode(value: String) {
        _themeMode.value = value // Instant in-memory update
        context.dataStore.edit { preferences -> preferences[THEME_MODE] = value } // Persist
    }

    val chatWallpaperId: Flow<String> =
            context.dataStore.data.map { preferences -> preferences[CHAT_WALLPAPER_ID] ?: "" }

    val chatWallpaperIdLight: Flow<String> =
            context.dataStore.data.map { preferences -> preferences[CHAT_WALLPAPER_ID_LIGHT] ?: "" }

    val chatWallpaperIdDark: Flow<String> =
            context.dataStore.data.map { preferences -> preferences[CHAT_WALLPAPER_ID_DARK] ?: "" }

    suspend fun setChatWallpaperId(value: String) {
        context.dataStore.edit { preferences -> preferences[CHAT_WALLPAPER_ID] = value }
    }

    suspend fun setChatWallpaperIdForTheme(isDarkTheme: Boolean, value: String) {
        val key = if (isDarkTheme) CHAT_WALLPAPER_ID_DARK else CHAT_WALLPAPER_ID_LIGHT
        context.dataStore.edit { preferences -> preferences[key] = value }
    }

    // ═════════════════════════════════════════════════════════════
    // 🔔 NOTIFICATIONS
    // ═════════════════════════════════════════════════════════════

    val notificationsEnabled: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[NOTIFICATIONS_ENABLED] ?: true }

    val notificationSoundEnabled: Flow<Boolean> =
            context.dataStore.data.map { preferences ->
                preferences[NOTIFICATION_SOUND_ENABLED] ?: true
            }

    val notificationVibrateEnabled: Flow<Boolean> =
            context.dataStore.data.map { preferences ->
                preferences[NOTIFICATION_VIBRATE_ENABLED] ?: true
            }

    val notificationPreviewEnabled: Flow<Boolean> =
            context.dataStore.data.map { preferences ->
                preferences[NOTIFICATION_PREVIEW_ENABLED] ?: true
            }

    val notificationAvatarEnabled: Flow<Boolean> =
            context.dataStore.data.map { preferences ->
                preferences[NOTIFICATION_AVATAR_ENABLED] ?: true
            }

    suspend fun setNotificationsEnabled(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[NOTIFICATIONS_ENABLED] = value }
    }

    suspend fun setNotificationSoundEnabled(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[NOTIFICATION_SOUND_ENABLED] = value }
    }

    suspend fun setNotificationVibrateEnabled(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[NOTIFICATION_VIBRATE_ENABLED] = value }
    }

    suspend fun setNotificationPreviewEnabled(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[NOTIFICATION_PREVIEW_ENABLED] = value }
    }

    suspend fun setNotificationAvatarEnabled(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[NOTIFICATION_AVATAR_ENABLED] = value }
    }

    // ═════════════════════════════════════════════════════════════
    // 💬 CHAT SETTINGS
    // ═════════════════════════════════════════════════════════════

    val messageTextSize: Flow<Int> =
            context.dataStore.data.map { preferences ->
                preferences[MESSAGE_TEXT_SIZE] ?: 1 // Default medium
            }

    val sendByEnter: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[SEND_BY_ENTER] ?: false }

    val autoDownloadPhotos: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[AUTO_DOWNLOAD_PHOTOS] ?: true }

    val autoDownloadVideos: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[AUTO_DOWNLOAD_VIDEOS] ?: false }

    val autoDownloadFiles: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[AUTO_DOWNLOAD_FILES] ?: false }

    val cameraFlashMode: Flow<Int> =
            context.dataStore.data.map { preferences ->
                normalizeCameraFlashMode(preferences[CAMERA_FLASH_MODE])
            }

    suspend fun setMessageTextSize(value: Int) {
        context.dataStore.edit { preferences -> preferences[MESSAGE_TEXT_SIZE] = value }
    }

    suspend fun setSendByEnter(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[SEND_BY_ENTER] = value }
    }

    suspend fun setAutoDownloadPhotos(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[AUTO_DOWNLOAD_PHOTOS] = value }
    }

    suspend fun setAutoDownloadVideos(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[AUTO_DOWNLOAD_VIDEOS] = value }
    }

    suspend fun setAutoDownloadFiles(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[AUTO_DOWNLOAD_FILES] = value }
    }

    suspend fun getCameraFlashMode(): Int {
        return normalizeCameraFlashMode(context.dataStore.data.first()[CAMERA_FLASH_MODE])
    }

    suspend fun setCameraFlashMode(value: Int) {
        context.dataStore.edit { preferences ->
            preferences[CAMERA_FLASH_MODE] = normalizeCameraFlashMode(value)
        }
    }

    private fun normalizeCameraFlashMode(value: Int?): Int {
        return when (value) {
            0, 1, 2 -> value
            else -> 1
        }
    }

    // ═════════════════════════════════════════════════════════════
    // 🔐 PRIVACY
    // ═════════════════════════════════════════════════════════════

    val showOnlineStatus: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[SHOW_ONLINE_STATUS] ?: true }

    val showReadReceipts: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[SHOW_READ_RECEIPTS] ?: true }

    val showTypingIndicator: Flow<Boolean> =
            context.dataStore.data.map { preferences -> preferences[SHOW_TYPING_INDICATOR] ?: true }

    suspend fun setShowOnlineStatus(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[SHOW_ONLINE_STATUS] = value }
    }

    suspend fun setShowReadReceipts(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[SHOW_READ_RECEIPTS] = value }
    }

    suspend fun setShowTypingIndicator(value: Boolean) {
        context.dataStore.edit { preferences -> preferences[SHOW_TYPING_INDICATOR] = value }
    }

    // ═════════════════════════════════════════════════════════════
    // 🌐 LANGUAGE
    // ═════════════════════════════════════════════════════════════

    val appLanguage: Flow<String> =
            context.dataStore.data.map { preferences ->
                preferences[APP_LANGUAGE] ?: "en" // Default English
            }

    suspend fun setAppLanguage(value: String) {
        context.dataStore.edit { preferences -> preferences[APP_LANGUAGE] = value }
    }

    // ═════════════════════════════════════════════════════════════
    // 🎨 APPEARANCE / CUSTOMIZATION
    // ═════════════════════════════════════════════════════════════

    private fun buildBackgroundBlurColorKey(account: String): Preferences.Key<String>? {
        val trimmedAccount = account.trim()
        if (trimmedAccount.isBlank()) return null
        return stringPreferencesKey("background_blur_color_id::$trimmedAccount")
    }

    val backgroundBlurColorId: Flow<String> =
            context.dataStore.data.map { preferences ->
                preferences[BACKGROUND_BLUR_COLOR_ID] ?: "avatar" // Default: use avatar blur
            }

    suspend fun setBackgroundBlurColorId(value: String) {
        context.dataStore.edit { preferences -> preferences[BACKGROUND_BLUR_COLOR_ID] = value }
    }

    fun backgroundBlurColorIdForAccount(account: String): Flow<String> =
            context.dataStore.data.map { preferences ->
                val scopedKey = buildBackgroundBlurColorKey(account)
                if (scopedKey != null) preferences[scopedKey] ?: "avatar" else "avatar"
            }

    suspend fun setBackgroundBlurColorId(account: String, value: String) {
        val scopedKey = buildBackgroundBlurColorKey(account)
        context.dataStore.edit { preferences ->
            if (scopedKey != null) {
                preferences[scopedKey] = value
            }
        }
    }

    // ═════════════════════════════════════════════════════════════
    // 📌 PINNED CHATS
    // ═════════════════════════════════════════════════════════════

    val pinnedChats: Flow<Set<String>> =
            context.dataStore.data.map { preferences ->
                preferences[PINNED_CHATS] ?: emptySet()
            }

    suspend fun setPinnedChats(value: Set<String>) {
        context.dataStore.edit { preferences -> preferences[PINNED_CHATS] = value }
    }

    suspend fun togglePinChat(opponentKey: String): Boolean {
        var wasPinned = false
        context.dataStore.edit { preferences ->
            val current = preferences[PINNED_CHATS] ?: emptySet()
            if (current.contains(opponentKey)) {
                // Unpin
                preferences[PINNED_CHATS] = current - opponentKey
                wasPinned = true
            } else if (current.size < 3) {
                // Pin (max 3)
                preferences[PINNED_CHATS] = current + opponentKey
            }
        }
        return wasPinned
    }

    // ═════════════════════════════════════════════════════════════
    // 🎨 APP ICON
    // ═════════════════════════════════════════════════════════════

    val appIcon: Flow<String> =
            context.dataStore.data.map { preferences ->
                preferences[APP_ICON] ?: "default"
            }

    suspend fun setAppIcon(value: String) {
        context.dataStore.edit { preferences -> preferences[APP_ICON] = value }
    }

    // ═════════════════════════════════════════════════════════════
    // 🔕 MUTED CHATS
    // ═════════════════════════════════════════════════════════════

    private fun buildMutedKey(account: String, opponentKey: String): String {
        val trimmedAccount = account.trim()
        val trimmedOpponent = opponentKey.trim()
        return if (trimmedAccount.isBlank()) trimmedOpponent else "$trimmedAccount::$trimmedOpponent"
    }

    private fun parseMutedKeyForAccount(rawKey: String, account: String): String? {
        val trimmedAccount = account.trim()
        if (rawKey.isBlank()) return null

        // Legacy format support: plain opponentKey without account prefix.
        if ("::" !in rawKey) return rawKey

        val parts = rawKey.split("::", limit = 2)
        if (parts.size != 2) return null
        val keyAccount = parts[0]
        val opponentKey = parts[1]
        return if (trimmedAccount.isBlank() || keyAccount == trimmedAccount) opponentKey else null
    }

    val mutedChats: Flow<Set<String>> =
            context.dataStore.data.map { preferences -> preferences[MUTED_CHATS] ?: emptySet() }

    fun mutedChatsForAccount(account: String): Flow<Set<String>> =
            mutedChats.map { muted ->
                muted.mapNotNull { parseMutedKeyForAccount(it, account) }.toSet()
            }

    suspend fun isChatMuted(account: String, opponentKey: String): Boolean {
        if (opponentKey.isBlank()) return false
        val current = mutedChats.first()
        return current.contains(buildMutedKey(account, opponentKey)) || current.contains(opponentKey)
    }

    suspend fun setChatMuted(account: String, opponentKey: String, muted: Boolean) {
        if (opponentKey.isBlank()) return
        val scopedKey = buildMutedKey(account, opponentKey)
        context.dataStore.edit { preferences ->
            val current = preferences[MUTED_CHATS] ?: emptySet()
            preferences[MUTED_CHATS] =
                    if (muted) {
                        current + scopedKey
                    } else {
                        current - scopedKey - opponentKey
                    }
        }
    }

    suspend fun toggleMuteChat(account: String, opponentKey: String): Boolean {
        if (opponentKey.isBlank()) return false
        val mutedNow = !isChatMuted(account, opponentKey)
        setChatMuted(account, opponentKey, mutedNow)
        return mutedNow
    }
}
