import { fireEvent, render, screen, within } from "@testing-library/react";
import { useSnackbar } from "@refinedev/mui";

import { useAppNotificationProvider } from "./useAppNotificationProvider";

jest.mock("@refinedev/mui", () => ({
  useSnackbar: jest.fn(),
}));

const mockedUseSnackbar = useSnackbar as jest.MockedFunction<typeof useSnackbar>;

const TestComponent = ({
  cancelMutation,
}: {
  cancelMutation?: () => void;
}) => {
  const notificationProvider = useAppNotificationProvider();

  return (
    <button
      type="button"
      onClick={() =>
        notificationProvider.open({
          key: "analysis-progress",
          type: "progress",
          message: "分析中",
          undoableTimeout: 3,
          cancelMutation,
        })
      }
    >
      Open progress
    </button>
  );
};

describe("useAppNotificationProvider", () => {
  const enqueueSnackbar = jest.fn();
  const closeSnackbar = jest.fn();

  beforeEach(() => {
    jest.clearAllMocks();
    mockedUseSnackbar.mockReturnValue({
      enqueueSnackbar,
      closeSnackbar,
    } as unknown as ReturnType<typeof useSnackbar>);
  });

  it("does not render an undo action for progress notifications without cancellation", async () => {
    render(<TestComponent />);

    fireEvent.click(screen.getByRole("button", { name: "Open progress" }));

    expect(enqueueSnackbar).toHaveBeenCalledTimes(1);
    expect(enqueueSnackbar.mock.calls[0][1]).toMatchObject({
      key: "analysis-progress",
      preventDuplicate: true,
      autoHideDuration: 3000,
    });
    expect(enqueueSnackbar.mock.calls[0][1]).not.toHaveProperty("action");
  });

  it("keeps undo action for progress notifications with cancellation", async () => {
    const cancelMutation = jest.fn();
    render(<TestComponent cancelMutation={cancelMutation} />);

    fireEvent.click(screen.getByRole("button", { name: "Open progress" }));

    const options = enqueueSnackbar.mock.calls[0][1];
    expect(options.action).toEqual(expect.any(Function));

    const undoAction = render(options.action("progress-key"));
    fireEvent.click(within(undoAction.container).getByRole("button"));

    expect(cancelMutation).toHaveBeenCalledTimes(1);
    expect(closeSnackbar).toHaveBeenCalledWith("progress-key");
  });
});
