import { Platform } from 'react-native';
import * as Keychain from 'react-native-keychain';

import { sleep } from './SleepUtils';
import { settingsStore } from '../stores/Stores';
import {
    Settings,
    DEFAULT_FIAT_RATES_SOURCE,
    DEFAULT_FIAT,
    DEFAULT_LSP_MAINNET,
    DEFAULT_LSP_TESTNET,
    DEFAULT_NOSTR_RELAYS,
    localeMigrationMapping,
    DEFAULT_NEUTRINO_PEERS_MAINNET,
    DEFAULT_NEUTRINO_PEERS_TESTNET,
    DEFAULT_LSPS1_HOST_MAINNET,
    DEFAULT_LSPS1_HOST_TESTNET,
    DEFAULT_LSPS1_PUBKEY_MAINNET,
    DEFAULT_LSPS1_PUBKEY_TESTNET,
    DEFAULT_LSPS1_REST_MAINNET,
    DEFAULT_LSPS1_REST_TESTNET,
    DEFAULT_SPEEDLOADER,
    DEFAULT_NOSTR_RELAYS_2023,
    PosEnabled,
    DEFAULT_SLIDE_TO_PAY_THRESHOLD,
    STORAGE_KEY,
    LEGACY_CURRENCY_CODES_KEY,
    CURRENCY_CODES_KEY
} from '../stores/SettingsStore';

import { LEGACY_NOTES_KEY, NOTES_KEY } from '../stores/NotesStore';
import { LEGACY_CONTACTS_KEY, CONTACTS_KEY } from '../stores/ContactStore';
import {
    LEGACY_LAST_CHANNEL_BACKUP_STATUS,
    LEGACY_LAST_CHANNEL_BACKUP_TIME,
    LAST_CHANNEL_BACKUP_STATUS,
    LAST_CHANNEL_BACKUP_TIME
} from '../stores/ChannelBackupStore';
import {
    LEGACY_ADDRESS_ACTIVATED_STRING,
    LEGACY_HASHES_STORAGE_STRING,
    ADDRESS_ACTIVATED_STRING,
    HASHES_STORAGE_STRING
} from '../stores/LightningAddressStore';
import {
    LEGACY_POS_HIDDEN_KEY,
    LEGACY_POS_STANDALONE_KEY,
    POS_HIDDEN_KEY,
    POS_STANDALONE_KEY
} from '../stores/PosStore';
import {
    LEGACY_CATEGORY_KEY,
    LEGACY_PRODUCT_KEY,
    CATEGORY_KEY,
    PRODUCT_KEY
} from '../stores/InventoryStore';
import { LEGACY_UNIT_KEY, UNIT_KEY } from '../stores/UnitsStore';
import {
    LEGACY_HIDDEN_ACCOUNTS_KEY,
    HIDDEN_ACCOUNTS_KEY
} from '../stores/UTXOsStore';

import { LEGACY_LSPS1_ORDERS_KEY, LSPS_ORDERS_KEY } from '../stores/LSPStore';

import { LNC_STORAGE_KEY, hash } from '../backends/LNC/credentialStore';

import {
    SWAPS_KEY,
    REVERSE_SWAPS_KEY,
    SWAPS_RESCUE_KEY,
    SWAPS_LAST_USED_KEY
} from '../utils/SwapUtils';

import {
    LEGACY_ACTIVITY_FILTERS_KEY,
    ACTIVITY_FILTERS_KEY
} from '../stores/ActivityStore';

const LEGACY_IS_BACKED_UP_KEY = 'backup-complete';
export const IS_BACKED_UP_KEY = 'backup-complete-v2';

const KEYCHAIN_MIGRATION_KEY = 'ios-keychain-cloud-sync-migration-v1';
const CASHU_MIGRATION_KEY = 'ios-keychain-cashu-fix-v1';

import EncryptedStorage from 'react-native-encrypted-storage';
import Storage from '../storage';

