import Foundation
import GRDB

/// One-time migration from legacy JSON persistence (ChatPersistenceStore) to SQLite.
/// Runs on first launch after the SQLite migration. After successful migration,
/// sets a UserDefaults flag so it never runs again.
enum DatabaseMigrationFromJSON {

    /// Migrate legacy JSON data for the given account into the SQLite database.
    /// Returns the number of messages migrated.
    @MainActor
    static func migrateIfNeeded(
        accountPublicKey: String,
        storagePassword: String
    ) async -> Int {
        let flagKey = "sqlite_migration_done_\(accountPublicKey.prefix(16))"

        // Check if migration already done AND data exists in SQLite
        if UserDefaults.standard.bool(forKey: flagKey) {
            // Verify data actually exists — if DB is empty, re-migrate
            let hasData: Bool
            do {
                hasData = try DatabaseManager.shared.read { db in
                    try DialogRecord.filter(DialogRecord.Columns.account == accountPublicKey)
                        .fetchCount(db) > 0
                }
            } catch { hasData = false }
            if hasData { return 0 }
            // DB is empty despite flag — reset flag and re-migrate
            UserDefaults.standard.removeObject(forKey: flagKey)
        }

        var totalMessages = 0

        // 1. Load dialogs from legacy JSON
        let dialogsFileName = ChatPersistenceStore.accountScopedFileName(
            prefix: "dialogs", accountPublicKey: accountPublicKey
        )
        let legacyDialogs = await ChatPersistenceStore.shared.load(
            [Dialog].self,
            fileName: dialogsFileName,
            password: storagePassword
        ) ?? []

        // 2. Load messages from legacy JSON
        let messagesFileName = ChatPersistenceStore.accountScopedFileName(
            prefix: "messages", accountPublicKey: accountPublicKey
        )
        let legacyMessages = await ChatPersistenceStore.shared.load(
            [String: [ChatMessage]].self,
            fileName: messagesFileName,
            password: storagePassword
        ) ?? [:]

        // Nothing to migrate
        if legacyDialogs.isEmpty && legacyMessages.isEmpty {
            UserDefaults.standard.set(true, forKey: flagKey)
            return 0
        }

        // 3. Insert into SQLite in a single transaction
        do {
            try DatabaseManager.shared.writeSync { db in
                // Insert dialogs
                for dialog in legacyDialogs where dialog.account == accountPublicKey {
                    var record = DialogRecord.from(dialog)
                    try record.insert(db, onConflict: .ignore)
                }

                // Insert messages
                for (_, messages) in legacyMessages {
                    for message in messages {
                        var record = MessageRecord.from(message, account: accountPublicKey)
                        try record.insert(db, onConflict: .ignore)
                        totalMessages += 1
                    }
                }
            }

            // 4. Mark migration as done
            UserDefaults.standard.set(true, forKey: flagKey)
            print("[DB Migration] Success: \(legacyDialogs.count) dialogs, \(totalMessages) messages")
        } catch {
            print("[DB Migration] Failed: \(error)")
        }

        return totalMessages
    }
}
