import configureMockStore from "redux-mock-store";

import {
  setServerPreferences,
  setI18n,
  setConfigurationTheme,
} from "../serverUtil";
import { IllegalArgumentException } from "../../exceptions";

import { availableLocales, Locales } from "../../i18n";

globalThis.preferencesProvider = {
  getPreferenceByName: jest.fn(),
  getLayoutConfigFileLocation: () => "/theme",
};

const mockStore = configureMockStore();

const getExpectedLocales = () =>
  new Locales([
    ...availableLocales.map((locale) =>
      locale.code === "nl"
        ? {
            ...locale,
            messages: {
              message_nl: "Dutch message",
            },
          }
        : locale,
    ),
  ]);

describe("serverUtil", () => {
  it("handles setI18n", () => {
    const store = mockStore({ i18n: {} });

    expect(() => setI18n(store)).toThrow(IllegalArgumentException);
    expect(() => setI18n(store, "bla")).toThrow(IllegalArgumentException);

    setI18n(
      store,
      [
        {
          code: "nl",
          messages: {
            message_nl: "Dutch message",
          },
        },
      ],
      {
        getHeader: () => "",
        getCookieByName: () => "",
      },
    );

    expect(store.getActions()).toStrictEqual([
      {
        type: "SET_LOCALES",
        payload: {
          locale: "en",
          locales: getExpectedLocales(),
        },
      },
    ]);
  });

  it("setConfigurationTheme", () => {
    global.dataFetcher = {
      fetch: () => '{ "prop": "value" }',
    };

    const store = mockStore({ preferences: {} });

    setConfigurationTheme(store);

    expect(store.getActions()).toStrictEqual([
      {
        type: "SET_PREFERENCE",
        payload: {
          theme: {
            prop: "value",
          },
        },
      },
    ]);
  });

  it("setServerPreferences by array of strings", () => {
    const store = mockStore({ preferences: {} });

    setServerPreferences(store, ["prefA", "prefB"]);

    expect(store.getActions()).toStrictEqual([
      {
        type: "SET_PREFERENCE",
        payload: {
          prefA: null,
        },
      },
      {
        type: "SET_PREFERENCE",
        payload: {
          prefB: null,
        },
      },
      {
        type: "SET_PREFERENCE",
        payload: {
          hasAllContentInData: false,
        },
      },
      {
        type: "SET_PREFERENCES",
        payload: {
          "FormClient.login_url": "/callback?client_name=FormClient",
          "FormClient.logout_url": "/logout",
          "FormClient.password_field_name": "j_password",
          "FormClient.username_field_name": "j_username",
          "security.clients": null,
        },
      },
      {
        type: "SET_PREFERENCE",
        payload: {
          isIncludeTimeOffsetInDateTimes: false,
        },
      },
    ]);
  });

  it("setServerPreferences by array of objects", () => {
    const store = mockStore({ preferences: {} });

    setServerPreferences(store, [
      { name: "prefA", defaultValue: "defaultA" },
      { name: "prefB", defaultValue: "defaultB, defaultB2" },
      { name: "prefC", defaultValue: "defaultC, defaultC2", type: "string" },
    ]);

    expect(store.getActions()).toStrictEqual([
      {
        type: "SET_PREFERENCE",
        payload: {
          prefA: "defaultA",
        },
      },
      {
        type: "SET_PREFERENCE",
        payload: {
          prefB: ["defaultB", "defaultB2"],
        },
      },
      {
        type: "SET_PREFERENCE",
        payload: {
          prefC: "defaultC, defaultC2",
        },
      },
      {
        type: "SET_PREFERENCE",
        payload: {
          hasAllContentInData: false,
        },
      },
      {
        type: "SET_PREFERENCES",
        payload: {
          "FormClient.login_url": "/callback?client_name=FormClient",
          "FormClient.logout_url": "/logout",
          "FormClient.password_field_name": "j_password",
          "FormClient.username_field_name": "j_username",
          "security.clients": null,
        },
      },
      {
        type: "SET_PREFERENCE",
        payload: {
          isIncludeTimeOffsetInDateTimes: false,
        },
      },
    ]);
  });
});
