import * as React from "react";
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
import reactToCSS from "react-style-object-to-css";
import { styleClean } from "@sc/utils";

import LinearScaleField from "./LinearScaleField";
import { EditorMode } from "../../../../Editor/types";
import { AttributeContainer } from "@sc/modules/v2/CRUD/AttributeBuilder";
import { AttributeNames } from "@sc/modules/v2/CRUD/AttributeBuilder/types";
import { LinearScaleDisplayType } from "../types";
import { styleData } from "../../FormBuilder.stories";
import { IconTypes } from "@sc/plugins/webcomponents/v2/Icon";

const testId = "FormBuilder-FormFields-LinearScaleField";
const props = {
  styles: styleData,
  attributeContainerDataSettings: { hide: false },
};

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

  it(`Should render in the dom`, () => {
    render(<LinearScaleField {...props} />);
    expect(screen.queryByTestId(testId)).toBeTruthy();
  });

  it(`Should render an EDITOR or LIVE version of the component based on the value of the mode prop`, () => {
    const testIdLive = "FormBuilder-FormFields-LinearScaleField-LIVE";
    const testIdEditor = "FormBuilder-FormFields-LinearScaleField-EDITOR";

    const { rerender } = render(
      <LinearScaleField {...props} mode={EditorMode.LIVE} />
    );
    expect(screen.queryByTestId(testIdLive)).toBeTruthy();

    rerender(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(testIdEditor)).toBeTruthy();
  });

  it(`Should render some radio buttons when the mode is live.  The amount should match the max value prop`, () => {
    const testIdLive = "FormBuilder-FormFields-LinearScaleField-LIVE";
    const min = 1;
    const max = 5;
    render(<LinearScaleField {...props} min={min} max={max} />);
    expect(
      screen.queryByTestId(testIdLive).querySelectorAll("input").length
    ).toEqual(max - min + 1);
  });

  it(`Should render the AttributeContainer component when the mode is edit`, () => {
    const attrTestId = "FormBuilder-AttributeContainer";
    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(attrTestId)).toBeTruthy();
  });

  it(`Should see that the <Label /> component has been rendered in the dom`, () => {
    const labelTestId = "FormBuilder-Attributes-Label";
    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(labelTestId)).toBeTruthy();
  });

  it(`Should see that the <Description /> component has been rendered in the dom`, () => {
    const descriptionTestId = "FormBuilder-Attributes-Description";
    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(descriptionTestId)).toBeTruthy();
  });

  it(`Should see that the <Column /> component has been rendered in the dom`, () => {
    const columnsTestId = "FormBuilder-Attributes-Columns";
    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(columnsTestId)).toBeTruthy();
  });

  it(`Should see an option for selecting minimum and maximum range of numbers (e.g. 1 to 5) displayed in the dom`, () => {
    const testId = "FormBuilder-FormFields-LinearScaleField-MinMax";
    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(testId)).toBeTruthy();
  });

  it(`Should see an option to set the content for the first and last label`, () => {
    const testId1 = "FormBuilder-FormFields-LinearScaleField-MinLabel";
    const testId2 = "FormBuilder-FormFields-LinearScaleField-MaxLabel";

    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(testId1)).toBeTruthy();
    expect(screen.queryByTestId(testId2)).toBeTruthy();
  });

  it(`Should see an option for showing the component using radio buttons or a slider`, () => {
    const testId = "FormBuilder-FormFields-LinearScaleField-RadioOrSlider";
    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(testId)).toBeTruthy();
  });

  test.skip(`Should render a button slider when the mode is live and type is slider`, () => {
    const testId = "ButtonSliderGroup";
    render(
      <LinearScaleField
        {...props}
        mode={EditorMode.LIVE}
        type={LinearScaleDisplayType.SLIDER}
      />
    );
    expect(screen.queryByTestId(testId)).toBeTruthy();
  });

  it(`Should see that the <Required /> component has been rendered in the dom`, () => {
    const requiredTestId = "FormBuilder-Attributes-Required";
    render(<LinearScaleField {...props} mode={EditorMode.EDITOR} />);
    expect(screen.queryByTestId(requiredTestId)).toBeTruthy();
  });

  it(`Should render an descriptionStyle, containerStyle, and labelStyle when specified`, () => {
    const label = "Label Check";
    const description = "Description Check";

    render(
      <LinearScaleField
        {...props}
        icon={IconTypes.Email}
        label={label}
        description={description}
      />
    );

    // descriptionStyle
    expect(
      styleClean(screen.getByText(description).getAttribute("style"))
    ).toContain(styleClean(reactToCSS(styleData.descriptionStyle)));

    // containerStyle
    expect(
      styleClean(screen.getByTestId(testId).getAttribute("style"))
    ).toContain(styleClean(reactToCSS(styleData.containerStyle)));

    // labelStyle
    expect(styleClean(screen.getByText(label).getAttribute("style"))).toContain(
      styleClean(reactToCSS(styleData.labelStyle))
    );
  });

  test.skip(`Should only see that the <Validation /> component has been rendered if the "hide" value is false`, () => {});
});

describe("<LinearScaleField /> Event Tests", () => {
  afterEach(cleanup);

  test.todo(
    `Should trigger the onChange event (via handleChange()) if the AttributeContainer's onChange event is called`
  );

  test.skip(`Should trigger the onChange event if the "radio or slider" option is changed (live mode)`, () => {
    const onChange = jest.fn();
    const { rerender } = render(
      <LinearScaleField
        {...props}
        onChange={onChange}
        mode={EditorMode.LIVE}
        type={LinearScaleDisplayType.RADIO}
      />
    );
    fireEvent.click(
      screen
        .getByTestId("FormBuilder-FormFields-LinearScaleField-LIVE")
        .querySelectorAll("input")[0],
      { target: { value: "" } }
    );
    expect(onChange).toBeCalled();

    rerender(
      <LinearScaleField
        {...props}
        onChange={onChange}
        mode={EditorMode.LIVE}
        type={LinearScaleDisplayType.SLIDER}
      />
    );
    fireEvent.click(screen.getByTestId("__testSliderValueUpdate"));

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

  test.skip(`Should trigger the onChange event (with appropriate payload) if the "min/max" option is changed (live and edit mode)`, () => {
    const testId = "FormBuilder-FormFields-LinearScaleField-MinMax";
    const onChange = jest.fn();
    render(<LinearScaleField {...props} onChange={onChange} />);
    fireEvent.change(screen.getByTestId(testId).querySelectorAll("select")[0], {
      target: { value: "" },
    });
    expect(onChange).toBeCalled();
  });

  test.skip(`Should trigger the onChange event (with appropriate payload) if the first or last label caption is changed`, () => {
    const testId = "FormBuilder-FormFields-LinearScaleField-RadioOrSlider";
    const onChange = jest.fn();
    render(<LinearScaleField {...props} onChange={onChange} />);
    fireEvent.click(screen.getByTestId(testId).querySelectorAll("input")[0], {
      target: { value: "" },
    });
    expect(onChange).toBeCalled();
  });
});

describe("<LinearScaleField /> Action Tests", () => {
  afterEach(cleanup);

  test.todo(
    `handleChange should convert the incoming payload to LiveFormFieldProps`
  );

  test.todo(`Should render radio buttons or slider buttons when selected`);
});
