import * as React from "react";
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
import ButtonSliderGroup from "./ButtonSliderGroup";

const props = {
  value: 10,
  maxValue: 95,
  minValue: 0,
  onChange: (): any => null,
};
const button1 = {
  value: 23,
  style: { padding: 35 },
  icon: "TestingIcon",
};
const button2 = {
  value: "GROW",
  style: { padding: 25 },
  icon: "ButtonTwoIconTest",
};
const getSliderValue = (container) => {
  return parseInt(container.querySelectorAll("input[type='hidden']")[0].value);
};

describe("<ButtonSliderGroup /> Rendering >", () => {
  afterEach(cleanup);

  it(`Should render component in the dom`, () => {
    render(<ButtonSliderGroup {...props} />);
    expect(screen.getByTestId("ButtonSliderGroup")).not.toBe(null);
  });

  it(`Should render a _Max Value_ checkbox when the showMaxCheck prop is true`, () => {
    render(<ButtonSliderGroup {...props} showMaxCheck />);
    expect(screen.queryByTestId("ButtonSliderGroup-maxCheck")).toBeTruthy();
  });

  it(`Should render the _Auto Set_ checkbox when the showAutoCheck prop is set to true`, () => {
    render(<ButtonSliderGroup {...props} showMaxCheck showAutoCheck />);
    expect(screen.queryByTestId("ButtonSliderGroup-autoCheck")).toBeTruthy();
  });

  it("Should render a slider if the showSlider prop is set to true", () => {
    render(<ButtonSliderGroup {...props} showSlider />);
    expect(screen.queryByTestId("ButtonSliderGroup-slider")).toBeTruthy();
  });

  it(`Slider should be positioned at the value provided in the prop`, () => {
    const value = 50;

    const { container } = render(
      <ButtonSliderGroup {...props} showSlider value={value} />
    );

    const sliderValue = getSliderValue(container);

    expect(sliderValue).toBe(value);
  });

  it(`Should not show a slider when the showSlider prop is set to false`, () => {
    render(<ButtonSliderGroup {...props} showSlider={false} />);
    expect(screen.queryByTestId("ButtonSliderGroup-slider")).toBe(null);
  });

  it(`Should show a label caption for the group using the label prop`, () => {
    const randomText = Math.random()
      .toString(36)
      .slice(2);
    render(<ButtonSliderGroup {...props} label={randomText} />);
    expect(screen.getByText(randomText)).not.toBe(null);
  });

  it(`Should render a button with the value, style, events, icon attributes provided in the button1 prop`, () => {
    const onChange = jest.fn();

    const { debug, getByTestId, queryByText } = render(
      <ButtonSliderGroup
        {...props}
        button1={button1}
        onValueChange={onChange}
      />
    );
    fireEvent.click(getByTestId("ButtonSliderGroup-Button1"));

    expect(queryByText(button1.icon)).not.toBe(null);
    expect(onChange.mock.calls[0][0]).toBe(button1.value);
    expect(getByTestId("ButtonSliderGroup-Button1").getAttribute("style")).toBe(
      `padding: ${button1.style.padding}px;`
    );
  });

  it(`Should render a button with the value, style, events, icon attributes provided in the button2 prop`, () => {
    const onChange = jest.fn();

    render(
      <ButtonSliderGroup
        {...props}
        button2={button2}
        onValueChange={onChange}
        // onValueChange={(value) => document.write(value)}
      />
    );
    fireEvent.click(screen.getByTestId("ButtonSliderGroup-Button2"));

    expect(screen.queryByText(button2.icon)).not.toBe(null);
    expect(onChange.mock.calls[0][0]).toBe(button2.value);
    expect(
      screen.getByTestId("ButtonSliderGroup-Button2").getAttribute("style")
    ).toBe(`padding: ${button2.style.padding}px;`);
  });

  it(`Should not allow any values below the provided minValue prop`, () => {
    const { container } = render(
      <ButtonSliderGroup {...props} showSlider value={63} maxValue={44} />
    );
    expect(getSliderValue(container)).toBe(44);
  });

  it(`Should not allow any values above the provided maxValue prop`, () => {
    const { container } = render(
      <ButtonSliderGroup {...props} showSlider value={63} minValue={75} />
    );
    expect(getSliderValue(container)).toBe(75);
  });

  test.skip(`Should show a tooltip when the group is hovered over`, () => {});
});

