import { describe, it, expect, vi } from "vitest";
import { createServiceContext } from "@vrtmrz/livesync-commonlib/context";
import type { LogFunction } from "@vrtmrz/livesync-commonlib/compat/services/lib/logUtils";
import {
    FlagFilesHumanReadable,
    FlagFilesOriginal,
} from "@vrtmrz/livesync-commonlib/compat/common/models/redflag.const";
import { REMOTE_MINIO, REMOTE_P2P } from "@vrtmrz/livesync-commonlib/compat/common/models/setting.const";
import {
    createFetchAllFlagHandler,
    createRebuildFlagHandler,
    createSuspendFlagHandler,
    isFlagFileExist,
    deleteFlagFile,
    adjustSettingToRemote,
    adjustSettingToRemoteIfNeeded,
    processVaultInitialisation,
    verifyAndUnlockSuspension,
    flagHandlerToEventHandler,
} from "./redFlag";
import {
    TweakValuesRecommendedTemplate,
    TweakValuesShouldMatchedTemplate,
    TweakValuesTemplate,
} from "@vrtmrz/livesync-commonlib/compat/common/types";
import {
    ExtraOnLocal,
    FullScanModes,
    synchroniseAllFilesBetweenDBandStorage,
} from "@vrtmrz/livesync-commonlib/compat/serviceFeatures/offlineScanner";
import {
    SIMPLE_FETCH_STAGE1_DETAILED,
    SIMPLE_FETCH_STAGE1_NEWER_WINS,
    SIMPLE_FETCH_STAGE1_REMOTE_WINS,
    SIMPLE_FETCH_STAGE2_NEWER_CLEANUP,
    SIMPLE_FETCH_STAGE2_NEWER_SYNC_ALL,
    SIMPLE_FETCH_STAGE2_REMOTE_DELETE_NONE,
    SIMPLE_FETCH_STAGE2_REMOTE_DELETE_ALL,
    STAGE2_ABORT,
    askAndPerformFastSetupOnScheduledFetchAll,
    askSimpleFetchMode,
} from "./redFlag.simpleFetch";
import { activateRemoteConfiguration } from "@vrtmrz/livesync-commonlib/remote-configurations";
//Mock synchroniseAllFilesBetweenDBandStorage
vi.mock("@vrtmrz/livesync-commonlib/compat/serviceFeatures/offlineScanner", async (importOriginal) => {
    const originalModule = (await importOriginal()) as any;
    return {
        ...originalModule,
        synchroniseAllFilesBetweenDBandStorage: vi.fn(() => Promise.resolve(true)),
    };
});

vi.mock("@vrtmrz/livesync-commonlib/compat/serviceFeatures/remoteConfig", () => {
    return {
        activateRemoteConfiguration: vi.fn((settings: any, configurationId: string) => {
            if (!settings?.remoteConfigurations?.[configurationId]) return false;
            return {
                activeConfigurationId: configurationId,
                remoteType: settings.remoteConfigurations[configurationId].remoteType ?? settings.remoteType,
                remoteURI: settings.remoteConfigurations[configurationId].uri,
            };
        }),
    };
});

// Mock types and functions
const createLoggerMock = (): LogFunction => {
    return vi.fn();
};

const availableRemoteTweaks = (values: Record<string, unknown>) => ({ status: "available", values }) as const;

const createStorageAccessMock = () => {
    const files: Set<string> = new Set();
    return {
        files,
        isExists: vi.fn((path: string) => Promise.resolve(files.has(path))),
        normalisePath: vi.fn((path: string) => path),
        delete: vi.fn((path: string, _recursive?: boolean) => {
            files.delete(path);
            return Promise.resolve();
        }),
        getFileNames: vi.fn(() => Array.from(files)),
    };
};

const createSettingServiceMock = () => {
    const settings: any = {
        batchSave: true,
        suspendFileWatching: false,
        writeLogToTheFile: false,
        remoteType: "CouchDB",
    };
    const smallConfig = new Map<string, string>();
    return {
        settings,
        currentSettings: vi.fn(() => settings),
        applyExternalSettings: vi.fn((partial: any, _feedback?: boolean) => {
            Object.assign(settings, partial);
            return Promise.resolve();
        }),
        applyPartial: vi.fn((partial: any, _feedback?: boolean) => {
            Object.assign(settings, partial);
            return Promise.resolve();
        }),
        suspendAllSync: vi.fn(() => Promise.resolve()),
        suspendExtraSync: vi.fn(() => Promise.resolve()),
        getSmallConfig: vi.fn((key: string) => smallConfig.get(key) ?? ""),
        setSmallConfig: vi.fn((key: string, value: string) => {
            smallConfig.set(key, value);
        }),
        deleteSmallConfig: vi.fn((key: string) => {
            smallConfig.delete(key);
        }),
    };
};

const createAppLifecycleMock = () => {
    return {
        performRestart: vi.fn(),
        onLayoutReady: {
            addHandler: vi.fn(),
        },
        getUnresolvedMessages: {
            addHandler: vi.fn(),
        },
    };
};

const createUIServiceMock = () => {
    return {
        dialogManager: {
            openWithExplicitCancel: vi.fn(),
        },
        confirm: {
            askSelectStringDialogue: vi.fn(),
            askYesNoDialog: vi.fn(),
            confirmWithMessage: vi.fn(),
        },
    };
};

const createRebuilderMock = () => {
    return {
        $fetchLocal: vi.fn(async () => {}),
        $fetchLocalDBFast: vi.fn(async () => {}),
        $rebuildEverything: vi.fn(async () => {}),
        finishRebuild: vi.fn(async () => {}),
    };
};

const createTweakValueMock = () => {
    return {
        fetchRemotePreferred: vi.fn(() =>
            Promise.resolve<any>({ status: "unavailable", error: new Error("Remote unavailable") })
        ),
    };
};

const createHostMock = () => {
    const storageAccessMock = createStorageAccessMock();
    const settingMock = createSettingServiceMock();
    const appLifecycleMock = createAppLifecycleMock();
    const uiMock = createUIServiceMock();
    const rebuilderMock = createRebuilderMock();
    const tweakValueMock = createTweakValueMock();

    return {
        services: {
            context: createServiceContext(),
            setting: settingMock,
            appLifecycle: appLifecycleMock,
            UI: uiMock,
            tweakValue: tweakValueMock,
        },
        serviceModules: {
            storageAccess: storageAccessMock,
            rebuilder: rebuilderMock,
        },
        mocks: {
            storageAccess: storageAccessMock,
            setting: settingMock,
            appLifecycle: appLifecycleMock,
            ui: uiMock,
            rebuilder: rebuilderMock,
            tweakValue: tweakValueMock,
        },
    };
};

