package com.rosetta.messenger.database

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase

@Database(
        entities =
                [
                        EncryptedAccountEntity::class,
                        MessageEntity::class,
                        DialogEntity::class,
                        BlacklistEntity::class,
                        AvatarCacheEntity::class,
                        AccountSyncTimeEntity::class,
                        GroupEntity::class,
                        PinnedMessageEntity::class],
        version = 14,
        exportSchema = false
)
abstract class RosettaDatabase : RoomDatabase() {
    abstract fun accountDao(): AccountDao
    abstract fun messageDao(): MessageDao
    abstract fun dialogDao(): DialogDao
    abstract fun blacklistDao(): BlacklistDao
    abstract fun avatarDao(): AvatarDao
    abstract fun syncTimeDao(): SyncTimeDao
    abstract fun groupDao(): GroupDao
    abstract fun pinnedMessageDao(): PinnedMessageDao

    companion object {
        @Volatile private var INSTANCE: RosettaDatabase? = null

        private val MIGRATION_4_5 =
                object : Migration(4, 5) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        // Добавляем новые столбцы для индикаторов прочтения
                        database.execSQL(
                                "ALTER TABLE dialogs ADD COLUMN last_message_from_me INTEGER NOT NULL DEFAULT 0"
                        )
                        database.execSQL(
                                "ALTER TABLE dialogs ADD COLUMN last_message_delivered INTEGER NOT NULL DEFAULT 0"
                        )
                        database.execSQL(
                                "ALTER TABLE dialogs ADD COLUMN last_message_read INTEGER NOT NULL DEFAULT 0"
                        )
                    }
                }

        private val MIGRATION_5_6 =
                object : Migration(5, 6) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        // Добавляем поле username в encrypted_accounts
                        database.execSQL("ALTER TABLE encrypted_accounts ADD COLUMN username TEXT")
                    }
                }

        private val MIGRATION_6_7 =
                object : Migration(6, 7) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        // Создаем таблицу для кэша аватаров
                        database.execSQL(
                                """
                    CREATE TABLE IF NOT EXISTS avatar_cache (
                        id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
                        public_key TEXT NOT NULL,
                        avatar TEXT NOT NULL,
                        timestamp INTEGER NOT NULL
                    )
                """
                        )
                        database.execSQL(
                                "CREATE INDEX IF NOT EXISTS index_avatar_cache_public_key_timestamp ON avatar_cache (public_key, timestamp)"
                        )
                    }
                }

        private val MIGRATION_7_8 =
                object : Migration(7, 8) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        // Удаляем таблицу avatar_delivery (больше не нужна)
                        database.execSQL("DROP TABLE IF EXISTS avatar_delivery")
                    }
                }

        /**
         * 🔥 МИГРАЦИЯ 8->9: Очищаем blob из attachments (как в desktop) Blob слишком большой для
         * SQLite CursorWindow (2MB лимит) Просто обнуляем attachments - изображения перескачаются с
         * CDN
         */
        private val MIGRATION_8_9 =
                object : Migration(8, 9) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        // Очищаем все attachments с большими blob'ами
                        // Они будут перескачаны с CDN при открытии
                        database.execSQL(
                                """
                    UPDATE messages 
                    SET attachments = '[]'
                    WHERE length(attachments) > 10000
                """
                        )
                    }
                }

        /**
         * 🔥 МИГРАЦИЯ 9->10: Повторная очистка blob из attachments Для пользователей которые уже
         * были на версии 9
         */
        private val MIGRATION_9_10 =
                object : Migration(9, 10) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        // Очищаем все attachments с большими blob'ами
                        database.execSQL(
                                """
                    UPDATE messages 
                    SET attachments = '[]'
                    WHERE length(attachments) > 10000
                """
                        )
                    }
                }

        /**
         * 🚀 МИГРАЦИЯ 10->11: Денормализация — кэш attachments последнего сообщения в dialogs
         * Устраняет N+1 проблему: ранее для каждого диалога делался отдельный запрос к messages
         */
        private val MIGRATION_10_11 =
                object : Migration(10, 11) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        // Добавляем столбец для кэша attachments последнего сообщения
                        database.execSQL(
                                "ALTER TABLE dialogs ADD COLUMN last_message_attachments TEXT NOT NULL DEFAULT '[]'"
                        )
                    }
                }

        private val MIGRATION_11_12 =
                object : Migration(11, 12) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        database.execSQL(
                                """
                    CREATE TABLE IF NOT EXISTS accounts_sync_times (
                        account TEXT NOT NULL PRIMARY KEY,
                        last_sync INTEGER NOT NULL
                    )
                """
                        )
                    }
                }

        /**
         * 📌 МИГРАЦИЯ 12->13: Таблица pinned_messages для закреплённых сообщений (Telegram-style)
         */
        private val MIGRATION_12_13 =
                object : Migration(12, 13) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        database.execSQL(
                                """
                    CREATE TABLE IF NOT EXISTS pinned_messages (
                        id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
                        account TEXT NOT NULL,
                        dialog_key TEXT NOT NULL,
                        message_id TEXT NOT NULL,
                        pinned_at INTEGER NOT NULL
                    )
                """
                        )
                        database.execSQL(
                                "CREATE UNIQUE INDEX IF NOT EXISTS index_pinned_messages_account_dialog_key_message_id ON pinned_messages (account, dialog_key, message_id)"
                        )
                        database.execSQL(
                                "CREATE INDEX IF NOT EXISTS index_pinned_messages_account_dialog_key_pinned_at ON pinned_messages (account, dialog_key, pinned_at)"
                        )
                    }
                }

        /**
         * 👥 МИГРАЦИЯ 13->14: Таблица groups для групповых диалогов
         */
        private val MIGRATION_13_14 =
                object : Migration(13, 14) {
                    override fun migrate(database: SupportSQLiteDatabase) {
                        database.execSQL(
                                """
                    CREATE TABLE IF NOT EXISTS groups (
                        id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
                        account TEXT NOT NULL,
                        group_id TEXT NOT NULL,
                        title TEXT NOT NULL,
                        description TEXT NOT NULL,
                        `key` TEXT NOT NULL
                    )
                """
                        )
                        database.execSQL(
                                "CREATE UNIQUE INDEX IF NOT EXISTS index_groups_account_group_id ON groups (account, group_id)"
                        )
                    }
                }

        fun getDatabase(context: Context): RosettaDatabase {
            return INSTANCE
                    ?: synchronized(this) {
                        val instance =
                                Room.databaseBuilder(
                                                context.applicationContext,
                                                RosettaDatabase::class.java,
                                                "rosetta_secure.db"
                                        )
                                        .setJournalMode(
                                                JournalMode.WRITE_AHEAD_LOGGING
                                        ) // WAL mode for performance
                                        .addMigrations(
                                                MIGRATION_4_5,
                                                MIGRATION_5_6,
                                                MIGRATION_6_7,
                                                MIGRATION_7_8,
                                                MIGRATION_8_9,
                                                MIGRATION_9_10,
                                                MIGRATION_10_11,
                                                MIGRATION_11_12,
                                                MIGRATION_12_13,
                                                MIGRATION_13_14
                                        )
                                        .fallbackToDestructiveMigration() // Для разработки - только
                                        // если миграция не
                                        // найдена
                                        .build()
                        INSTANCE = instance
                        instance
                    }
        }
    }
}
