import { beforeEach, describe, expect, it } from "vitest";
import { createStorage } from "unstorage";
import memoryDriver from "unstorage/drivers/memory";

import { StorageKeys } from "@/data/storage/storage_keys";
import { runStorageMigrations } from "@/data/storage/storage_migration";
import { SpAsyncUtil } from "@/utils/storage";

describe("runStorageMigrations", () => {
  beforeEach(() => {
    SpAsyncUtil.setStorage(createStorage({ driver: memoryDriver() }));
  });

  it("moves legacy facebook id into asid", async () => {
    await SpAsyncUtil.setString("facebook_id", "asid-legacy");

    const result = await runStorageMigrations();

    expect(result.success).toBe(true);
    await expectString(StorageKeys.asid, "asid-legacy");
    await expectString("facebook_id", null);
  });

  it("does not overwrite existing asid", async () => {
    await SpAsyncUtil.setString(StorageKeys.asid, "asid-current");
    await SpAsyncUtil.setString("facebook_id", "asid-legacy");

    const result = await runStorageMigrations();

    expect(result.success).toBe(true);
    await expectString(StorageKeys.asid, "asid-current");
    await expectString("facebook_id", null);
  });

  it("migrates legacy pwa dialog markers and removes old keys", async () => {
    await SpAsyncUtil.setString("last_pwa_dialog_shown", "2026-01-01");

    const result = await runStorageMigrations();

    expect(result.success).toBe(true);
    const shown = await SpAsyncUtil.getBool(StorageKeys.pwaDialogShown);
    expect(shown).toEqual({ success: true, data: true });
    await expectString("last_pwa_dialog_shown", null);
  });

  it("records migration version and skips repeated migrations", async () => {
    await SpAsyncUtil.setString("facebook_id", "asid-legacy");
    await expectSuccess(runStorageMigrations());
    await SpAsyncUtil.setString("facebook_id", "asid-new-legacy");

    await expectSuccess(runStorageMigrations());

    await expectString(StorageKeys.asid, "asid-legacy");
    await expectString("facebook_id", "asid-new-legacy");
    const version = await SpAsyncUtil.getInt(StorageKeys.storageMigrationVersion);
    expect(version).toEqual({ success: true, data: 1 });
  });
});

async function expectString(
  key: string,
  expected: string | null,
): Promise<void> {
  const value = await SpAsyncUtil.getString(key);
  expect(value).toEqual({ success: true, data: expected });
}

async function expectSuccess(
  resultPromise: Promise<{ success: boolean }>,
): Promise<void> {
  const result = await resultPromise;
  expect(result.success).toBe(true);
}
