import trackingWrapper from "./tracking";
import { AppManifest } from "./types";

describe("trackingWrapper", () => {
  test.each([
    {
      method: "load",
      message: "WalletAPI Load",
    },
    {
      method: "reload",
      message: "WalletAPI Reload",
    },
    {
      method: "loadFail",
      message: "WalletAPI Load Fail",
    },
    {
      method: "loadSuccess",
      message: "WalletAPI Load Success",
    },
    {
      method: "signTransactionRequested",
      message: "WalletAPI SignTransaction",
    },
    {
      method: "signTransactionFail",
      message: "WalletAPI SignTransaction Fail",
    },
    {
      method: "signTransactionSuccess",
      message: "WalletAPI SignTransaction Success",
    },
    {
      method: "requestAccountRequested",
      message: "WalletAPI RequestAccount",
    },
    {
      method: "requestAccountFail",
      message: "WalletAPI RequestAccount Fail",
    },
    {
      method: "requestAccountSuccess",
      message: "WalletAPI RequestAccount Success",
    },
    {
      method: "receiveRequested",
      message: "WalletAPI Receive",
    },
    {
      method: "receiveFail",
      message: "WalletAPI Receive Fail",
    },
    {
      method: "receiveSuccess",
      message: "WalletAPI Receive Success",
    },
    {
      method: "broadcastFail",
      message: "WalletAPI Broadcast Fail",
    },
    {
      method: "broadcastSuccess",
      message: "WalletAPI Broadcast Success",
    },
    {
      method: "broadcastOperationDetailsClick",
      message: "WalletAPI Broadcast OpD Clicked",
    },
    {
      method: "startExchangeRequested",
      message: "WalletAPI start Exchange Nonce request",
    },
    {
      method: "startExchangeSuccess",
      message: "WalletAPI start Exchange Nonce success",
    },
    {
      method: "startExchangeFail",
      message: "WalletAPI start Exchange Nonce fail",
    },
    {
      method: "completeExchangeRequested",
      message: "WalletAPI complete Exchange requested",
    },
    {
      method: "completeExchangeSuccess",
      message: "WalletAPI complete Exchange success",
    },
    {
      method: "completeExchangeFail",
      message: "WalletAPI complete Exchange Nonce fail",
    },
    {
      method: "signMessageRequested",
      message: "WalletAPI sign message requested",
    },
    {
      method: "signMessageSuccess",
      message: "WalletAPI sign message success",
    },
    {
      method: "signMessageFail",
      message: "WalletAPI sign message fail",
    },
    {
      method: "signMessageUserRefused",
      message: "WalletAPI sign message user refused",
    },
  ])(
    "calls once inner trackWalletAPI function $method with event named: $message",
    ({ method, message }) => {
      // Given
      const appManifest = appManifestFixture();
      const mockedTrack = jest.fn();

      // When
      trackingWrapper(mockedTrack)[method](appManifest);

      // Then
      expect(mockedTrack).toHaveBeenCalledTimes(1);
      expect(mockedTrack).toHaveBeenCalledWith(
        message,
        {
          walletAPI: appManifest.name,
        },
        null,
      );
    },
  );
});

describe("trackingWrapper with optional tracking params", () => {
  test.each([
    { method: "signTransactionRequested", message: "WalletAPI SignTransaction" },
    { method: "signTransactionFail", message: "WalletAPI SignTransaction Fail" },
    { method: "signTransactionSuccess", message: "WalletAPI SignTransaction Success" },
  ])("$method includes isEmbeddedSwap and partner when provided", ({ method, message }) => {
    // Given
    const appManifest = appManifestFixture();
    const mockedTrack = jest.fn();

    // When
    trackingWrapper(mockedTrack)[method](appManifest, true, "uniswap");

    // Then
    expect(mockedTrack).toHaveBeenCalledTimes(1);
    expect(mockedTrack).toHaveBeenCalledWith(
      message,
      {
        walletAPI: appManifest.name,
        isEmbeddedSwap: "true",
        partner: "uniswap",
      },
      null,
    );
  });
});

describe("trackingWrapper broadcast with BroadcastTrackingData", () => {
  test.each([
    { method: "broadcastFail", message: "WalletAPI Broadcast Fail" },
    { method: "broadcastSuccess", message: "WalletAPI Broadcast Success" },
  ])("$method includes all properties when provided", ({ method, message }) => {
    // Given
    const appManifest = appManifestFixture();
    const mockedTrack = jest.fn();

    // When
    trackingWrapper(mockedTrack)[method](appManifest, {
      isEmbeddedSwap: true,
      partner: "uniswap",
      sourceCurrency: "Bitcoin",
      targetCurrency: "LBTC",
      network: "bitcoin",
    });

    // Then
    expect(mockedTrack).toHaveBeenCalledTimes(1);
    expect(mockedTrack).toHaveBeenCalledWith(
      message,
      {
        walletAPI: appManifest.name,
        isEmbeddedSwap: "true",
        partner: "uniswap",
        sourceCurrency: "Bitcoin",
        targetCurrency: "LBTC",
        network: "bitcoin",
      },
      null,
    );
  });

  test.each([
    { method: "broadcastFail", message: "WalletAPI Broadcast Fail" },
    { method: "broadcastSuccess", message: "WalletAPI Broadcast Success" },
  ])(
    "$method includes only sourceCurrency and network when targetCurrency is not available",
    ({ method, message }) => {
      // Given
      const appManifest = appManifestFixture();
      const mockedTrack = jest.fn();

      // When
      trackingWrapper(mockedTrack)[method](appManifest, {
        sourceCurrency: "Ethereum",
        network: "ethereum",
      });

      // Then
      expect(mockedTrack).toHaveBeenCalledTimes(1);
      expect(mockedTrack).toHaveBeenCalledWith(
        message,
        {
          walletAPI: appManifest.name,
          sourceCurrency: "Ethereum",
          network: "ethereum",
        },
        null,
      );
    },
  );

  test.each([
    { method: "broadcastFail", message: "WalletAPI Broadcast Fail" },
    { method: "broadcastSuccess", message: "WalletAPI Broadcast Success" },
  ])("$method works with no data (backward compatible)", ({ method, message }) => {
    // Given
    const appManifest = appManifestFixture();
    const mockedTrack = jest.fn();

    // When
    trackingWrapper(mockedTrack)[method](appManifest);

    // Then
    expect(mockedTrack).toHaveBeenCalledTimes(1);
    expect(mockedTrack).toHaveBeenCalledWith(
      message,
      {
        walletAPI: appManifest.name,
      },
      null,
    );
  });
});

function appManifestFixture(name = "live-app"): AppManifest {
  return {
    id: "12",
    name,
    url: "https://www.ledger.fr",
    homepageUrl: "https://www.ledger.fr",
    platforms: ["ios", "android", "desktop"],
    apiVersion: "1.0.0",
    manifestVersion: "1.0.0",
    branch: "debug",
    categories: ["test"],
    currencies: "*",
    content: {
      shortDescription: {
        en: "test",
      },
      description: {
        en: "test",
      },
    },
    permissions: [],
    domains: [],
    visibility: "complete",
  };
}
