import { jsx, jsxs } from 'react/jsx-runtime';
import { cx, css } from '@emotion/css';
import { flip, shift, useFloating, autoUpdate } from '@floating-ui/react';
import { useDialog } from '@react-aria/dialog';
import { FocusScope } from '@react-aria/focus';
import { useOverlay } from '@react-aria/overlays';
import * as React from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';
import Calendar from 'react-calendar';
import { useMedia } from 'react-use';
import { dateTimeFormat, dateTime, isDateTime, dateTimeForTimeZone, getTimeZone } from '@grafana/data';
import { Components } from '@grafana/e2e-selectors';
import { useStyles2, useTheme2 } from '../../../themes/ThemeContext.js';
import 'micro-memoize';
import '@emotion/react';
import 'tinycolor2';
import '../../../utils/skeleton.js';
import { Button } from '../../Button/Button.js';
import { InlineField } from '../../Forms/InlineField.js';
import { Icon } from '../../Icon/Icon.js';
import { Input } from '../../Input/Input.js';
import { Stack } from '../../Layout/Stack/Stack.js';
import { getModalStyles } from '../../Modal/getModalStyles.js';
import { Portal } from '../../Portal/Portal.js';
import { TimeOfDayPicker, POPUP_CLASS_NAME } from '../TimeOfDayPicker.js';
import { getBodyStyles } from '../TimeRangePicker/CalendarBody.js';
import { isValid } from '../utils.js';
import { adjustDateForReactCalendar } from '../utils/adjustDateForReactCalendar.js';

