import { describe, expect, it, vi } from "vitest";
import {
  VaultfireSDK,
  type V2CompatibilityClient,
  type V3VersionClient,
} from "../../sdk/facade";
import {
  V3WritesBlockedError,
  VaultfireSDKv3,
} from "../../sdk/v3/client";

describe("VaultfireSDK version routing", () => {
  it("routes reads to the selected version", async () => {
    const v2 = { read: vi.fn(async () => "legacy"), write: vi.fn() };
    const v3 = { read: vi.fn(async () => "current"), write: vi.fn() };
    const sdk = new VaultfireSDK(v2 as V2CompatibilityClient, v3 as V3VersionClient);

    await expect(sdk.read("v2", "bond", 1)).resolves.toEqual({ version: "v2", data: "legacy" });
    await expect(sdk.read("v3", "bond", 1)).resolves.toEqual({ version: "v3", data: "current" });
    expect(v2.read).toHaveBeenCalledTimes(1);
    expect(v3.read).toHaveBeenCalledTimes(1);
  });

  it("never redirects writes across versions", async () => {
    const v2 = { read: vi.fn(), write: vi.fn(async () => "v2tx") };
    const v3 = { read: vi.fn(), write: vi.fn(async () => "v3tx") };
    const sdk = new VaultfireSDK(v2 as V2CompatibilityClient, v3 as V3VersionClient);

    await expect(sdk.write("v2", "create", {})).resolves.toEqual({ version: "v2", data: "v2tx" });
    await expect(sdk.write("v3", "create", {})).resolves.toEqual({ version: "v3", data: "v3tx" });
    expect(v2.write).toHaveBeenCalledTimes(1);
    expect(v3.write).toHaveBeenCalledTimes(1);
  });
});

describe("VaultfireSDKv3 pause gate", () => {
  const config = {
    baseUrl: "https://example.test",
    defaultChainId: 8453,
    rpcUrls: {},
    x402: { payer: "0x0", assetPerChain: {}, payeePerChain: {} },
  };

  it("fails closed on a degraded status response", async () => {
    vi.stubGlobal("fetch", vi.fn(async () =>
      Response.json({ status: "degraded", protocolVersion: "v3", v3: { pausedContracts: null } }, { status: 503 })
    ));
    await expect(new VaultfireSDKv3(config).pauseGate()).rejects.toBeInstanceOf(V3WritesBlockedError);
    vi.unstubAllGlobals();
  });

  it("fails closed on an HTTP-200 status response missing the required envelope", async () => {
    vi.stubGlobal("fetch", vi.fn(async () =>
      Response.json({ status: "ok", protocolVersion: "v3", data: { v3: { pausedContracts: [] } } })
    ));
    await expect(new VaultfireSDKv3(config).pauseGate()).rejects.toBeInstanceOf(V3WritesBlockedError);
    vi.unstubAllGlobals();
  });

  it("returns pause state only for a healthy typed response", async () => {
    vi.stubGlobal("fetch", vi.fn(async () =>
      Response.json({
        chainId: 8453,
        contractAddress: "0x1111111111111111111111111111111111111111",
        protocolVersion: "v3",
        contractStatus: "active",
        status: "ok",
        blockNumber: "1",
        blockHash: `0x${"22".repeat(32)}`,
        observedAt: "2026-08-20T00:00:00.000Z",
        finality: "safe",
        dataSourceErrors: [],
        schemaVersion: "1.0.0",
        data: { v3: { pausedContracts: ["0xabc"] } },
      })
    ));
    await expect(new VaultfireSDKv3(config).pauseGate()).resolves.toBe(true);
    vi.unstubAllGlobals();
  });
});