class MigrationsUtils {
    /**
     * Migrates a key from old keychain (cloud or local) to new Storage namespace.
     * Safe order: read → write → verify → delete
     *
     * Since Storage now uses a "zeus:" prefix, old and new keys are in different
     * namespaces, so deleting old keys won't affect newly written data.
     */
    private async migrateKey(key: string): Promise<string | null> {
        try {
            // 1. Check if already migrated to new Storage namespace
            const existingData = await Storage.getItem(key);
            if (existingData) return existingData;

            // 2. Read from old keychain (local first, then cloud)
            const credentials = await this.readFromOldKeychain(key);
            if (!credentials) return null;

            console.log(`[Migration] Moving ${key} to Local Storage...`);

            // iOS: Add delay after read to allow iCloud sync
            if (Platform.OS === 'ios') {
                await sleep(500);
            }

            // 3. Write to new Storage namespace (zeus:key)
            const writeSuccess = await Storage.setItem(
                key,
                credentials.password
            );

            if (!writeSuccess) {
                throw new Error(
                    `Write failed for ${key}. Storage.setItem returned false.`
                );
            }

            // 4. Verify write succeeded by reading back
            const verifyData = await Storage.getItem(key);
            if (!verifyData) {
                throw new Error(
                    `Verification failed for ${key}. Data not found after write.`
                );
            }

            // iOS: Add delay before delete to allow iCloud sync
            if (Platform.OS === 'ios') {
                await sleep(500);
            }

            // 5. Only delete old keychain entries after successful write + verify
            await this.deleteFromOldKeychain(key);

            console.log(`[Migration] Successfully migrated ${key}`);
            return credentials.password;
        } catch (error) {
            console.error(`[Migration] Failed to migrate ${key}:`, error);
            throw error;
        }
    }

    /**
     * Reads from old keychain (without zeus: prefix).
     * Tries local keychain first, then cloud keychain as fallback.
     */
    private async readFromOldKeychain(key: string) {
        try {
            // Try local keychain first
            const localCreds = await Keychain.getInternetCredentials(key);
            if (localCreds) return localCreds;

            // Fallback to cloud keychain
            return await Keychain.getInternetCredentials(key, {
                cloudSync: true
            });
        } catch (e) {
            console.warn(`[Migration] Read error for ${key}`, e);
            return null;
        }
    }

    /**
     * Deletes from old keychain entries (without zeus: prefix).
     *
     * DISABLED: To prevent potential data loss during migration.
     * Old keychain entries will remain but are harmless (orphaned data).
     * The new Storage uses a "zeus:" prefix, so old and new keys don't conflict.
     */
    private async deleteFromOldKeychain(key: string) {
        // Safety measure: skip deletion to prevent any potential data loss
        console.log(`[Migration] Skipping delete for ${key} (safety measure)`);
        return;

        // Original delete code - commented out for safety:
        // try {
        //     await Keychain.resetInternetCredentials({
        //         server: key,
        //         cloudSync: true
        //     });
        // } catch (e) {
        //     console.warn(
        //         `[Migration] Error deleting from cloud keychain: ${key}`,
        //         e
        //     );
        // }
        // try {
        //     await Keychain.resetInternetCredentials({ server: key });
        // } catch (e) {
        //     console.warn(
        //         `[Migration] Error deleting from local keychain: ${key}`,
        //         e
        //     );
        // }
    }

    private async migrateCashuForNode(lndDir: string) {
        console.log(`Migrating Cashu data for node: ${lndDir}`);

        const cashuKeys = [
            `${lndDir}-cashu-mintUrls`,
            `${lndDir}-cashu-selectedMintUrl`,
            `${lndDir}-cashu-totalBalanceSats`,
            `${lndDir}-cashu-invoices`,
            `${lndDir}-cashu-payments`,
            `${lndDir}-cashu-received-tokens`,
            `${lndDir}-cashu-sent-tokens`,
            `${lndDir}-cashu-seed-version`,
            `${lndDir}-cashu-seed-phrase`,
            `${lndDir}-cashu-seed`
        ];

        for (const key of cashuKeys) {
            await this.migrateKey(key);
        }

        const mintUrlsJson = await this.migrateKey(`${lndDir}-cashu-mintUrls`);

        if (mintUrlsJson) {
            try {
                const mintUrls = JSON.parse(mintUrlsJson);
                if (Array.isArray(mintUrls)) {
                    for (const mintUrl of mintUrls) {
                        const walletId = `${lndDir}==${mintUrl}`;
                        const walletKeys = [
                            `${walletId}-mintInfo`,
                            `${walletId}-counter`,
                            `${walletId}-proofs`,
                            `${walletId}-balance`,
                            `${walletId}-pubkey`
                        ];
                        for (const wKey of walletKeys) {
                            await this.migrateKey(wKey);
                        }
                    }
                }
            } catch (e) {
                console.warn(`Failed to parse mintUrls for ${lndDir}`, e);
            }
        }
    }

