import * as React from "react";
import "@babel/polyfill";
import "@testing-library/jest-dom/extend-expect";
import {
  render,
  screen,
  within,
  fireEvent,
  cleanup,
} from "@testing-library/react";
import {
  mockGetComputedSpacing,
  mockDndElSpacing,
  makeDnd,
  DND_DRAGGABLE_DATA_ATTR,
  DND_DIRECTION_DOWN,
  DND_DIRECTION_UP,
} from "react-beautiful-dnd-test-utils";

import SectionsLegend from "./SectionsLegend";
import { PageSectionCategory } from "@sc/plugins/misc/v2/blocks/weblayouts/types";

const sections = [
  {
    id: "sdkfj",
    label: "Take out the garbage",
    type: PageSectionCategory.HEADER,
  },
  {
    id: "dskjf",
    label: "Watch my favorite show",
    type: PageSectionCategory.HEADER,
  },
  { id: "vmkds", label: "Charge my phone", type: PageSectionCategory.HEADER },
  { id: "fsdvs", label: "Cook dinner", type: PageSectionCategory.HEADER },
];

describe("Rendering > <SectionsLegend /> Tests", () => {
  afterEach(cleanup);
  it(`Should render in the dom`, () => {
    render(<SectionsLegend />);
    expect(screen.queryByTestId("Blocks-SectionsLegend")).toBeTruthy();
  });

  it(`Should show an Add New Section button in the dom`, () => {
    render(<SectionsLegend />);
    expect(
      screen.queryByTestId("Blocks-SectionsLegend-AddNewButton")
    ).toBeTruthy();
  });

  it(`Should show a title in the dom that matches the title string passed in the prosp`, () => {
    const title = "Testing Title";
    render(<SectionsLegend title={title.toUpperCase()} />);
    expect(screen.queryByText(title.toUpperCase())).toBeTruthy();
  });

  it(`Should show a list of <SectionItem /> elements...the amount should match the number of sections passed in the sections array`, () => {
    render(<SectionsLegend sections={sections} />);
    expect(
      screen.queryAllByTestId("Blocks-SectionsLegend-SectionItem").length
    ).toEqual(sections.length);
  });
});

describe("Events > <SectionsLegend /> Tests", () => {
  afterEach(cleanup);
  beforeEach(() => {
    mockGetComputedSpacing();
  });

  test(`Should trigger the onChange event when the sections are re-ordered via drag-and-drop`, async () => {
    const onChange = jest.fn();

    const rtlUtils = render(
      <SectionsLegend sections={sections} onChange={onChange} />
    );

    const { getByText } = rtlUtils;
    mockDndElSpacing(rtlUtils);
    const makeGetDragEl = (text) => () =>
      rtlUtils.getByText(text).closest(DND_DRAGGABLE_DATA_ATTR);

    await makeDnd({
      getByText,
      getDragEl: makeGetDragEl("Take out the garbage".toUpperCase()),
      direction: DND_DIRECTION_DOWN,
      positions: 2,
    });

    expect(onChange).toBeCalled();
  });

  it(`Should trigger the onCreate event when the add new button is clicked`, () => {
    const onCreate = jest.fn();
    render(<SectionsLegend onCreate={onCreate} />);
    fireEvent.click(screen.getByTestId("Blocks-SectionsLegend-AddNewButton"));
    expect(onCreate).toBeCalled();
  });
});

describe("Methods > <SectionsLegend /> Tests", () => {
  afterEach(cleanup);

  beforeEach(() => {
    mockGetComputedSpacing();
  });

  it(`Should return an updated list of settings from the onChange event return function when the sections are re-ordered via drag and drop`, async () => {
    const onChange = jest.fn();

    mockDndElSpacing(
      render(<SectionsLegend sections={sections} onChange={onChange} />)
    );

    const positions = 4;

    await makeDnd({
      getByText: screen.getByText,
      getDragEl: () =>
        screen
          .queryAllByTestId("Blocks-SectionsLegend-SectionItem")[0]
          .closest(DND_DRAGGABLE_DATA_ATTR),
      direction: DND_DIRECTION_DOWN,
      positions,
    });

    expect(onChange.mock.calls[0][0][1]).toMatchObject(sections[0]);
  });

  it(`Should toggle beteween open and close when the hide button is clicked`, () => {
    render(<SectionsLegend />);

    fireEvent.click(screen.getByTestId("Blocks-SectionsLegend-ShowHideToggle"));
    expect(
      screen.queryByTestId("Blocks-SectionsLegend-AddNewButton")
    ).toBeNull();

    fireEvent.click(screen.getByTestId("Blocks-SectionsLegend-ShowHideToggle"));
    expect(
      screen.queryByTestId("Blocks-SectionsLegend-AddNewButton")
    ).toBeTruthy();
  });
});