describe("<ButtonSliderGroup /> Actions >", () => {
  afterEach(cleanup);

  // it(`Should set the value to the autoCheckValue prop's value when the _Auto_ checkbox is checked`, () => {
  //   expect(true).toBe(false);
  // });

  it(`Should set the value to the maxCheckValue prop's value when the _Max_ checkbox is checked`, () => {
    // render it
    const { container, debug } = render(
      <ButtonSliderGroup {...props} showSlider showMaxCheck />
    );

    // click the checkbox
    fireEvent.click(container.querySelectorAll("input[type='checkbox']")[0]);

    // confirm that the value is the maxValue
    expect(getSliderValue(container)).toBe(props.maxValue);
  });

  it(`Should immediately uncheck the MaxCheck checkbox when the button is clicked or slider is changed`, () => {
    // render it
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        showMaxCheck
        __testSliderValue={25}
      />
    );

    // click the max check box (on)
    fireEvent.click(container.querySelectorAll('input[type="checkbox"]')[0]);

    // confirm that the max checkbox is on
    expect(getSliderValue(container)).toBe(props.maxValue);
    expect(
      screen.getByTestId("ButtonSliderGroup-maxCheck").getAttribute("class")
    ).toContain("Mui-checked");

    // set the slider value
    fireEvent.click(screen.getByTestId("__testSliderValueUpdate"));

    // confirm that the max checkbox is off
    expect(
      screen.getByTestId("ButtonSliderGroup-maxCheck").getAttribute("class")
    ).not.toContain("Mui-checked");
  });

  it(`Should immediately uncheck the AutoCheck checkbox when the button is clicked or slider is changed`, () => {
    // render it
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        showAutoCheck
        __testSliderValue={25}
      />
    );

    // click the max check box (on)
    fireEvent.click(container.querySelectorAll('input[type="checkbox"]')[0]);

    // confirm that the auto check checkbox is on
    expect(
      screen.getByTestId("ButtonSliderGroup-autoCheck").getAttribute("class")
    ).toContain("Mui-checked");

    // set the slider value
    fireEvent.click(screen.getByTestId("__testSliderValueUpdate"));

    // confirm that the autoCheck checkbox is off
    expect(
      screen.getByTestId("ButtonSliderGroup-autoCheck").getAttribute("class")
    ).not.toContain("Mui-checked");
  });

  it(`Should automatically check the MaxCheck Checkbox when the slider is at the maximum position`, () => {
    // render it normally
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        showMaxCheck
        __testSliderValue={props.maxValue}
      />
    );
    // set the slider to the max position
    fireEvent.click(screen.getByTestId("__testSliderValueUpdate"));

    // confirm that the checkbox is on
    expect(
      screen.getByTestId("ButtonSliderGroup-maxCheck").getAttribute("class")
    ).toContain("Mui-checked");
  });

  it(`Should position the value of the slider to the max position if the MaxCheck checkbox is checked`, () => {
    // render the component
    const { container, debug } = render(
      <ButtonSliderGroup {...props} showSlider showMaxCheck />
    );

    // click the max checkbox
    fireEvent.click(container.querySelectorAll('input[type="checkbox"]')[0]);

    // confirm that the slider value is the same as the max value
    expect(getSliderValue(container)).toBe(props.maxValue);
  });

  it(`Should revert the value back to the original value if the _Auto_ checkbox is un-checked`, () => {
    const value = 64;

    // render the component
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        showAutoCheck
        autoCheckValue={value}
      />
    );
    // click the autocheck checkbox
    fireEvent.click(container.querySelectorAll('input[type="checkbox"]')[0]);

    // confirm that the slider value matches the originalValue prop
    expect(getSliderValue(container)).toBe(value);
  });
});

describe("<ButtonSliderGroup /> Events >", () => {
  afterEach(cleanup);

  it(`Should trigger the onChange() event with the new value when either of the buttons are clicked`, () => {
    const onChange = jest.fn();
    // render the component
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        button1={button1}
        onValueChange={onChange}
      />
    );

    // click one of the buttons
    fireEvent.click(screen.getByTestId("ButtonSliderGroup-Button1"));
    // confirm that the onChange event was fired and the value was passed
    expect(onChange.mock.calls[0][0]).toBe(button1.value);
  });

  it(`Should trigger the onChange() event with the new value when the slider is moved`, () => {
    const value = 66;
    const onChange = jest.fn();
    // render the component
    const { container, debug } = render(
      <ButtonSliderGroup
        {...props}
        showSlider
        __testSliderValue={value}
        onValueChange={onChange}
      />
    );

    // change the slider position
    fireEvent.click(screen.getByTestId("__testSliderValueUpdate"));

    // confirm that the onChange event was fired and the value was passed
    expect(onChange.mock.calls[0][0]).toBe(value);
  });
});

describe("<ButtonSliderGroup /> Hooks >", () => {
  afterEach(cleanup);
  test.skip(`Should trigger the _onButtonSliderGroupRender_ plugin hook when the ButtonSliderGroup component renders`, () => {});

  test.skip(`Should trigger the _onButtonSliderGroupChange_ plugin hook when the value of the ButtonSliderGroup property changes`, () => {});

  test.skip(`Should trigger the onButtonSliderGroupFinish plugin hook when the mouse button is released (on the button or slider)`, () => {});
});
