import "./HtmlSelect";

import { Meta, StoryObj } from "@storybook/react-vite";
import { expect, fn, userEvent, within } from "storybook/test";

import { iconClass } from "../../../../utils/iconClass";
import { useValue } from "../../../__fixtures__/useValue.hook";
import { Select } from "../Select";

const options = [
  {
    label: "Option 1",
    value: "option-1"
  },
  {
    label: "Option 2",
    value: "option-2"
  },
  {
    label: "Option 3",
    value: "option-3"
  }
];
/**
 * HTML5 select component.
 *
 * ```tsx
 * import {Select} from "@tsed/react-formio/molecules/forms/select/all"; // import HTML5, ChoicesJS and React components
 *
 * // or
 * import {Select} from "@tsed/react-formio/molecules/forms/select/Select";
 * import "@tsed/react-formio/molecules/forms/select/components/HtmlSelect"; // register only HTML5 component
 *
 * ```
 */
export default {
  title: "forms/Select/Html5",
  component: Select,
  parameters: {
    layout: "centered",
    backgrounds: { default: "pearl" }
  },
  args: {},
  argTypes: {
    label: {
      control: "text"
    },
    name: {
      control: "text"
    },
    value: {
      control: "select",
      options: ["option-1", "option-2", "option-3"]
    },
    size: {
      control: "radio",
      options: ["small", "normal"]
    },
    placeholder: {
      control: "text"
    },
    options: {
      control: "object"
    },
    onChange: {
      action: "onChange"
    }
  },
  tags: ["autodocs"],
  render(args) {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    const { value, onChange } = useValue(args);

    return (
      <div style={{ width: "300px" }}>
        <Select {...args} value={value} onChange={onChange} />
      </div>
    );
  }
} satisfies Meta<typeof Select>;

type Story = StoryObj<typeof Select<string>>;
/**
 * Basic select component using HTML5 syntax.
 */
export const Usage: Story = {
  args: {
    name: "name",
    label: "Label",
    value: "option-1",
    options,
    onChange: fn()
  },
  play: async ({ canvasElement, args }) => {
    const canvas = within(canvasElement);

    const select = canvas.getByTestId("select_name");

    await expect(select).toBeInTheDocument();
    await expect(select).toHaveValue("option-1");

    await userEvent.selectOptions(select, "option-2");

    await expect(select).toHaveValue("option-2");
    await expect(args.onChange).toHaveBeenCalledWith("name", "option-2");

    const label = canvas.getByTestId("form-group-name");

    await expect(label).toBeInTheDocument();
    await expect(label).toHaveTextContent("Label");
  }
};

/**
 * Select component with a placeholder.
 */
export const WithPlaceholder: Story = {
  args: {
    name: "name",
    placeholder: "Select an option",
    options,
    onChange: fn()
  },
  play: async ({ canvasElement, args }) => {
    const canvas = within(canvasElement);

    const select = canvas.getByTestId("select_name");

    await expect(select).toBeInTheDocument();
    await expect(select).toHaveValue("");

    await userEvent.selectOptions(select, "option-2");

    await expect(select).toHaveValue("option-2");
    await expect(args.onChange).toHaveBeenCalledWith("name", "option-2");
  }
};
/**
 * Select component with a disabled prop.
 */
export const WithDisabledProp: Story = {
  args: {
    disabled: true,
    options
  }
};

/**
 * Select component with a disabled option.
 */
export const WithDisabledOption: Story = {
  args: {
    options: [
      {
        label: "Option 1",
        value: "option-1"
      },
      {
        label: "Option 2",
        value: "option-2",
        disabled: true
      },
      {
        label: "Option 3",
        value: "option-3"
      }
    ]
  }
};

export const WithSizeOption: Story = {
  args: {
    size: "small",
    options: [
      {
        label: "Option 1",
        value: "option-1"
      },
      {
        label: "Option 2",
        value: "option-2",
        disabled: true
      },
      {
        label: "Option 3",
        value: "option-3"
      }
    ]
  }
};

export const AppendBefore: Story = {
  args: {
    before: <i className={iconClass(undefined, "calendar")} />,
    label: "Label",
    value: "",
    size: "",
    placeholder: "Placeholder",
    options
  }
};

export const AppendAfter: Story = {
  args: {
    after: <i className={iconClass(undefined, "calendar")} />,
    label: "Label",
    value: "",
    size: "",
    placeholder: "Placeholder",
    options
  }
};

export const WithDescription: Story = {
  args: {
    label: "Label",
    name: "name",
    value: "",
    placeholder: "Placeholder",
    description: "Select multiple values",
    options
  }
};

export const WithGroups: Story = {
  args: {
    label: "Label",
    name: "name",
    value: [],
    size: "",
    description: "Select multiple values",
    options: [
      {
        label: "Group 1",
        group: "group-1",
        value: "option-1"
      },
      {
        group: "group-1",
        label: "Option 2",
        value: "option-2"
      },
      {
        label: "Group 2",
        group: "group-2",
        value: "option-3"
      },
      {
        group: "group-2",
        label: "Option 4",
        value: "option-4"
      }
    ]
  }
};

export const WithMultiple: Story = {
  args: {
    label: "Label",
    name: "name",
    value: [],
    size: "",
    multiple: true,
    placeholder: "Placeholder",
    description: "Select multiple values",
    options
  }
};

export const WithGroupsAndMultiple: Story = {
  args: {
    label: "Label",
    name: "name",
    value: [],
    size: "",
    multiple: true,
    description: "Select multiple values",
    options: [
      {
        label: "Group 1",
        group: "group-1",
        value: "option-1"
      },
      {
        group: "group-1",
        label: "Option 2",
        value: "option-2"
      },
      {
        label: "Group 2",
        group: "group-2",
        value: "option-3"
      },
      {
        group: "group-2",
        label: "Option 4",
        value: "option-4"
      }
    ]
  }
};
