// Copyright (c) 2023 Tudor Stanciu

import React, { useReducer, useMemo } from "react";
import { renderHook } from "@testing-library/react-hooks";
import { TuitioContext, TuitioDispatchContext } from "../../src/contexts";
import { useTuitioUserInfo } from "../../src/hooks";
import { reducer, dispatchActions } from "../../src/reducer";
import { TuitioDispatchActions } from "../../src/types";
import axios from "axios";

jest.mock("axios");

const userInfoMock = {
  userId: 1,
  userName: "tuitio.test",
  firstName: "Tuitio",
  lastName: "Test",
  email: "tuitio.test@lab.com",
  profilePictureUrl: "https://domain/cdn/resources/test.jpg",
  securityStamp: "mock",
  creationDate: "2023-03-08T11:46:31.453",
  failedLoginAttempts: 0,
  lastLoginDate: "2023-03-27T16:09:26.283",
  userRoles: [
    {
      id: 1,
      code: "SYSTEM_ADMINISTRATOR",
      name: "System administrator"
    },
    { id: 2, code: "FULLSTACK_DEVELOPER", name: "Fullstack developer" }
  ],
  userGroups: [
    {
      id: 1,
      code: "ADMINISTRATORS",
      name: "Administrators"
    }
  ]
};

describe("useTuitioUserInfo: dispatchActions", () => {
  const tuitioContextState = {
    auth: {
      userName: null,
      token: null,
      validUntil: null
    },
    configuration: { tuitioUrl: "http://localhost:5063/" }
  };

  let dispatchedActions: TuitioDispatchActions;

  const Wrapper = ({ children }: { children: React.ReactNode }) => {
    const [state, dispatch] = useReducer(reducer, tuitioContextState);
    dispatchedActions = useMemo(() => dispatchActions(dispatch), [dispatch]);

    return (
      <TuitioContext.Provider value={state}>
        <TuitioDispatchContext.Provider value={dispatchedActions}>{children}</TuitioDispatchContext.Provider>
      </TuitioContext.Provider>
    );
  };

  it("useTuitioUserInfo should return the user info obtained from Tuitio's API", async () => {
    (axios.request as jest.Mock).mockResolvedValue({
      data: { ...userInfoMock }
    });

    const { result, waitForNextUpdate } = renderHook(useTuitioUserInfo, { wrapper: Wrapper });
    expect(result.current.userInfo).toBeUndefined();

    const onUserInfoLoadedSpy = jest.spyOn(dispatchedActions, "onUserInfoLoaded");
    await waitForNextUpdate();

    expect(onUserInfoLoadedSpy).toHaveBeenCalled();
    expect(onUserInfoLoadedSpy).toHaveBeenCalledWith(userInfoMock);

    const { userInfo } = result.current;
    expect(userInfo).toBeDefined();
    expect(userInfo?.userId).toBe(1);
    expect(userInfo?.userName).toBe("tuitio.test");
    expect(userInfo?.userRoles).toHaveLength(2);
    expect(userInfo?.userGroups).toHaveLength(1);
  });
});