    public async legacySettingsMigrations(settings: string) {
        const newSettings = JSON.parse(settings) as Settings;
        if (!newSettings.fiatRatesSource) {
            newSettings.fiatRatesSource = DEFAULT_FIAT_RATES_SOURCE;
        }

        // migrate fiat settings from older versions
        if (!newSettings.fiat || newSettings.fiat === 'Disabled') {
            newSettings.fiat = DEFAULT_FIAT;
            newSettings.fiatEnabled = false;
        } else if (newSettings.fiatEnabled == null) {
            newSettings.fiatEnabled = true;
        }

        // set default LSPs if not defined
        if (newSettings.enableLSP === undefined) {
            newSettings.enableLSP = true;
        }
        if (!newSettings.lspMainnet) {
            newSettings.lspMainnet = DEFAULT_LSP_MAINNET;
        }
        if (!newSettings.lspTestnet) {
            newSettings.lspTestnet = DEFAULT_LSP_TESTNET;
        }

        // default Lightning Address settings
        if (!newSettings.lightningAddress) {
            newSettings.lightningAddress = {
                enabled: false,
                automaticallyAccept: true,
                automaticallyAcceptAttestationLevel: 2,
                automaticallyRequestOlympusChannels: false, // deprecated
                routeHints: false,
                allowComments: true,
                nostrPrivateKey: '',
                nostrRelays: DEFAULT_NOSTR_RELAYS,
                notifications: 0,
                mintUrl: '' // Cashu
            };
        }

        // migrate locale to ISO 639-1
        if (
            newSettings.locale != null &&
            localeMigrationMapping[newSettings.locale]
        ) {
            newSettings.locale = localeMigrationMapping[newSettings.locale];
        }

        const MOD_KEY = 'lsp-taproot-mod';
        const mod = await EncryptedStorage.getItem(MOD_KEY);
        if (!mod) {
            newSettings.requestSimpleTaproot = true;
            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY, 'true');
        }

