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

import LiveFormField from "./LiveFormField";
import { FormFieldTypes } from "../types";
import { IconTypes } from "@sc/plugins/webcomponents/v2/Icon";
import { IListItem } from "../FormFields/types";

const testId = "FormBuilder-LiveFormField";
const props = {};

const textFieldTestId = "FormBuilder-FormFields-TextField-LIVE";
const dateFieldTestId = "FormBuilder-FormFields-DateField-LIVE";
const dropDownTestId = "FormBuilder-FormFields-DropdownField-LIVE";
const textAreaTestId = "FormBuilder-FormFields-TextAreaField-LIVE";
const checkboxesTestId = "FormBuilder-FormFields-Checkboxes";
const multipleChoiceTestId = "FormBuilder-FormFields-MultipleChoice";
const contentFieldTestId = "FormBuilder-FormFields-ContentField";
const fileUploadTestId = "FormBuilder-FormFields-FileUpload";
const linearScaleTestId = "FormBuilder-FormFields-LinearScaleField";

const elem = {
  Text: "input",
  Password: "input",
  Checkbox: "input",
  Checkboxes: "input",
  Radio: "input",
  Textarea: "textarea",
  Select: "select",
  Date: "input",
  Content: "div",
  Number: "input",
  Currency: "input",
  DropDown: "select",
  MultipleChoice: "input",
  Typography: "div",
  FileUpload: "input",
  LinearScale: "input",
};

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

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

  it(`Should show the <TextField /> when the type prop is TEXT`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.TEXT} />);
    expect(screen.queryByTestId(textFieldTestId)).toBeTruthy();
  });

  it(`Should show the <DateField /> when the type prop is DATE`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.DATE} />);
    expect(screen.queryByTestId(dateFieldTestId)).toBeTruthy();
  });

  it(`Should show the <NumberField /> input when the type prop is NUMBER`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.NUMBER} />);
    expect(screen.queryByTestId(textFieldTestId)).toBeTruthy();
  });

  it(`Should show the <CurrencyField /> when the type prop is CURRENCY`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.CURRENCY} />);
    expect(screen.queryByTestId(textFieldTestId)).toBeTruthy();
  });

  it(`Should show <DropdownField /> menu when the type prop is DROPDOWN`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.DROPDOWN} />);
    expect(screen.queryByTestId(dropDownTestId)).toBeTruthy();
  });

  it(`Should show a checkbox & label (<Checkboxes /> the when type prop is CHECKBOX`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.CHECKBOXES} />);
    expect(screen.queryByTestId(checkboxesTestId)).toBeTruthy();
  });

  it(`Should show radio input fields (<MultipleChoice /> the when type prop is MULTIPLECHOICE`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.MULTIPLECHOICE} />);
    expect(screen.queryByTestId(multipleChoiceTestId)).toBeTruthy();
  });

  it(`Should show a <ContentField /> the when type prop is TYPOGRAPHY`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.TYPOGRAPHY} />);
    expect(screen.queryByTestId(contentFieldTestId)).toBeTruthy();
  });

  it(`Should show a <FileUpload /> component when the type prop is FILEUPLOAD`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.FILEUPLOAD} />);
    expect(screen.queryByTestId(fileUploadTestId)).toBeTruthy();
  });

  it(`Should show a <TextAreaField /> component when the type prop is TEXTAREA`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.TEXTAREA} />);
    expect(screen.queryByTestId(textAreaTestId)).toBeTruthy();
  });

  it(`Should show a <LinearScale /> component when the type prop is LINEARSCALE`, () => {
    render(<LiveFormField {...props} type={FormFieldTypes.LINEARSCALE} />);
    expect(screen.queryByTestId(linearScaleTestId)).toBeTruthy();
  });

  it(`Should use the "placeholder" property as the placeholder for the form field`, () => {
    const placeholder = "Testing 123";
    const { rerender } = render(<div />);

    // TextField
    rerender(
      <LiveFormField
        {...props}
        placeholder={placeholder}
        type={FormFieldTypes.TEXT}
      />
    );
    expect(
      screen
        .queryByTestId(textFieldTestId)
        .querySelector("input")
        .getAttribute("placeholder")
    ).toBe(placeholder);

    // DropdownField
    rerender(
      <LiveFormField
        {...props}
        placeholder={placeholder}
        type={FormFieldTypes.DROPDOWN}
      />
    );
    expect(
      screen
        .queryByTestId(dropDownTestId)
        .querySelector("select")
        .getAttribute("placeholder")
    ).toBe(placeholder);

    // TextAreaField
    rerender(
      <LiveFormField
        {...props}
        placeholder={placeholder}
        type={FormFieldTypes.TEXTAREA}
      />
    );
    expect(
      screen
        .queryByTestId(textAreaTestId)
        .querySelector("textarea")
        .getAttribute("placeholder")
    ).toBe(placeholder);
  });

  // it(`Should use the "styles" property to determine the style to use for the default form field`, () => {
  //   const { rerender } = render(<div />);
  //   const styles = {
  //     labelStyle: { padding: 5 },
  //     inputStyle: { padding: 5 },
  //     containerStyle: { padding: 5 },
  //     validationStyle: { padding: 5 },
  //     iconStyle: { padding: 5 },
  //   };
  //   for (let type in FormFieldTypes) {
  //     rerender(
  //       <LiveFormField styles={styles} type={FormFieldTypes[type]} />
  //     );
  //     // expect(container.firstChild).toMatchSnapshot();
  //     expect(screen.getByTestId(testId).getAttribute("style")).toContain(
  //       reactToCSS(styles.containerStyle).trim()
  //     );
  //   }
  // });

  it(`Should use the "icon" property to determine the icon to use in this form field`, () => {
    const iconTestId = "WC-ICON-LIVE";
    const { rerender } = render(<div />);
    // TextField
    rerender(
      <LiveFormField
        type={FormFieldTypes.TEXT}
        {...props}
        icon={IconTypes.Email}
      />
    );

    // debug();
    expect(screen.queryByTestId(iconTestId)).toBeTruthy();

    // DateField
    rerender(
      <LiveFormField
        type={FormFieldTypes.DATE}
        {...props}
        icon={IconTypes.Email}
      />
    );
    expect(screen.queryByTestId(iconTestId)).toBeTruthy();

    // DropdownField
    rerender(
      <LiveFormField
        type={FormFieldTypes.DROPDOWN}
        {...props}
        icon={IconTypes.Email}
      />
    );
    expect(screen.queryByTestId(iconTestId)).toBeTruthy();

    // TextAreaField
    rerender(
      <LiveFormField
        type={FormFieldTypes.TEXTAREA}
        {...props}
        icon={IconTypes.Email}
      />
    );
    expect(screen.queryByTestId(iconTestId)).toBeTruthy();
  });

  it(`Should use the "label" property to determine the label to show next to the form field`, () => {
    const { rerender } = render(<div />);
    const label = "Label Content";

    // TextField
    rerender(
      <LiveFormField {...props} type={FormFieldTypes.TEXT} label={label} />
    );
    expect(screen.queryByText(label)).toBeTruthy();

    // Checkboxes
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.CHECKBOXES}
        label={label}
      />
    );
    expect(screen.queryByText(label)).toBeTruthy();

    // DateField
    rerender(
      <LiveFormField {...props} type={FormFieldTypes.DATE} label={label} />
    );
    expect(screen.queryByText(label)).toBeTruthy();

    // DropdownField
    rerender(
      <LiveFormField {...props} type={FormFieldTypes.DROPDOWN} label={label} />
    );
    expect(screen.queryByText(label)).toBeTruthy();

    // FileUpload
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.FILEUPLOAD}
        label={label}
      />
    );
    expect(screen.queryByText(label)).toBeTruthy();

    // LinearScaleField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.LINEARSCALE}
        label={label}
      />
    );
    expect(screen.queryByText(label)).toBeTruthy();

    // MultipleChoiceField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.MULTIPLECHOICE}
        label={label}
      />
    );
    expect(screen.queryByText(label)).toBeTruthy();

    // TextAreaField
    rerender(
      <LiveFormField {...props} type={FormFieldTypes.TEXTAREA} label={label} />
    );
    expect(screen.queryByText(label)).toBeTruthy();
  });

  it(`Should use the "defaultValue" property to determine the value to use for the form field`, () => {
    const { rerender } = render(<div />);
    const defaultValue = "This is the default value";

    const items: IListItem[] = [
      { id: "1", label: "Testing", value: "123" },
      { id: "2", label: defaultValue, value: defaultValue },
      { id: "3", label: "Testing", value: "123" },
    ];

    // TextField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.TEXT}
        defaultValue={defaultValue}
      />
    );
    expect(
      screen
        .getByTestId(textFieldTestId)
        .querySelector(elem[FormFieldTypes.TEXT])
        .getAttribute("value")
    ).toBe(defaultValue);

    // DateField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.DATE}
        defaultValue={defaultValue}
      />
    );
    expect(
      screen
        .getByTestId(dateFieldTestId)
        .querySelector(elem[FormFieldTypes.DATE])
        .getAttribute("value")
    ).toBe(defaultValue);

    // DropdownField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.DROPDOWN}
        defaultValue={defaultValue}
        items={items}
      />
    );
    expect(screen.queryByText(defaultValue)).toBeTruthy();

    // TextAreaField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.TEXTAREA}
        defaultValue={defaultValue}
      />
    );
    expect(screen.queryByText(defaultValue)).toBeTruthy();
  });

  it(`Should use the "description" property to determine the description to show next to the form field`, () => {
    const { rerender } = render(<div />);
    const description = "This is the description test";

    // TextField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.TEXT}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();

    // Checkboxes
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.CHECKBOXES}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();

    // DateField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.DATE}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();

    // DropdownField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.DROPDOWN}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();

    // FileUpload
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.FILEUPLOAD}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();

    // LinearScaleField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.LINEARSCALE}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();

    // MultipleChoice
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.MULTIPLECHOICE}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();

    // TextAreaField
    rerender(
      <LiveFormField
        {...props}
        type={FormFieldTypes.TEXTAREA}
        description={description}
      />
    );
    expect(screen.queryByText(description)).toBeTruthy();
  });

  it(`Should use the "(items)" property to determine the list of items to include in a dropdown menu field`, () => {
    const defaultValue = "This is the default value";
    const items: IListItem[] = [
      { id: "1", label: "Testing", value: "123" },
      { id: "2", label: "Testing", value: defaultValue },
      { id: "3", label: "Testing", value: "123" },
    ];

    render(
      <LiveFormField
        {...props}
        type={FormFieldTypes.DROPDOWN}
        items={items}
        defaultValue={defaultValue}
      />
    );

    expect(
      screen.getByTestId(dropDownTestId).querySelectorAll("option").length
    ).toEqual(items.length);
  });

  test.todo(`Multiple Choice, Radio, LinearScaleField default values`);
});

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

  test.todo(
    `Should trigger the "onChange" property found in the data object when the form field changes`
  );

  test.todo(
    `Should onChange should send back the original payload it received, but mutated)`
  );

  test.todo(
    `Should trigger the "onClick" property found in the data object when a click event occurs with the form field`
  );

  test.todo(
    `Should trigger the "onKeyUp" property found in the data object when a keyUp event occurs with the form field`
  );
});