describe("Red Flag Feature", () => {
    describe("isFlagFileExist", () => {
        it("should return true if flag file exists", async () => {
            const host = createHostMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);

            const result = await isFlagFileExist(host as any, FlagFilesOriginal.FETCH_ALL);
            expect(result).toBe(true);
        });

        it("should return false if flag file does not exist", async () => {
            const host = createHostMock();

            const result = await isFlagFileExist(host as any, FlagFilesOriginal.FETCH_ALL);
            expect(result).toBe(false);
        });
    });

    describe("deleteFlagFile", () => {
        it("should delete flag file if it exists", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);

            await deleteFlagFile(host as any, log, FlagFilesOriginal.FETCH_ALL);

            const exists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesOriginal.FETCH_ALL)
            );
            expect(exists).toBe(false);
        });

        it("should not throw error if file does not exist", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            await expect(deleteFlagFile(host as any, log, FlagFilesOriginal.FETCH_ALL)).resolves.not.toThrow();
        });

        it("should log error if deletion fails", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.delete.mockRejectedValueOnce(new Error("Delete failed"));
            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);

            await deleteFlagFile(host as any, log, FlagFilesOriginal.FETCH_ALL);

            expect(log).toHaveBeenCalled();
        });
    });

    describe("FlagFile Handler Priority", () => {
        it("should handle suspend flag with priority 5", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createSuspendFlagHandler(host as any, log);
            expect(handler.priority).toBe(5);
            expect(typeof handler.check).toBe("function");
            expect(typeof handler.handle).toBe("function");
        });

        it("should handle fetch all flag with priority 10", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createFetchAllFlagHandler(host as any, log);
            expect(handler.priority).toBe(10);
            expect(typeof handler.check).toBe("function");
            expect(typeof handler.handle).toBe("function");
        });

        it("should handle rebuild all flag with priority 20", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createRebuildFlagHandler(host as any, log);
            expect(handler.priority).toBe(20);
            expect(typeof handler.check).toBe("function");
            expect(typeof handler.handle).toBe("function");
        });
    });

    describe("Setting adjustment during vault initialisation", () => {
        it("should suspend file watching during initialisation", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            expect(host.mocks.setting.currentSettings().suspendFileWatching).toBe(false);

            const result = await processVaultInitialisation(host as any, log, () => {
                expect(host.mocks.setting.currentSettings().suspendFileWatching).toBe(true);
                return Promise.resolve(true);
            });

            expect(result).toBe(true);
        });

        it("should disable batch save during initialisation", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            expect(host.mocks.setting.currentSettings().batchSave).toBe(true);

            const result = await processVaultInitialisation(host as any, log, () => {
                expect(host.mocks.setting.currentSettings().batchSave).toBe(false);
                return Promise.resolve(true);
            });

            expect(result).toBe(true);
        });

        it("should suspend all sync operations", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            await processVaultInitialisation(host as any, log, () => {
                return Promise.resolve(true);
            });

            expect(host.mocks.setting.suspendAllSync).toHaveBeenCalled();
            expect(host.mocks.setting.suspendExtraSync).toHaveBeenCalled();
        });

        it("should resume file watching after initialisation completes", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            await processVaultInitialisation(
                host as any,
                log,
                () => {
                    return Promise.resolve(true);
                },
                "resume"
            );

            expect(host.mocks.setting.currentSettings().suspendFileWatching).toBe(false);
        });

        it("should keep suspending when the policy is keep", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            await processVaultInitialisation(
                host as any,
                log,
                () => {
                    return Promise.resolve(true);
                },
                "keep"
            );

            expect(host.mocks.setting.currentSettings().suspendFileWatching).toBe(true);
        });

        it("should return false when process fails", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const result = await processVaultInitialisation(
                host as any,
                log,
                () => {
                    throw new Error("Process failed");
                },
                "resume"
            );

            expect(result).toBe(false);
            expect(log).toHaveBeenCalled();
        });
    });

    describe("Suspend Flag Handler", () => {
        it("should write logs to file when suspend flag is detected", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createSuspendFlagHandler(host as any, log);

            expect(handler.priority).toBe(5);
            expect(typeof handler.check).toBe("function");
            expect(typeof handler.handle).toBe("function");
        });

        it("should keep suspending after initialisation when suspend flag is active", async () => {
            const host = createHostMock();

            const handler = createSuspendFlagHandler(host as any, createLoggerMock());

            const checkResult = await handler.check();
            expect(typeof checkResult).toBe("boolean");
        });

        it("should apply writeLogToTheFile setting during suspension", async () => {
            const host = createHostMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.SUSPEND_ALL);

            const handler = createSuspendFlagHandler(host as any, createLoggerMock());
            const checkResult = await handler.check();

            expect(checkResult).toBe(true);
        });
    });

    describe("Fetch All Flag Handler", () => {
        it("should detect fetch all flag using original filename", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);

            const handler = createFetchAllFlagHandler(host as any, log);
            const exists = await handler.check();

            expect(exists).toBe(true);
        });

        it("should detect fetch all flag using human-readable filename", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesHumanReadable.FETCH_ALL);

            const handler = createFetchAllFlagHandler(host as any, log);
            const exists = await handler.check();

            expect(exists).toBe(true);
        });

        it("should clean up both original and human-readable fetch all flag files", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.storageAccess.files.add(FlagFilesHumanReadable.FETCH_ALL);

            await deleteFlagFile(host as any, log, FlagFilesOriginal.FETCH_ALL);
            await deleteFlagFile(host as any, log, FlagFilesHumanReadable.FETCH_ALL);

            const originalExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesOriginal.FETCH_ALL)
            );
            const humanExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesHumanReadable.FETCH_ALL)
            );

            expect(originalExists).toBe(false);
            expect(humanExists).toBe(false);
        });

        it("should have priority 10", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createFetchAllFlagHandler(host as any, log);
            expect(handler.priority).toBe(10);
        });

        it("should use simplified remote-only mode and call performFullScan", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            // Stage 1: Overwrite all with remote files
            // Stage 2: Delete local files if not on remote (Clean overwrite)
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_REMOTE_DELETE_ALL);

            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(true);
            expect(host.mocks.rebuilder.$fetchLocalDBFast).toHaveBeenCalled();
            expect(synchroniseAllFilesBetweenDBandStorage).toHaveBeenCalled();
            const firstPrompt = host.mocks.ui.confirm.confirmWithMessage.mock.calls[0]?.[1];
            expect(firstPrompt).toContain("data retrieved from this remote source");
            expect(firstPrompt).not.toContain("remote server");
            // We can't easily check performFullScan call here because it's imported,
            // but we can verify rebuilder was called.
        });

        it("opens the detailed Fetch flow when requested", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_DETAILED);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce({
                vault: "identical",
                backup: "backup_skipped",
                extra: { preventFetchingConfig: false },
            });
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );
            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(true);
            expect(host.mocks.ui.dialogManager.openWithExplicitCancel).toHaveBeenCalled();
            expect(host.mocks.rebuilder.$fetchLocal).toHaveBeenCalled();
        });

        it("should cancel fetch flow when first quick step is cancelled", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(false);

            const handler = createFetchAllFlagHandler(host as any, log);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );
            const result = await handler.handle();

            expect(result).toBe(false);
            expect(host.mocks.rebuilder.$fetchLocal).not.toHaveBeenCalled();
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalled();
        });

        it("should use remote-authoritative quick mode for empty vault", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_REMOTE_DELETE_ALL);

            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );
            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(true);
            expect(host.mocks.rebuilder.$fetchLocalDBFast).toHaveBeenCalled();
            expect(host.mocks.rebuilder.$fetchLocal).not.toHaveBeenCalledWith(false, true);
        });

        it("should keep current remote configuration when selected", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            Object.assign(host.mocks.setting.settings, {
                remoteConfigurations: {
                    alpha: { name: "Alpha", uri: "sls+https://user:pass@example.com/db1" },
                    beta: { name: "Beta", uri: "sls+https://user:pass@example.com/db2" },
                },
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Use active remote");
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(false);

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(false);
            expect(host.mocks.setting.applyPartial).not.toHaveBeenCalledWith(
                expect.objectContaining({ activeConfigurationId: expect.any(String) })
            );
        });

        it("should stop when remote selection is cancelled", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            Object.assign(host.mocks.setting.settings, {
                remoteConfigurations: {
                    alpha: { name: "Alpha", uri: "sls+https://user:pass@example.com/db1" },
                    beta: { name: "Beta", uri: "sls+https://user:pass@example.com/db2" },
                },
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Cancel");

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(false);
            expect(host.mocks.ui.confirm.confirmWithMessage).not.toHaveBeenCalled();
            expect(host.mocks.storageAccess.files.has(FlagFilesOriginal.FETCH_ALL)).toBe(false);
            await expect(handler.check()).resolves.toBe(false);
            expect(host.mocks.setting.applyPartial).toHaveBeenCalledWith(
                {
                    suspendFileWatching: true,
                    suspendParseReplicationResult: true,
                },
                true
            );
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalledOnce();
        });

        it("should activate selected remote configuration", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            Object.assign(host.mocks.setting.settings, {
                remoteConfigurations: {
                    alpha: {
                        name: "Alpha",
                        uri: "sls+https://user:pass@example.com/db1",
                        remoteType: "CouchDB",
                    },
                    beta: {
                        name: "Beta",
                        uri: "sls+https://user:pass@example.com/db2",
                        remoteType: "CouchDB",
                    },
                },
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockImplementationOnce(
                async (_message: string, selections: string[]) => selections.find((e) => e.startsWith("Beta -"))
            );
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(false);

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(false);
            expect(activateRemoteConfiguration).toHaveBeenCalledWith(host.mocks.setting.settings, "beta");
            expect(host.mocks.setting.applyPartial).toHaveBeenCalledWith(
                expect.objectContaining({ activeConfigurationId: "beta" })
            );
        });

        it("should stop when selected remote name is unknown", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            Object.assign(host.mocks.setting.settings, {
                remoteConfigurations: {
                    alpha: { name: "Alpha", uri: "sls+https://user:pass@example.com/db1" },
                    beta: { name: "Beta", uri: "sls+https://user:pass@example.com/db2" },
                },
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Unknown option");

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(false);
            expect(host.mocks.ui.confirm.confirmWithMessage).not.toHaveBeenCalled();
        });

        it("should stop when remote activation fails", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            Object.assign(host.mocks.setting.settings, {
                remoteConfigurations: {
                    alpha: { name: "Alpha", uri: "sls+https://user:pass@example.com/db1" },
                    beta: { name: "Beta", uri: "sls+https://user:pass@example.com/db2" },
                },
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockImplementationOnce(
                async (_message: string, selections: string[]) => selections.find((e) => e.startsWith("Beta -"))
            );
            (activateRemoteConfiguration as any).mockReturnValueOnce(false);

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.handle();

            expect(result).toBe(false);
            expect(host.mocks.ui.confirm.confirmWithMessage).not.toHaveBeenCalled();
        });
    });

    describe("askSimpleFetchMode", () => {
        it("should return cancelled when stage1 is cancelled", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(false);

            await expect(askSimpleFetchMode(host as any)).resolves.toBe("cancelled");
        });

        it("selects the detailed Fetch flow", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_DETAILED);

            await expect(askSimpleFetchMode(host as any)).resolves.toEqual({ mode: "detailed", options: {} });
        });

        it("should return remote-only with keep-local option", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_REMOTE_DELETE_NONE);

            await expect(askSimpleFetchMode(host as any)).resolves.toEqual({
                mode: "remote-only",
                options: {
                    mode: FullScanModes.DB_APPLY,
                    extraOnRemote: undefined,
                },
            });
        });

        it("should return cancelled when remote-only stage2 is cancelled", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(false);

            await expect(askSimpleFetchMode(host as any)).resolves.toBe("cancelled");
        });

        it("should return aborted when remote-only stage2 aborts", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(STAGE2_ABORT);

            await expect(askSimpleFetchMode(host as any)).resolves.toBe("aborted");
        });

        it("should return newer-wins cleanup option", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_NEWER_CLEANUP);

            await expect(askSimpleFetchMode(host as any)).resolves.toEqual({
                mode: "newer-wins",
                options: {
                    mode: FullScanModes.NEWER_WINS,
                    extraOnLocal: ExtraOnLocal.DELETE_DB_DELETED,
                },
            });
        });

        it("should return newer-wins keep-all option", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_NEWER_SYNC_ALL);

            await expect(askSimpleFetchMode(host as any)).resolves.toEqual({
                mode: "newer-wins",
                options: {
                    mode: FullScanModes.NEWER_WINS,
                    extraOnLocal: ExtraOnLocal.APPEND_STORAGE_ONLY,
                },
            });
        });

        it("should return cancelled when newer-wins stage2 is cancelled", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(false);

            await expect(askSimpleFetchMode(host as any)).resolves.toBe("cancelled");
        });

        it("should return aborted when newer-wins stage2 aborts", async () => {
            const host = createHostMock();
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(STAGE2_ABORT);

            await expect(askSimpleFetchMode(host as any)).resolves.toBe("aborted");
        });
    });

    describe("askAndPerformFastSetupOnScheduledFetchAll", () => {
        it("releases both reflection suspensions after Fast Setup succeeds", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            Object.assign(host.mocks.setting.settings, {
                doNotSuspendOnFetching: true,
                suspendParseReplicationResult: true,
            });
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_NEWER_CLEANUP);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValue(availableRemoteTweaks({ batchSave: false }));

            await expect(askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag)).resolves.toBe(true);

            expect(host.mocks.setting.currentSettings()).toMatchObject({
                suspendFileWatching: false,
                suspendParseReplicationResult: false,
            });
        });

        it("keeps Vault reflection suspended and preserves recovery state when Fast Fetch fails", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_NEWER_CLEANUP);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValue(availableRemoteTweaks({ batchSave: false }));
            host.mocks.rebuilder.$fetchLocalDBFast.mockRejectedValueOnce(new Error("cannot decrypt remote document"));

            await expect(askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag)).resolves.toBe(false);

            expect(host.mocks.setting.currentSettings()).toMatchObject({
                suspendFileWatching: true,
                suspendParseReplicationResult: true,
            });
            expect(host.mocks.rebuilder.finishRebuild).not.toHaveBeenCalled();
            expect(cleanupFlag).not.toHaveBeenCalled();
            expect(host.mocks.setting.deleteSmallConfig).not.toHaveBeenCalledWith("simple-fetch-mode");
        });

        it("re-suspends both reflection directions when finalisation fails after releasing them", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_NEWER_CLEANUP);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValue(availableRemoteTweaks({ batchSave: false }));
            host.mocks.rebuilder.finishRebuild.mockImplementationOnce(async () => {
                await host.mocks.setting.applyPartial(
                    {
                        suspendFileWatching: false,
                        suspendParseReplicationResult: false,
                    },
                    true
                );
                throw new Error("Vault scan failed after reflection resumed");
            });

            await expect(askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag)).resolves.toBe(false);

            expect(host.mocks.setting.currentSettings()).toMatchObject({
                suspendFileWatching: true,
                suspendParseReplicationResult: true,
            });
            expect(cleanupFlag).not.toHaveBeenCalled();
        });

        it("should remember quick flow choices while the scheduled fetch is pending", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_NEWER_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_NEWER_CLEANUP);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValue(availableRemoteTweaks({ batchSave: false }));
            host.mocks.rebuilder.$fetchLocalDBFast.mockRejectedValueOnce(new Error("offline"));

            await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);
            await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);

            expect(host.mocks.ui.confirm.confirmWithMessage).toHaveBeenCalledTimes(2);
            expect(host.mocks.rebuilder.$fetchLocalDBFast).toHaveBeenCalledTimes(2);
        });

        it("should clear remembered quick flow choices after completion", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_REMOTE_DELETE_ALL);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValue(availableRemoteTweaks({ batchSave: false }));

            await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);

            expect(host.mocks.setting.deleteSmallConfig).toHaveBeenCalledWith("simple-fetch-mode");
        });

        it("should return false and cleanup when quick flow is cancelled", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(false);

            const result = await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);

            expect(result).toBe(false);
            expect(cleanupFlag).toHaveBeenCalled();
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalled();
        });

        it("should return false without cleanup when quick flow is aborted", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(STAGE2_ABORT);

            const result = await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);

            expect(result).toBe(false);
            expect(cleanupFlag).not.toHaveBeenCalled();
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalled();
        });

        it("leaves the detailed Fetch flow to its existing handler", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_DETAILED);

            const result = await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);

            expect(result).toBeUndefined();
            expect(host.mocks.rebuilder.$fetchLocalDBFast).not.toHaveBeenCalled();
        });

        it("should preserve automatic synchronisation choices and enter Scram when quick Fetch is cancelled", async () => {
            const host = createHostMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);
            Object.assign(host.mocks.setting.settings, {
                liveSync: true,
                periodicReplication: true,
                syncOnSave: true,
                syncOnEditorSave: true,
                syncOnStart: true,
                syncOnFileOpen: true,
                syncAfterMerge: true,
                suspendParseReplicationResult: false,
            });
            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_REMOTE_DELETE_ALL);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce({
                status: "not-configured",
                reason: "milestone-missing",
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Cancel");

            const result = await askAndPerformFastSetupOnScheduledFetchAll(
                host as any,
                createLoggerMock(),
                cleanupFlag
            );

            expect(result).toBe(false);
            expect(host.mocks.rebuilder.$fetchLocalDBFast).not.toHaveBeenCalled();
            expect(host.mocks.setting.suspendAllSync).not.toHaveBeenCalled();
            expect(host.mocks.setting.applyPartial).toHaveBeenCalledWith(
                {
                    suspendFileWatching: true,
                    suspendParseReplicationResult: true,
                },
                true
            );
            expect(host.mocks.setting.currentSettings()).toMatchObject({
                liveSync: true,
                periodicReplication: true,
                syncOnSave: true,
                syncOnEditorSave: true,
                syncOnStart: true,
                syncOnFileOpen: true,
                syncAfterMerge: true,
                suspendFileWatching: true,
                suspendParseReplicationResult: true,
            });
            expect(cleanupFlag).toHaveBeenCalledOnce();
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalledOnce();
            expect(host.mocks.setting.applyPartial.mock.invocationCallOrder[0]).toBeLessThan(
                cleanupFlag.mock.invocationCallOrder[0]
            );
            expect(cleanupFlag.mock.invocationCallOrder[0]).toBeLessThan(
                host.mocks.appLifecycle.performRestart.mock.invocationCallOrder[0]
            );
        });

        it("should reboot and return false when sync has failures and user chooses rerun", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_REMOTE_DELETE_ALL);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );
            (synchroniseAllFilesBetweenDBandStorage as any).mockResolvedValueOnce(false);
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Reboot to re-run the process");

            const result = await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);

            expect(result).toBe(false);
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalled();
            expect(cleanupFlag).not.toHaveBeenCalled();
            expect(host.mocks.rebuilder.finishRebuild).not.toHaveBeenCalled();
        });

        it("should continue and finalise when sync has failures but user releases flag", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const cleanupFlag = vi.fn().mockResolvedValue(undefined);

            host.mocks.ui.confirm.confirmWithMessage
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_REMOTE_WINS)
                .mockResolvedValueOnce(SIMPLE_FETCH_STAGE2_REMOTE_DELETE_ALL);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );
            (synchroniseAllFilesBetweenDBandStorage as any).mockResolvedValueOnce(false);
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce(
                "Finalise the process and resume normal operation"
            );

            const result = await askAndPerformFastSetupOnScheduledFetchAll(host as any, log, cleanupFlag);

            expect(result).toBe(true);
            expect(host.mocks.rebuilder.finishRebuild).toHaveBeenCalled();
            expect(cleanupFlag).toHaveBeenCalled();
        });
    });

    describe("Rebuild All Flag Handler", () => {
        it("identifies P2P when opening the scheduled rebuild confirmation", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            host.mocks.setting.settings.remoteType = REMOTE_P2P;
            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce("cancelled");

            await createRebuildFlagHandler(host as any, log).handle();

            expect(host.mocks.ui.dialogManager.openWithExplicitCancel).toHaveBeenCalledWith(expect.anything(), {
                isP2P: true,
            });
        });

        it("should detect rebuild all flag using original filename", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);

            const handler = createRebuildFlagHandler(host as any, log);
            const exists = await handler.check();

            expect(exists).toBe(true);
        });

        it("should detect rebuild all flag using human-readable filename", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesHumanReadable.REBUILD_ALL);

            const handler = createRebuildFlagHandler(host as any, log);
            const exists = await handler.check();

            expect(exists).toBe(true);
        });

        it("should clean up both original and human-readable rebuild all flag files", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);
            host.mocks.storageAccess.files.add(FlagFilesHumanReadable.REBUILD_ALL);

            await deleteFlagFile(host as any, log, FlagFilesOriginal.REBUILD_ALL);
            await deleteFlagFile(host as any, log, FlagFilesHumanReadable.REBUILD_ALL);

            const originalExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesOriginal.REBUILD_ALL)
            );
            const humanExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesHumanReadable.REBUILD_ALL)
            );

            expect(originalExists).toBe(false);
            expect(humanExists).toBe(false);
        });

        it("should have priority 20", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createRebuildFlagHandler(host as any, log);
            expect(handler.priority).toBe(20);
        });
    });

    describe("Flag file cleanup on error", () => {
        it("should handle errors during flag file deletion gracefully", async () => {
            const host = createHostMock();

            // Simulate error in delete operation
            host.mocks.storageAccess.delete.mockRejectedValueOnce(new Error("Delete failed"));

            try {
                await host.mocks.storageAccess.delete(FlagFilesOriginal.FETCH_ALL, true);
            } catch {
                // Error handled
            }

            expect(host.mocks.storageAccess.delete).toHaveBeenCalled();
        });
    });

    describe("Integration: Handler registration on layout ready", () => {
        it("should register handlers with correct priorities", () => {
            const host = createHostMock();

            expect(host.services.appLifecycle.onLayoutReady.addHandler).toBeDefined();
            expect(typeof host.services.appLifecycle.onLayoutReady.addHandler).toBe("function");
        });
    });

    describe("Dialog interaction scenarios", () => {
        it("should handle fetch all dialog cancellation", async () => {
            const host = createHostMock();

            // Simulate user clicking cancel
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce("cancelled");

            // The dialog manager would return cancelled
            const result = await host.mocks.ui.dialogManager.openWithExplicitCancel();
            expect(result).toBe("cancelled");
        });

        it("should handle rebuild dialog cancellation", async () => {
            const host = createHostMock();

            // Simulate user clicking cancel
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce("cancelled");

            const result = await host.mocks.ui.dialogManager.openWithExplicitCancel();
            expect(result).toBe("cancelled");
        });

        it("should handle confirm dialog for remote configuration mismatch", async () => {
            const host = createHostMock();

            await host.mocks.ui.confirm.askSelectStringDialogue("Your settings differed slightly.", ["OK"]);
            expect(host.mocks.ui.confirm.askSelectStringDialogue).toHaveBeenCalled();
        });
    });

    describe("Remote configuration adjustment", () => {
        it("keeps this device's E2EE settings when preparing to overwrite the remote", async () => {
            const host = createHostMock();
            Object.assign(host.mocks.setting.settings, TweakValuesShouldMatchedTemplate, {
                encrypt: true,
                passphrase: "local-encryption-passphrase",
            });
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({
                    ...TweakValuesShouldMatchedTemplate,
                    encrypt: false,
                })
            );

            const result = await adjustSettingToRemote(
                host as any,
                createLoggerMock(),
                host.mocks.setting.currentSettings(),
                "rebuild"
            );

            expect(result).toBe(true);
            expect(host.mocks.tweakValue.fetchRemotePreferred).toHaveBeenCalledOnce();
            expect(host.mocks.setting.currentSettings().encrypt).toBe(true);
            expect(host.mocks.setting.currentSettings().passphrase).toBe("local-encryption-passphrase");
            expect(host.mocks.setting.applyExternalSettings).not.toHaveBeenCalled();
        });

        it("should skip remote configuration fetch when preventFetchingConfig is true", async () => {
            const host = createHostMock();
            const config = { preventFetchingConfig: true } as any;

            await adjustSettingToRemoteIfNeeded(
                host as any,
                createLoggerMock(),
                { preventFetchingConfig: true },
                config
            );

            expect(host.mocks.tweakValue.fetchRemotePreferred).not.toHaveBeenCalled();
        });

        it("should fetch remote configuration when preventFetchingConfig is false", async () => {
            const host = createHostMock();
            const config = { batchSave: true } as any;

            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );

            await adjustSettingToRemoteIfNeeded(
                host as any,
                createLoggerMock(),
                { preventFetchingConfig: false },
                config
            );

            expect(host.mocks.tweakValue.fetchRemotePreferred).toHaveBeenCalled();
        });

        const mismatchDetectionKeys = Object.keys(TweakValuesShouldMatchedTemplate);
        it.each(mismatchDetectionKeys)(
            "should apply remote configuration when available and different:%s",
            async (key) => {
                const host = createHostMock();

                const config = { [key]: TweakValuesTemplate[key as keyof typeof TweakValuesTemplate] } as any;
                const differentValue =
                    typeof config[key as keyof typeof config] === "boolean"
                        ? !config[key as keyof typeof config]
                        : typeof config[key as keyof typeof config] === "number"
                          ? (config[key as keyof typeof config] as number) + 1
                          : "different";
                const differentConfig = {
                    [key]: differentValue,
                };
                host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                    availableRemoteTweaks(differentConfig)
                );
                host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("OK");

                await adjustSettingToRemote(host as any, createLoggerMock(), config);
                expect(host.mocks.ui.confirm.askSelectStringDialogue).toHaveBeenCalled();
                expect(host.mocks.setting.applyExternalSettings).toHaveBeenCalled();
            }
        );
        const mismatchAcceptedKeys = Object.keys(TweakValuesRecommendedTemplate).filter(
            (key) => !mismatchDetectionKeys.includes(key)
        );

        it.each(mismatchAcceptedKeys)(
            "should apply remote configuration when available and different but acceptable: %s",
            async (key) => {
                const host = createHostMock();

                const config = { [key]: TweakValuesTemplate[key as keyof typeof TweakValuesTemplate] } as any;
                const differentValue =
                    typeof config[key as keyof typeof config] === "boolean"
                        ? !config[key as keyof typeof config]
                        : typeof config[key as keyof typeof config] === "number"
                          ? (config[key as keyof typeof config] as number) + 1
                          : "different";
                const differentConfig = {
                    [key]: differentValue,
                };
                host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                    availableRemoteTweaks(differentConfig)
                );
                host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("OK");

                await adjustSettingToRemote(host as any, createLoggerMock(), config);

                expect(host.mocks.setting.applyExternalSettings).toHaveBeenCalled();
                expect(host.mocks.ui.confirm.askSelectStringDialogue).not.toHaveBeenCalled();
            }
        );

        it("should explain that missing remote settings are normal for a new database without offering retry", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const config = { batchSave: true } as any;

            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce({
                status: "not-configured",
                reason: "milestone-missing",
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Use this device's settings");

            await expect(adjustSettingToRemote(host as any, log, config)).resolves.toBe(true);

            expect(host.mocks.ui.confirm.askSelectStringDialogue).toHaveBeenCalledWith(
                "The selected remote has no saved synchronisation settings. This is normal for a new remote. Use this device's settings, or cancel if you expected existing settings.",
                ["Use this device's settings", "Cancel"],
                {
                    defaultAction: "Use this device's settings",
                    timeout: 0,
                    title: "No Synchronisation Settings Found",
                }
            );
            expect(host.mocks.tweakValue.fetchRemotePreferred).toHaveBeenCalledOnce();
            expect(host.mocks.setting.applyExternalSettings).not.toHaveBeenCalled();
        });

        it("should retry only when remote settings are unavailable", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const config = { batchSave: true } as any;
            const failure = new Error("network failed");

            host.mocks.tweakValue.fetchRemotePreferred
                .mockResolvedValueOnce({ status: "unavailable", error: failure })
                .mockResolvedValueOnce({ status: "available", values: { batchSave: false } } as any);
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Retry");

            await expect(adjustSettingToRemote(host as any, log, config)).resolves.toBe(true);

            expect(host.mocks.tweakValue.fetchRemotePreferred).toHaveBeenCalledTimes(2);
            expect(host.mocks.ui.confirm.askSelectStringDialogue).toHaveBeenCalledWith(
                "Could not read the remote's synchronisation settings. Check the connection and credentials, then retry.",
                ["Retry", "Cancel"],
                {
                    defaultAction: "Retry",
                    timeout: 0,
                    title: "Could Not Read Synchronisation Settings",
                }
            );
        });

        it("should cancel initialisation instead of proceeding after an unavailable remote", async () => {
            const host = createHostMock();
            const config = { batchSave: true } as any;

            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce({
                status: "unavailable",
                error: new Error("network failed"),
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Cancel");

            await expect(adjustSettingToRemote(host as any, createLoggerMock(), config)).resolves.toBe(false);

            expect(host.mocks.tweakValue.fetchRemotePreferred).toHaveBeenCalledOnce();
            expect(host.mocks.setting.applyExternalSettings).not.toHaveBeenCalled();
        });

        it("should log when no changes needed", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const config = { batchSave: false } as any;

            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({ batchSave: false })
            );

            await adjustSettingToRemote(host as any, log, config);

            expect(log).toHaveBeenCalled();
        });

        it("should handle null extra parameter in adjustSettingToRemoteIfNeeded", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            const config = { batchSave: true } as any;

            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce({
                status: "not-configured",
                reason: "preferred-values-missing",
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Use this device's settings");

            await adjustSettingToRemoteIfNeeded(host as any, log, null as any, config);

            expect(host.mocks.tweakValue.fetchRemotePreferred).toHaveBeenCalled();
        });
    });

    describe("MinIO configuration handling", () => {
        it("should not enable makeLocalChunkBeforeSync when remote is MinIO", () => {
            const host = createHostMock();
            host.mocks.setting.settings.remoteType = REMOTE_MINIO;

            const settings = host.mocks.setting.currentSettings();
            const isMinIO = settings.remoteType === REMOTE_MINIO;

            expect(isMinIO).toBe(true);
        });

        it("should enable makeLocalChunkBeforeSync for non-MinIO remotes", () => {
            const host = createHostMock();
            host.mocks.setting.settings.remoteType = "CouchDB";

            const settings = host.mocks.setting.currentSettings();
            const isMinIO = settings.remoteType === REMOTE_MINIO;

            expect(isMinIO).toBe(false);
        });
    });

    describe("Suspension unlock verification", () => {
        it("should return true when suspension is not active", async () => {
            const host = createHostMock();

            const result = await verifyAndUnlockSuspension(host as any, createLoggerMock());
            expect(result).toBe(true);
        });

        it("should ask for confirmation when suspension is active", async () => {
            const host = createHostMock();

            await host.mocks.setting.applyPartial({ suspendFileWatching: true });

            host.mocks.ui.confirm.askYesNoDialog.mockResolvedValueOnce("yes");

            await verifyAndUnlockSuspension(host as any, createLoggerMock());

            expect(host.mocks.ui.confirm.askYesNoDialog).toHaveBeenCalled();
        });

        it("should return true when user declines suspension unlock", async () => {
            const host = createHostMock();

            await host.mocks.setting.applyPartial({ suspendFileWatching: true });
            host.mocks.ui.confirm.askYesNoDialog.mockResolvedValueOnce("no");

            const result = await verifyAndUnlockSuspension(host as any, createLoggerMock());

            expect(result).toBe(true);
        });

        it("should resume file watching and restart when user accepts", async () => {
            const host = createHostMock();

            await host.mocks.setting.applyPartial({ suspendFileWatching: true }, true);
            host.mocks.ui.confirm.askYesNoDialog.mockResolvedValueOnce("yes");

            await verifyAndUnlockSuspension(host as any, createLoggerMock());

            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalled();
        });
    });

    describe("Error handling in vault initialization", () => {
        it("should handle errors during initialisation gracefully", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const result = await processVaultInitialisation(host as any, log, () => {
                throw new Error("Initialization failed");
            });

            expect(result).toBe(false);
            expect(log).toHaveBeenCalled();
        });

        it("should track log calls during error conditions", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            await processVaultInitialisation(host as any, log, () => {
                throw new Error("Test error");
            });

            expect(log).toHaveBeenCalled();
        });

        it("should keep suspension state when error occurs during initialization", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            await processVaultInitialisation(
                host as any,
                log,
                () => {
                    return Promise.resolve(false);
                },
                "keep"
            );

            expect(host.mocks.setting.currentSettings().suspendFileWatching).toBe(true);
        });

        it("should handle applySetting error in processVaultInitialisation", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.setting.applyPartial.mockRejectedValueOnce(new Error("Apply partial failed"));

            const result = await processVaultInitialisation(host as any, log, () => {
                return Promise.resolve(true);
            });

            expect(result).toBe(false);
        });
    });

    describe("Flag file detection with both formats", () => {
        it("should detect either original or human-readable fetch all flag", async () => {
            const host = createHostMock();

            // Add only human-readable flag
            host.mocks.storageAccess.files.add(FlagFilesHumanReadable.FETCH_ALL);

            const humanExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesHumanReadable.FETCH_ALL)
            );

            expect(humanExists).toBe(true);
        });

        it("should detect either original or human-readable rebuild flag", async () => {
            const host = createHostMock();

            // Add only original flag
            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);

            const originalExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesOriginal.REBUILD_ALL)
            );

            expect(originalExists).toBe(true);
        });
    });

    describe("Handler execution", () => {
        it("should execute fetch all handler check method", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.check();

            expect(result).toBe(true);
        });

        it("should execute rebuild handler check method", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);

            const handler = createRebuildFlagHandler(host as any, log);
            const result = await handler.check();

            expect(result).toBe(true);
        });

        it("should execute suspend handler check method", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.SUSPEND_ALL);

            const handler = createSuspendFlagHandler(host as any, log);
            const result = await handler.check();

            expect(result).toBe(true);
        });

        it("should return false when flag does not exist", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createFetchAllFlagHandler(host as any, log);
            const result = await handler.check();

            expect(result).toBe(false);
        });

        it("should return correct priority for each handler", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const suspendHandler = createSuspendFlagHandler(host as any, log);
            const fetchHandler = createFetchAllFlagHandler(host as any, log);
            const rebuildHandler = createRebuildFlagHandler(host as any, log);

            expect(suspendHandler.priority).toBe(5);
            expect(fetchHandler.priority).toBe(10);
            expect(rebuildHandler.priority).toBe(20);
        });

        it("should handle suspend flag and execute handler", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.SUSPEND_ALL);

            const handler = createSuspendFlagHandler(host as any, log);
            const checkResult = await handler.check();

            expect(checkResult).toBe(true);
            expect(typeof handler.handle).toBe("function");
        });

        it("should have handle method for all handlers", () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const suspendHandler = createSuspendFlagHandler(host as any, log);
            const fetchHandler = createFetchAllFlagHandler(host as any, log);
            const rebuildHandler = createRebuildFlagHandler(host as any, log);

            expect(typeof suspendHandler.handle).toBe("function");
            expect(typeof fetchHandler.handle).toBe("function");
            expect(typeof rebuildHandler.handle).toBe("function");
        });
    });

    describe("Multiple concurrent operations", () => {
        it("should handle multiple flag files existing simultaneously", async () => {
            const host = createHostMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);
            host.mocks.storageAccess.files.add(FlagFilesOriginal.SUSPEND_ALL);

            const fetchExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesOriginal.FETCH_ALL)
            );
            const rebuildExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesOriginal.REBUILD_ALL)
            );
            const suspendExists = await host.mocks.storageAccess.isExists(
                host.mocks.storageAccess.normalisePath(FlagFilesOriginal.SUSPEND_ALL)
            );

            expect(fetchExists).toBe(true);
            expect(rebuildExists).toBe(true);
            expect(suspendExists).toBe(true);
        });

        it("should cleanup all flags when processing completes", async () => {
            const host = createHostMock();

            host.mocks.storageAccess.files.add(FlagFilesHumanReadable.FETCH_ALL);
            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);

            await host.mocks.storageAccess.delete(FlagFilesHumanReadable.FETCH_ALL);
            await host.mocks.storageAccess.delete(FlagFilesOriginal.FETCH_ALL);

            expect(host.mocks.storageAccess.files.size).toBe(0);
        });
    });

    describe("Setting state transitions", () => {
        it("should apply complete state transition for initialization", async () => {
            const host = createHostMock();

            // Initial state
            const initialState = {
                batchSave: host.mocks.setting.currentSettings().batchSave,
                suspendFileWatching: host.mocks.setting.currentSettings().suspendFileWatching,
            };

            // Initialization state
            await host.mocks.setting.applyPartial(
                {
                    batchSave: false,
                    suspendFileWatching: true,
                },
                true
            );

            const initState = {
                batchSave: host.mocks.setting.currentSettings().batchSave,
                suspendFileWatching: host.mocks.setting.currentSettings().suspendFileWatching,
            };

            // Post-initialization state
            await host.mocks.setting.applyPartial(
                {
                    batchSave: true,
                    suspendFileWatching: false,
                },
                true
            );

            const finalState = {
                batchSave: host.mocks.setting.currentSettings().batchSave,
                suspendFileWatching: host.mocks.setting.currentSettings().suspendFileWatching,
            };

            expect(initialState.batchSave).toBe(true);
            expect(initialState.suspendFileWatching).toBe(false);

            expect(initState.batchSave).toBe(false);
            expect(initState.suspendFileWatching).toBe(true);

            expect(finalState.batchSave).toBe(true);
            expect(finalState.suspendFileWatching).toBe(false);
        });
    });

    describe("flagHandlerToEventHandler integration", () => {
        it("should stop a detailed Fetch when remote-setting initialisation is cancelled", async () => {
            const host = createHostMock();
            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_DETAILED);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce({
                vault: "independent",
                extra: { preventFetchingConfig: false },
            });
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce({
                status: "not-configured",
                reason: "milestone-missing",
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Cancel");

            const result = await createFetchAllFlagHandler(host as any, createLoggerMock()).handle();

            expect(result).toBe(false);
            expect(host.mocks.rebuilder.$fetchLocal).not.toHaveBeenCalled();
            expect(host.mocks.setting.suspendAllSync).not.toHaveBeenCalled();
            expect(host.mocks.setting.applyPartial).toHaveBeenCalledWith(
                {
                    suspendFileWatching: true,
                    suspendParseReplicationResult: true,
                },
                true
            );
            expect(host.mocks.storageAccess.files.has(FlagFilesOriginal.FETCH_ALL)).toBe(false);
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalledOnce();
        });

        it("should stop Rebuild before deleting local data when remote-setting initialisation is cancelled", async () => {
            const host = createHostMock();
            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce({
                extra: { preventFetchingConfig: false },
            });
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce({
                status: "not-configured",
                reason: "milestone-missing",
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Cancel");

            const result = await createRebuildFlagHandler(host as any, createLoggerMock()).handle();

            expect(result).toBe(false);
            expect(host.mocks.rebuilder.$rebuildEverything).not.toHaveBeenCalled();
            expect(host.mocks.setting.suspendAllSync).not.toHaveBeenCalled();
            expect(host.mocks.setting.applyPartial).toHaveBeenCalledWith(
                {
                    suspendFileWatching: true,
                    suspendParseReplicationResult: true,
                },
                true
            );
            expect(host.mocks.storageAccess.files.has(FlagFilesOriginal.REBUILD_ALL)).toBe(false);
            expect(host.mocks.appLifecycle.performRestart).toHaveBeenCalledOnce();
        });

        it("should let Rebuild use this device's settings when remote settings are unavailable", async () => {
            const host = createHostMock();
            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce({
                extra: { preventFetchingConfig: false },
            });
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce({
                status: "unavailable",
                error: new Error("network failed"),
            });
            host.mocks.ui.confirm.askSelectStringDialogue.mockResolvedValueOnce("Use this device's settings");

            const result = await createRebuildFlagHandler(host as any, createLoggerMock()).handle();

            expect(result).toBe(true);
            expect(host.mocks.ui.confirm.askSelectStringDialogue).toHaveBeenCalledWith(
                "Could not read the remote's synchronisation settings. Retry, or continue the overwrite with this device's settings. A working connection is still required.",
                ["Retry", "Use this device's settings", "Cancel"],
                {
                    defaultAction: "Retry",
                    timeout: 0,
                    title: "Could Not Read Synchronisation Settings",
                }
            );
            expect(host.mocks.rebuilder.$rebuildEverything).toHaveBeenCalledOnce();
            expect(host.mocks.storageAccess.files.has(FlagFilesOriginal.REBUILD_ALL)).toBe(false);
            expect(host.mocks.appLifecycle.performRestart).not.toHaveBeenCalled();
        });

        it("should return true when flag does not exist", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createFetchAllFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            const result = await eventHandler();
            expect(result).toBe(true);
        });

        it("should execute handle when flag exists and check returns true", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(availableRemoteTweaks({}));
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_DETAILED);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce("cancelled");

            const handler = createFetchAllFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            await eventHandler();

            // When dialog is cancelled, handle returns false
            expect(host.mocks.ui.dialogManager.openWithExplicitCancel).toHaveBeenCalled();
        });

        it("should return handle result when flag exists", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.SUSPEND_ALL);

            const handler = createSuspendFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            const result = await eventHandler();

            // Suspend handler execution results in false from processVaultInitialisation
            expect(typeof result).toBe("boolean");
        });

        it("should not call handle when check returns false", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const handler = createRebuildFlagHandler(host as any, log);
            const handleSpy = vi.spyOn(handler, "handle");
            const eventHandler = flagHandlerToEventHandler(handler);

            const result = await eventHandler();

            // Check returns false because no rebuild flag exists
            expect(handleSpy).not.toHaveBeenCalled();
            expect(result).toBe(true);
        });

        it("should handle rebuild flag with flagHandlerToEventHandler", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce("cancelled");

            const handler = createRebuildFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            await eventHandler();

            expect(host.mocks.ui.dialogManager.openWithExplicitCancel).toHaveBeenCalled();
        });

        it("should propagate errors from handle method", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockRejectedValueOnce(new Error("Dialog failed"));

            const handler = createFetchAllFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            try {
                await eventHandler();
            } catch (error) {
                expect((error as Error).message).toBe("Dialog failed");
            }
        });

        it("should handle fetchAll flag with flagHandlerToEventHandler identical", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValue(availableRemoteTweaks({ customChunkSize: 1 }));

            host.mocks.storageAccess.files.add(FlagFilesOriginal.FETCH_ALL);
            host.mocks.ui.confirm.confirmWithMessage.mockResolvedValueOnce(SIMPLE_FETCH_STAGE1_DETAILED);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce({ vault: "identical", extra: {} });
            host.mocks.rebuilder.$fetchLocal.mockResolvedValueOnce();
            const handler = createFetchAllFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            await Promise.resolve(eventHandler());
            await new Promise((resolve) => setTimeout(resolve, 10));
            expect(host.mocks.rebuilder.$fetchLocal).toHaveBeenCalled();

            expect(host.mocks.ui.dialogManager.openWithExplicitCancel).toHaveBeenCalled();
        });
        it("should handle rebuildAll flag with flagHandlerToEventHandler", async () => {
            const host = createHostMock();
            const log = createLoggerMock();
            Object.assign(host.mocks.setting.settings, TweakValuesShouldMatchedTemplate, {
                encrypt: true,
                passphrase: "local-encryption-passphrase",
            });
            host.mocks.tweakValue.fetchRemotePreferred.mockResolvedValueOnce(
                availableRemoteTweaks({
                    ...TweakValuesShouldMatchedTemplate,
                    encrypt: false,
                })
            );

            host.mocks.storageAccess.files.add(FlagFilesOriginal.REBUILD_ALL);
            host.mocks.ui.dialogManager.openWithExplicitCancel.mockResolvedValueOnce({ extra: {} });
            host.mocks.rebuilder.$rebuildEverything.mockResolvedValueOnce();
            const handler = createRebuildFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            await Promise.resolve(eventHandler());
            await new Promise((resolve) => setTimeout(resolve, 10));
            expect(host.mocks.rebuilder.$rebuildEverything).toHaveBeenCalled();
            expect(host.mocks.setting.currentSettings().encrypt).toBe(true);
            expect(host.mocks.setting.applyExternalSettings).not.toHaveBeenCalled();

            expect(host.mocks.ui.dialogManager.openWithExplicitCancel).toHaveBeenCalled();
        });

        it("should execute all handlers in sequence", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            const suspendHandler = createSuspendFlagHandler(host as any, log);
            const fetchHandler = createFetchAllFlagHandler(host as any, log);
            const rebuildHandler = createRebuildFlagHandler(host as any, log);

            const suspendEvent = flagHandlerToEventHandler(suspendHandler);
            const fetchEvent = flagHandlerToEventHandler(fetchHandler);
            const rebuildEvent = flagHandlerToEventHandler(rebuildHandler);

            // All should return true when flags don't exist
            expect(await suspendEvent()).toBe(true);
            expect(await fetchEvent()).toBe(true);
            expect(await rebuildEvent()).toBe(true);
        });

        it("should return false from handle when suspending", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.files.add(FlagFilesOriginal.SUSPEND_ALL);

            const handler = createSuspendFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            const result = await eventHandler();

            // Suspend handler returns false from its handle method
            expect(result).toBe(false);
        });

        it("should handle check error gracefully", async () => {
            const host = createHostMock();
            const log = createLoggerMock();

            host.mocks.storageAccess.isExists.mockRejectedValueOnce(new Error("Check failed"));

            const handler = createFetchAllFlagHandler(host as any, log);
            const eventHandler = flagHandlerToEventHandler(handler);

            try {
                await eventHandler();
            } catch (error) {
                expect((error as Error).message).toBe("Check failed");
            }
        });
    });
});