        const MOD_KEY2 = 'lsp-preview-mod';
        const mod2 = await EncryptedStorage.getItem(MOD_KEY2);
        if (!mod2) {
            if (newSettings?.lspMainnet === 'https://lsp-preview.lnolymp.us') {
                newSettings.lspMainnet = DEFAULT_LSP_MAINNET;
            }
            if (newSettings?.lspTestnet === 'https://testnet-lsp.lnolymp.us') {
                newSettings.lspTestnet = DEFAULT_LSP_TESTNET;
            }
            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY2, 'true');
        }

        const MOD_KEY3 = 'neutrino-peers-mod1';
        const mod3 = await EncryptedStorage.getItem(MOD_KEY3);
        if (!mod3) {
            const neutrinoPeersMainnetOld = [
                'btcd1.lnolymp.us',
                'btcd2.lnolymp.us',
                'btcd-mainnet.lightning.computer',
                'node.eldamar.icu',
                'noad.sathoarder.com'
            ];
            if (
                JSON.stringify(newSettings?.neutrinoPeersMainnet) ===
                JSON.stringify(neutrinoPeersMainnetOld)
            ) {
                newSettings.neutrinoPeersMainnet =
                    DEFAULT_NEUTRINO_PEERS_MAINNET;
            }
            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY3, 'true');
        }

        const MOD_KEY4 = 'lsps1-hosts1';
        const mod4 = await EncryptedStorage.getItem(MOD_KEY4);
        if (!mod4) {
            if (!newSettings?.lsps1HostMainnet) {
                newSettings.lsps1HostMainnet = DEFAULT_LSPS1_HOST_MAINNET;
            }
            if (!newSettings?.lsps1HostTestnet) {
                newSettings.lsps1HostTestnet = DEFAULT_LSPS1_HOST_TESTNET;
            }
            if (!newSettings?.lsps1PubkeyMainnet) {
                newSettings.lsps1PubkeyMainnet = DEFAULT_LSPS1_PUBKEY_MAINNET;
            }
            if (!newSettings?.lsps1PubkeyTestnet) {
                newSettings.lsps1PubkeyTestnet = DEFAULT_LSPS1_PUBKEY_TESTNET;
            }
            if (!newSettings?.lsps1RestMainnet) {
                newSettings.lsps1RestMainnet = DEFAULT_LSPS1_REST_MAINNET;
            }
            if (!newSettings?.lsps1RestTestnet) {
                newSettings.lsps1RestTestnet = DEFAULT_LSPS1_REST_TESTNET;
            }

            if (!newSettings?.lsps1Token) {
                newSettings.lsps1Token = '';
            }

            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY4, 'true');
        }

        const MOD_KEY5 = 'millisat_amounts';
        const mod5 = await EncryptedStorage.getItem(MOD_KEY5);
        if (!mod5) {
            if (!newSettings?.display?.showMillisatoshiAmounts) {
                if (!newSettings.display) {
                    newSettings.display = {
                        showMillisatoshiAmounts: true
                    };
                } else {
                    newSettings.display.showMillisatoshiAmounts = true;
                }
            }

            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY5, 'true');
        }

        const MOD_KEY6 = 'egs-host';
        const mod6 = await EncryptedStorage.getItem(MOD_KEY6);
        if (!mod6) {
            if (!newSettings?.speedloader) {
                newSettings.speedloader = DEFAULT_SPEEDLOADER;
                newSettings.customSpeedloader = '';
            }

            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY6, 'true');
        }

        // switch off bimodal pathfinding while bug exists
        // https://github.com/lightningnetwork/lnd/issues/9085
        const MOD_KEY7 = 'bimodal-bug-9085';
        const mod7 = await EncryptedStorage.getItem(MOD_KEY7);
        if (!mod7) {
            if (newSettings?.bimodalPathfinding) {
                newSettings.bimodalPathfinding = false;
            }

            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY7, 'true');
        }

        const MOD_KEY8 = 'nostr-relays-2024';
        const mod8 = await EncryptedStorage.getItem(MOD_KEY8);
        if (!mod8) {
            if (
                JSON.stringify(newSettings?.lightningAddress?.nostrRelays) ===
                JSON.stringify(DEFAULT_NOSTR_RELAYS_2023)
            ) {
                newSettings.lightningAddress.nostrRelays = DEFAULT_NOSTR_RELAYS;
            }

            settingsStore.setSettings(JSON.stringify(newSettings));
            await EncryptedStorage.setItem(MOD_KEY8, 'true');
        }

        // migrate old POS squareEnabled setting to posEnabled
        if (newSettings?.pos?.squareEnabled) {
            newSettings.pos.posEnabled = PosEnabled.Square;
            newSettings.pos.squareEnabled = false;
        }

        if (!newSettings.neutrinoPeersMainnet) {
            newSettings.neutrinoPeersMainnet = DEFAULT_NEUTRINO_PEERS_MAINNET;
        }
        if (!newSettings.neutrinoPeersTestnet) {
            newSettings.neutrinoPeersTestnet = DEFAULT_NEUTRINO_PEERS_TESTNET;
        }

        if (newSettings.payments == null) {
            newSettings.payments = {
                slideToPayThreshold: DEFAULT_SLIDE_TO_PAY_THRESHOLD
            };
        } else if (newSettings.payments.slideToPayThreshold == null) {
            newSettings.payments.slideToPayThreshold =
                DEFAULT_SLIDE_TO_PAY_THRESHOLD;
        }

        return newSettings;
    }

    public async storageMigrationV2(settings: any) {
        const migrationTasks = [];

        // Settings migration
        console.log('Attemping settings migration');
        const settingsMigration = Storage.setItem(STORAGE_KEY, settings).then(
            (writeSuccess) => {
                console.log('Settings migration status', writeSuccess);
                return writeSuccess;
            }
        );
        migrationTasks.push(settingsMigration);

        // Contacts migration
        const contactsMigration = (async () => {
            try {
                const contacts = await EncryptedStorage.getItem(
                    LEGACY_CONTACTS_KEY
                );
                if (contacts) {
                    console.log('Attemping contacts migration');
                    const writeSuccess = await Storage.setItem(
                        CONTACTS_KEY,
                        contacts
                    );
                    console.log('Contacts migration status', writeSuccess);
                    return writeSuccess;
                }
            } catch (error) {
                console.error(
                    'Error loading contacts from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(contactsMigration);

        // Notes migration
        const notesMigration = (async () => {
            try {
                const storedKeys = await EncryptedStorage.getItem(
                    LEGACY_NOTES_KEY
                );
                if (storedKeys) {
                    const noteKeys = JSON.parse(storedKeys);
                    console.log('Attemping notes migration');
                    const writeSuccess = await Storage.setItem(
                        NOTES_KEY,
                        noteKeys
                    );
                    console.log('Notes keys migration status', writeSuccess);

                    // Load all legacy notes
                    const notesPromises = noteKeys.map(async (key: string) => {
                        const note = await EncryptedStorage.getItem(key);
                        if (note) {
                            const writeSuccess = await Storage.setItem(
                                key,
                                note
                            );
                            console.log(
                                `Notes keys migration status: ${key}`,
                                writeSuccess
                            );
                            return writeSuccess;
                        }
                    });

                    const noteResults = await Promise.all(notesPromises);
                    return (
                        writeSuccess &&
                        noteResults.every((result) => result !== false)
                    );
                }
            } catch (error) {
                console.error(
                    'Error loading note keys from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(notesMigration);

        // Lightning address migration
        const lightningAddressMigration = (async () => {
            try {
                let activatedSuccess: any = true;
                let hashesSuccess: any = true;

                const activated = await EncryptedStorage.getItem(
                    LEGACY_ADDRESS_ACTIVATED_STRING
                );
                if (activated) {
                    console.log(
                        'Attemping lightning address activated migration'
                    );
                    activatedSuccess = await Storage.setItem(
                        ADDRESS_ACTIVATED_STRING,
                        activated
                    );
                    console.log(
                        'Lightning address activated migration status',
                        activatedSuccess
                    );
                }

                const hashes = await EncryptedStorage.getItem(
                    LEGACY_HASHES_STORAGE_STRING
                );
                if (hashes) {
                    console.log('Attemping lightning address hashes migration');
                    hashesSuccess = await Storage.setItem(
                        HASHES_STORAGE_STRING,
                        hashes
                    );
                    console.log(
                        'Lightning address hashes migration status',
                        hashesSuccess
                    );
                }

                return activatedSuccess && hashesSuccess;
            } catch (error) {
                console.error(
                    'Error loading lightning address data from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(lightningAddressMigration);

        // Backup status migration
        const backupStatusMigration = (async () => {
            try {
                let statusSuccess: any = true;
                let timeSuccess: any = true;

                const status = await EncryptedStorage.getItem(
                    LEGACY_LAST_CHANNEL_BACKUP_STATUS
                );
                if (status) {
                    console.log('Attemping backup status migration');
                    statusSuccess = await Storage.setItem(
                        LAST_CHANNEL_BACKUP_STATUS,
                        status
                    );
                    console.log(
                        'Backup status migration status',
                        statusSuccess
                    );
                }

                const time = await EncryptedStorage.getItem(
                    LEGACY_LAST_CHANNEL_BACKUP_TIME
                );
                if (time) {
                    console.log('Attemping backup time migration');
                    timeSuccess = await Storage.setItem(
                        LAST_CHANNEL_BACKUP_TIME,
                        time
                    );
                    console.log('Backup time migration status', timeSuccess);
                }

                return statusSuccess && timeSuccess;
            } catch (error) {
                console.error(
                    'Error loading backup status from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(backupStatusMigration);

        // POS migration
        const posMigration = (async () => {
            try {
                let hiddenKeySuccess: any = true;
                let standaloneKeySuccess: any = true;
                let categoriesSuccess: any = true;
                let productsSuccess: any = true;

                const posHiddenKey = await EncryptedStorage.getItem(
                    LEGACY_POS_HIDDEN_KEY
                );
                if (posHiddenKey) {
                    console.log('Attemping POS hidden key migration');
                    hiddenKeySuccess = await Storage.setItem(
                        POS_HIDDEN_KEY,
                        posHiddenKey
                    );
                    console.log(
                        'POS hidden key migration status',
                        hiddenKeySuccess
                    );
                }

                const posStandaloneKey = await EncryptedStorage.getItem(
                    LEGACY_POS_STANDALONE_KEY
                );
                if (posStandaloneKey) {
                    console.log('Attemping POS standalone key migration');
                    standaloneKeySuccess = await Storage.setItem(
                        POS_STANDALONE_KEY,
                        posStandaloneKey
                    );
                    console.log(
                        'POS standalone key migration status',
                        standaloneKeySuccess
                    );
                }

                const categories = await EncryptedStorage.getItem(
                    LEGACY_CATEGORY_KEY
                );
                if (categories) {
                    console.log('Attemping POS categories migration');
                    categoriesSuccess = await Storage.setItem(
                        CATEGORY_KEY,
                        categories
                    );
                    console.log(
                        'POS categories migration status',
                        categoriesSuccess
                    );
                }

                const products = await EncryptedStorage.getItem(
                    LEGACY_PRODUCT_KEY
                );
                if (products) {
                    console.log('Attemping POS products migration');
                    productsSuccess = await Storage.setItem(
                        PRODUCT_KEY,
                        products
                    );
                    console.log(
                        'POS products migration status',
                        productsSuccess
                    );
                }

                return (
                    hiddenKeySuccess &&
                    standaloneKeySuccess &&
                    categoriesSuccess &&
                    productsSuccess
                );
            } catch (error) {
                console.error(
                    'Error loading POS data from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(posMigration);

        // Units migration
        const unitsMigration = (async () => {
            try {
                const units = await EncryptedStorage.getItem(LEGACY_UNIT_KEY);
                if (units) {
                    console.log('Attemping units migration');
                    const writeSuccess = await Storage.setItem(UNIT_KEY, units);
                    console.log('Units migration status', writeSuccess);
                    return writeSuccess;
                }
            } catch (error) {
                console.error(
                    'Error loading units data from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(unitsMigration);

        // Hidden accounts migration
        const hiddenAccountsMigration = (async () => {
            try {
                const accounts = await EncryptedStorage.getItem(
                    LEGACY_HIDDEN_ACCOUNTS_KEY
                );
                if (accounts) {
                    console.log('Attemping hidden accounts migration');
                    const writeSuccess = await Storage.setItem(
                        HIDDEN_ACCOUNTS_KEY,
                        accounts
                    );
                    console.log(
                        'Hidden accounts migration status',
                        writeSuccess
                    );
                    return writeSuccess;
                }
            } catch (error) {
                console.error(
                    'Error loading hidden accounts from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(hiddenAccountsMigration);

        // Currency codes migration
        const currencyCodesMigration = (async () => {
            try {
                const currencyCodes = await EncryptedStorage.getItem(
                    LEGACY_CURRENCY_CODES_KEY
                );
                if (currencyCodes) {
                    console.log('Attemping currency codes migration');
                    const writeSuccess = await Storage.setItem(
                        CURRENCY_CODES_KEY,
                        currencyCodes
                    );
                    console.log(
                        'Currency codes migration status',
                        writeSuccess
                    );
                    return writeSuccess;
                }
            } catch (error) {
                console.error(
                    'Error loading currency codes from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(currencyCodesMigration);

        // Activity filters migration
        const activityFiltersMigration = (async () => {
            try {
                const activityFilters = await EncryptedStorage.getItem(
                    LEGACY_ACTIVITY_FILTERS_KEY
                );
                if (activityFilters) {
                    console.log('Attemping activity filters migration');
                    const writeSuccess = await Storage.setItem(
                        ACTIVITY_FILTERS_KEY,
                        activityFilters
                    );
                    console.log(
                        'Activity filters migration status',
                        writeSuccess
                    );
                    return writeSuccess;
                }
            } catch (error) {
                console.error(
                    'Error loading activity filters from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(activityFiltersMigration);

        // Embedded LND is backed up migration
        const embeddedLndIsBackedUpMigration = (async () => {
            try {
                const embeddedLndIsBackedUp = await EncryptedStorage.getItem(
                    LEGACY_IS_BACKED_UP_KEY
                );
                if (embeddedLndIsBackedUp) {
                    console.log(
                        'Attemping Embedded LND is backed up migration'
                    );
                    const writeSuccess = await Storage.setItem(
                        IS_BACKED_UP_KEY,
                        embeddedLndIsBackedUp
                    );
                    console.log(
                        'Embedded LND is backed up migration status',
                        writeSuccess
                    );
                    return writeSuccess;
                }
            } catch (error) {
                console.error(
                    'Error loading Embedded LND is backed up from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(embeddedLndIsBackedUpMigration);

        // LSPS1 orders migration
        const lsps1OrdersMigration = (async () => {
            try {
                const lsps1orders = await EncryptedStorage.getItem(
                    LEGACY_LSPS1_ORDERS_KEY
                );
                if (lsps1orders) {
                    console.log('Attemping LSPS1 orders migration');
                    const writeSuccess = await Storage.setItem(
                        LSPS_ORDERS_KEY,
                        lsps1orders
                    );
                    console.log('LSPS1 orders migration status', writeSuccess);
                    return writeSuccess;
                }
            } catch (error) {
                console.error(
                    'Error loading LSPS1 orders from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(lsps1OrdersMigration);

        // LNC migrations
        const lncMigration = (async () => {
            try {
                const migrationPromises =
                    settings?.nodes.map(async (node: any) => {
                        if (node.implementation === 'lightning-node-connect') {
                            const baseKey = `${LNC_STORAGE_KEY}:${hash(
                                node.pairingPhrase
                            )}`;
                            const hostKey = `${baseKey}:host`;

                            const baseKeyData: string =
                                (await EncryptedStorage.getItem(baseKey)) ||
                                '{}';

                            console.log(
                                'Attemping LNC base key migration',
                                baseKey
                            );
                            const writeSuccess1 = await Storage.setItem(
                                baseKey,
                                JSON.parse(baseKeyData)
                            );
                            console.log(
                                'LNC base key migration status',
                                writeSuccess1
                            );

                            const hostKeyData = await EncryptedStorage.getItem(
                                hostKey
                            );

                            console.log(
                                'Attemping LNC host key migration',
                                baseKey
                            );
                            const writeSuccess2 = await Storage.setItem(
                                hostKey,
                                hostKeyData
                            );
                            console.log(
                                'LNC host key migration status',
                                writeSuccess2
                            );

                            return writeSuccess1 && writeSuccess2;
                        }
                    }) || [];

                const results = await Promise.all(migrationPromises);
                return results.every((result) => result !== false);
            } catch (error) {
                console.error(
                    'Error loading LNC data from encrypted storage',
                    error
                );
                return false;
            }
        })();
        migrationTasks.push(lncMigration);

        const results = await Promise.all(migrationTasks);
        console.log('storageMigrationV2 completed!', results);
        return results.every((result) => result === true);
    }

    public async migrateCashuSeedVersion(cashuStore: any) {
        // cashuStore is passed as 'any' to avoid circular dependency issues
        // but it's an instance of CashuStore
        // TODO fix circular dependency
        if (cashuStore.seedVersion === undefined) {
            console.log('Migrating Cashu seed version to v1');
            cashuStore.seedVersion = 'v1';
            try {
                await Storage.setItem(
                    `${cashuStore.getLndDir()}-cashu-seed-version`,
                    'v1'
                );
                console.log('Cashu seed version migrated and saved as v1.');
            } catch (error) {
                console.error(
                    'Error saving migrated Cashu seed version:',
                    error
                );
            }
        }
    }

    public async keychainCloudSyncMigration() {
        try {
            const hasMigrated = await EncryptedStorage.getItem(
                KEYCHAIN_MIGRATION_KEY
            );

            if (hasMigrated !== 'true') {
                console.log('Attempting keychain cloud sync migration...');

                const settingsData = await this.migrateKey(STORAGE_KEY);

                if (settingsData) {
                    settingsStore.isMigrating = true;
                }

                const migrationKeys = [
                    CONTACTS_KEY,
                    LAST_CHANNEL_BACKUP_STATUS,
                    LAST_CHANNEL_BACKUP_TIME,
                    ADDRESS_ACTIVATED_STRING,
                    HASHES_STORAGE_STRING,
                    POS_HIDDEN_KEY,
                    POS_STANDALONE_KEY,
                    CATEGORY_KEY,
                    PRODUCT_KEY,
                    UNIT_KEY,
                    HIDDEN_ACCOUNTS_KEY,
                    CURRENCY_CODES_KEY,
                    ACTIVITY_FILTERS_KEY,
                    IS_BACKED_UP_KEY,
                    LSPS_ORDERS_KEY,
                    SWAPS_KEY,
                    REVERSE_SWAPS_KEY,
                    SWAPS_RESCUE_KEY,
                    SWAPS_LAST_USED_KEY
                ];

                for (const key of migrationKeys) {
                    await this.migrateKey(key);
                }

                const notesListJson = await this.migrateKey(NOTES_KEY);
                if (notesListJson) {
                    const noteKeys = JSON.parse(notesListJson);
                    if (Array.isArray(noteKeys)) {
                        for (const noteKey of noteKeys) {
                            await this.migrateKey(noteKey);
                        }
                    }
                }

                if (settingsData) {
                    const settings = JSON.parse(settingsData);
                    if (settings.nodes && Array.isArray(settings.nodes)) {
                        for (const node of settings.nodes) {
                            if (
                                node.implementation ===
                                    'lightning-node-connect' &&
                                node.pairingPhrase
                            ) {
                                const baseKey = `${LNC_STORAGE_KEY}:${hash(
                                    node.pairingPhrase
                                )}`;
                                const hostKey = `${baseKey}:host`;

                                await this.migrateKey(baseKey);
                                await this.migrateKey(hostKey);
                            }
                        }
                    }
                }

                await EncryptedStorage.setItem(KEYCHAIN_MIGRATION_KEY, 'true');
                console.log(
                    'Keychain cloud sync migration completed successfully.'
                );
            }

            const cashuMigration = await EncryptedStorage.getItem(
                CASHU_MIGRATION_KEY
            );

            if (cashuMigration !== 'true') {
                console.log('Running Cashu Multi-Node Migration...');

                const settingsJson = await Storage.getItem(STORAGE_KEY);
                if (settingsJson) {
                    settingsStore.isMigrating = true;
                    const settings = JSON.parse(settingsJson);
                    if (settings.nodes && Array.isArray(settings.nodes)) {
                        for (const node of settings.nodes) {
                            if (node.implementation === 'embedded-lnd') {
                                const lndDir = node.lndDir || 'lnd';
                                await this.migrateCashuForNode(lndDir);
                            }
                        }
                    }
                }
                await EncryptedStorage.setItem(CASHU_MIGRATION_KEY, 'true');
                console.log('Cashu Migration Completed.');
            }
        } catch (error) {
            console.error('Error during keychain cloud sync migration:', error);
        }
    }
}

const migrationsUtils = new MigrationsUtils();
export default migrationsUtils;
