import type { Decorator, Meta, StoryObj } from "@storybook/react";

import {
  ThemeProviderWithStyledEngine,
  DatePicker,
  Button,
  DateField,
  Calendar,
} from "../index";
import {
  type ComponentProps,
  type FocusEventHandler,
  type MutableRefObject,
  useCallback,
  useRef,
  useState,
} from "react";
import { Popper } from "@mui/material";

const disabled = {
  table: {
    disable: true,
  },
};

const decorator: Decorator<unknown> = (Story) => (
  <ThemeProviderWithStyledEngine>{Story()}</ThemeProviderWithStyledEngine>
);

const meta = {
  title: "Components/Inputs/DatePicker",
  component: DatePicker,
  argTypes: {
    label: { type: "string" },
    defaultValue: { type: "string" },
    locale: {
      type: "string",
      options: ["en", "nl", "de"],
      control: {
        type: "select",
      },
    },
    tooltip: { type: "string" },
    value: disabled,
    onChange: disabled,
    onClear: disabled,
    ESCAPE_className: disabled,
    ESCAPE_popoverProps: disabled,
    renderPicker: disabled,
    renderPopover: disabled,
    tooltipProps: disabled,
    autoFocusCalendar: disabled,
  },
  decorators: [decorator],
} satisfies Meta<ComponentProps<typeof DatePicker>>;

export default meta;
type Story = StoryObj<ComponentProps<typeof DatePicker>>;

export const Default: Story = {
  args: {
    locale: "nl",
    variant: "outlined",
    fullWidth: true,
    label: "Birthday",
    required: false,
    error: false,
    errorText: "It's wrong",
    disabled: false,
    height: "40",
    min: "2023-10-01",
    max: "2033-10-01",
    clearButton: true,
  },
};

export const ButtonOnly: Story = {
  render: ({ label, disabled, ...args }) => (
    <div className="flex justify-center py-20">
      <DatePicker
        {...args}
        disabled={disabled}
        aria-label={label as string}
        ESCAPE_popoverProps={{
          anchorOrigin: { vertical: "bottom", horizontal: "center" },
          transformOrigin: {
            horizontal: "center",
            vertical: -8,
          },
        }}
        renderPicker={({ buttonProps }, ref) => (
          <Button
            {...buttonProps}
            disabled={disabled}
            tooltip={label as string}
            ref={ref as MutableRefObject<HTMLButtonElement>}
            icon="calendar"
          />
        )}
      />
    </div>
  ),
  args: {
    locale: "nl",
    label: "Birthday",
    disabled: false,
    min: "2023-10-01",
    max: "2033-10-01",
  },
};

function useFocusBoundOpen() {
  const [isOpen, setIsOpen] = useState(false);
  const focusBoundaryRef = useRef<HTMLSpanElement>(null);
  const popoverRef = useRef<HTMLDivElement>(null);

  const handleFocus = useCallback<FocusEventHandler>((event) => {
    if (!focusBoundaryRef.current?.contains(event.relatedTarget)) {
      setIsOpen(true);
    }
  }, []);

  const handleBlur = useCallback<FocusEventHandler>((event) => {
    if (
      !focusBoundaryRef.current?.contains(event.relatedTarget) &&
      !popoverRef.current?.contains(event.relatedTarget)
    ) {
      setIsOpen(false);
    }
  }, []);

  return {
    boundaryProps: {
      ref: focusBoundaryRef,
      onFocus: handleFocus,
      onBlur: handleBlur,
    },
    popoverRef,
    isOpen,
    setIsOpen,
  };
}

const NonModalDatePicker = (props: ComponentProps<typeof DatePicker>) => {
  const { boundaryProps, popoverRef, isOpen, setIsOpen } = useFocusBoundOpen();

  return (
    <span {...boundaryProps}>
      <DatePicker
        {...props}
        isOpen={isOpen}
        autoFocusCalendar={false}
        renderPicker={({ fieldProps, labelProps, groupProps }, ref) => (
          <div className="flex items-center gap-8" {...groupProps}>
            <strong {...labelProps}>First time you tried Snickers:</strong>
            <div ref={ref as MutableRefObject<HTMLDivElement>}>
              <DateField {...fieldProps} />
            </div>
          </div>
        )}
        renderPopover={({ calendarProps, dialogProps }, ref, state) => (
          <Popper
            placement="bottom"
            popperOptions={{
              modifiers: [{ name: "offset", options: { offset: [0, 8] } }],
            }}
            open={state.isOpen}
            anchorEl={ref.current}
            keepMounted
            ref={popoverRef}
          >
            <div
              className="rounded-12 bg-N0 p-16 text-N700 shadow-S300"
              {...dialogProps}
            >
              <Calendar
                {...calendarProps}
                onChange={(value) => {
                  setIsOpen(false);
                  calendarProps.onChange?.(value);
                }}
              />
            </div>
          </Popper>
        )}
      />
    </span>
  );
};

export const NonModalGhost: Story = {
  ...ButtonOnly,
  render: ({ label, ...args }) => (
    <NonModalDatePicker
      {...args}
      aria-label={label as string}
      onChange={(e) => console.log(e)}
    />
  ),
};