const DateTimePicker = ({
  date,
  maxDate,
  minDate,
  label,
  onChange,
  disabledHours,
  disabledMinutes,
  disabledSeconds,
  timeZone,
  showSeconds = true,
  clearable = false
}) => {
  const [isOpen, setOpen] = useState(false);
  const ref = useRef(null);
  const { overlayProps, underlayProps } = useOverlay(
    {
      onClose: () => setOpen(false),
      isDismissable: true,
      isOpen,
      shouldCloseOnInteractOutside: (element) => {
        const popupElement = document.getElementsByClassName(POPUP_CLASS_NAME)[0];
        return !(popupElement && popupElement.contains(element));
      }
    },
    ref
  );
  const { dialogProps } = useDialog({}, ref);
  const theme = useTheme2();
  const { modalBackdrop } = useStyles2(getModalStyles);
  const isFullscreen = useMedia(`(min-width: ${theme.breakpoints.values.lg}px)`);
  const styles = useStyles2(getStyles);
  const middleware = [
    flip({
      // see https://floating-ui.com/docs/flip#combining-with-shift
      crossAxis: false,
      boundary: document.body
    }),
    shift()
  ];
  const { refs, floatingStyles } = useFloating({
    open: isOpen,
    placement: "bottom-start",
    onOpenChange: setOpen,
    middleware,
    whileElementsMounted: autoUpdate,
    strategy: "fixed"
  });
  const onApply = useCallback(
    (date2) => {
      setOpen(false);
      onChange(date2);
    },
    [onChange]
  );
  const onOpen = useCallback(
    (event) => {
      event.preventDefault();
      setOpen(true);
    },
    [setOpen]
  );
  return /* @__PURE__ */ jsxs("div", { "data-testid": "date-time-picker", style: { position: "relative" }, children: [
    /* @__PURE__ */ jsx(
      DateTimeInput,
      {
        date,
        onChange,
        isFullscreen,
        onOpen,
        label,
        ref: refs.setReference,
        showSeconds,
        clearable,
        timeZone
      }
    ),
    isOpen ? isFullscreen ? /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(FocusScope, { contain: true, autoFocus: true, restoreFocus: true, children: /* @__PURE__ */ jsx("div", { ref, ...overlayProps, ...dialogProps, children: /* @__PURE__ */ jsx(
      DateTimeCalendar,
      {
        date,
        onChange: onApply,
        isFullscreen: true,
        onClose: () => setOpen(false),
        maxDate,
        minDate,
        ref: refs.setFloating,
        style: floatingStyles,
        showSeconds,
        disabledHours,
        disabledMinutes,
        disabledSeconds,
        timeZone
      }
    ) }) }) }) : /* @__PURE__ */ jsxs(Portal, { children: [
      /* @__PURE__ */ jsx("div", { className: modalBackdrop, ...underlayProps }),
      /* @__PURE__ */ jsx(FocusScope, { contain: true, autoFocus: true, restoreFocus: true, children: /* @__PURE__ */ jsx("div", { ref, ...overlayProps, ...dialogProps, children: /* @__PURE__ */ jsx("div", { className: styles.modal, children: /* @__PURE__ */ jsx(
        DateTimeCalendar,
        {
          date,
          maxDate,
          minDate,
          onChange: onApply,
          isFullscreen: false,
          onClose: () => setOpen(false),
          showSeconds,
          disabledHours,
          disabledMinutes,
          disabledSeconds,
          timeZone
        }
      ) }) }) })
    ] }) : null
  ] });
};
const DateTimeInput = React.forwardRef(
  ({ date, label, onChange, onOpen, timeZone, showSeconds = true, clearable = false }, ref) => {
    const styles = useStyles2(getStyles);
    const format = showSeconds ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD HH:mm";
    const [internalDate, setInternalDate] = useState(() => {
      return {
        value: date ? dateTimeFormat(date, { timeZone }) : !clearable ? dateTimeFormat(dateTime(), { timeZone }) : "",
        invalid: false
      };
    });
    useEffect(() => {
      if (date) {
        const formattedDate = dateTimeFormat(date, { format, timeZone });
        setInternalDate({
          invalid: !isValid(formattedDate),
          value: isDateTime(date) ? formattedDate : date
        });
      }
    }, [date, format, timeZone]);
    const onChangeDate = useCallback((event) => {
      const isInvalid = !isValid(event.currentTarget.value);
      setInternalDate({
        value: event.currentTarget.value,
        invalid: isInvalid
      });
    }, []);
    const onBlur = useCallback(() => {
      if (!internalDate.invalid && internalDate.value) {
        const date2 = dateTimeForTimeZone(getTimeZone({ timeZone }), internalDate.value);
        onChange(date2);
      }
    }, [internalDate, onChange, timeZone]);
    const clearInternalDate = useCallback(() => {
      setInternalDate({ value: "", invalid: false });
      onChange();
    }, [onChange]);
    const icon = /* @__PURE__ */ jsx(Button, { "aria-label": "Time picker", icon: "calendar-alt", variant: "secondary", onClick: onOpen });
    return /* @__PURE__ */ jsx(InlineField, { label, invalid: !!(internalDate.value && internalDate.invalid), className: styles.field, children: /* @__PURE__ */ jsx(
      Input,
      {
        onChange: onChangeDate,
        addonAfter: icon,
        value: internalDate.value,
        onBlur,
        "data-testid": Components.DateTimePicker.input,
        placeholder: "Select date/time",
        ref,
        suffix: clearable && internalDate.value && /* @__PURE__ */ jsx(Icon, { name: "times", className: styles.clearIcon, onClick: clearInternalDate })
      }
    ) });
  }
);
DateTimeInput.displayName = "DateTimeInput";
const DateTimeCalendar = React.forwardRef(
  ({
    date,
    onClose,
    onChange,
    isFullscreen,
    maxDate,
    minDate,
    style,
    showSeconds = true,
    disabledHours,
    disabledMinutes,
    disabledSeconds,
    timeZone
  }, ref) => {
    const calendarStyles = useStyles2(getBodyStyles);
    const styles = useStyles2(getStyles);
    const [timeOfDayDateTime, setTimeOfDayDateTime] = useState(() => {
      if (date && date.isValid()) {
        return dateTimeForTimeZone(getTimeZone({ timeZone }), date);
      }
      return dateTimeForTimeZone(getTimeZone({ timeZone }), /* @__PURE__ */ new Date());
    });
    const [reactCalendarDate, setReactCalendarDate] = useState(() => {
      if (date && date.isValid()) {
        return adjustDateForReactCalendar(date.toDate(), getTimeZone({ timeZone }));
      }
      return adjustDateForReactCalendar(/* @__PURE__ */ new Date(), getTimeZone({ timeZone }));
    });
    const onChangeDate = useCallback((date2) => {
      if (date2 && !Array.isArray(date2)) {
        setReactCalendarDate(date2);
      }
    }, []);
    const onChangeTime = useCallback((date2) => {
      setTimeOfDayDateTime(date2);
    }, []);
    const handleApply = () => {
      const newDate = dateTime(timeOfDayDateTime);
      newDate.set("date", reactCalendarDate.getDate());
      newDate.set("month", reactCalendarDate.getMonth());
      newDate.set("year", reactCalendarDate.getFullYear());
      onChange(newDate);
    };
    return /* @__PURE__ */ jsxs("div", { className: cx(styles.container, { [styles.fullScreen]: isFullscreen }), style, ref, children: [
      /* @__PURE__ */ jsx(
        Calendar,
        {
          next2Label: null,
          prev2Label: null,
          value: reactCalendarDate,
          nextLabel: /* @__PURE__ */ jsx(Icon, { name: "angle-right" }),
          nextAriaLabel: "Next month",
          prevLabel: /* @__PURE__ */ jsx(Icon, { name: "angle-left" }),
          prevAriaLabel: "Previous month",
          onChange: onChangeDate,
          locale: "en",
          className: calendarStyles.body,
          tileClassName: calendarStyles.title,
          maxDate,
          minDate
        }
      ),
      /* @__PURE__ */ jsx("div", { className: styles.time, children: /* @__PURE__ */ jsx(
        TimeOfDayPicker,
        {
          showSeconds,
          onChange: onChangeTime,
          value: timeOfDayDateTime,
          disabledHours,
          disabledMinutes,
          disabledSeconds
        }
      ) }),
      /* @__PURE__ */ jsxs(Stack, { children: [
        /* @__PURE__ */ jsx(Button, { type: "button", onClick: handleApply, children: "Apply" }),
        /* @__PURE__ */ jsx(Button, { variant: "secondary", type: "button", onClick: onClose, children: "Cancel" })
      ] })
    ] });
  }
);
DateTimeCalendar.displayName = "DateTimeCalendar";
const getStyles = (theme) => ({
  container: css({
    padding: theme.spacing(1),
    border: `1px ${theme.colors.border.weak} solid`,
    borderRadius: theme.shape.radius.default,
    backgroundColor: theme.colors.background.primary,
    zIndex: theme.zIndex.modal
  }),
  fullScreen: css({
    position: "absolute"
  }),
  time: css({
    marginBottom: theme.spacing(2)
  }),
  modal: css({
    position: "fixed",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    zIndex: theme.zIndex.modal,
    maxWidth: "280px"
  }),
  clearIcon: css({
    cursor: "pointer"
  }),
  field: css({
    marginBottom: 0,
    width: "100%"
  })
});

export { DateTimePicker };
//# sourceMappingURL=DateTimePicker.js.map
