import _Popover from "@mui/material/Popover";
import _IconButton from "@mui/material/IconButton";
import _Menu from "@mui/material/Menu";
import _MenuItem from "@mui/material/MenuItem";
import _Typography from "@mui/material/Typography";
/*!
 * Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved.
 * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
 *
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and limitations under the License.
 */

import styled from "@emotion/styled";
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Autocomplete } from "../Autocomplete.js";
import { Box } from "../Box.js";
import { Button } from "../Buttons/Button.js";
import { Checkbox } from "../Fields/Checkbox.js";
import { CheckboxGroup } from "../Fields/CheckboxGroup.js";
import { Radio } from "../Fields/Radio.js";
import { RadioGroup } from "../Fields/RadioGroup.js";
import { Trans, useTranslation } from "../i18n.generated/i18n.js";
import { CheckIcon, ChevronRightIcon, CloseCircleFilledIcon, FilterIcon } from "../icons.generated/index.js";
import { useOdysseyDesignTokens } from "../OdysseyDesignTokensContext.js";
import { SearchField } from "../SearchField.js";
import { Tag } from "../Tag.js";
import { TagList } from "../TagList.js";
import { TextField } from "../TextField.js";
import { Subordinate } from "../Typography.js";
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
const StyledAutocompleteOuterContainer = styled("div", {
  shouldForwardProp: prop => prop !== "odysseyDesignTokens"
})(({
  odysseyDesignTokens
}) => ({
  display: "flex",
  alignItems: "flex-end",
  gap: odysseyDesignTokens.Spacing2
}));
const StyledAutocompleteInnerContainer = styled("div")({
  width: "100%"
});
const FilterTags = ({
  activeFilters,
  updateFilterAndInputValues
}) => {
  const filtersWithValues = activeFilters.filter(activeFilter => activeFilter.value);
  const filtersToRender = [];
  filtersWithValues.forEach(filter => {
    if (Array.isArray(filter.value)) {
      filter.value.forEach(filterValue => {
        const formattedValue = typeof filterValue === "string" ? filterValue : filterValue.value;
        filtersToRender.push({
          id: filter.id,
          label: filter.label,
          value: formattedValue
        });
      });
    }
    if (typeof filter.value === "string") {
      filtersToRender.push({
        id: filter.id,
        label: filter.label,
        value: filter.value
      });
    }
  });
  const getFilter = id => filtersWithValues.find(filter => filter.id === id);
  const removeValueFromFilterAndInput = (id, removedFilterValue) => {
    const currentFilter = getFilter(id);
    if (currentFilter) {
      const {
        value
      } = currentFilter;
      if (Array.isArray(value)) {
        const updatedValues = value.filter(currentValue => {
          return currentValue.value !== removedFilterValue;
        });
        updateFilterAndInputValues({
          filterId: id,
          value: updatedValues.length > 0 ? updatedValues : undefined
        });
      }
      if (typeof value === "string") {
        updateFilterAndInputValues({
          filterId: id,
          value: undefined
        });
      }
    }
  };
  return _jsx(TagList, {
    children: filtersToRender.map(filter => _jsx(Tag, {
      label: `${filter.label}: ${filter.value}`,
      onRemove: () => removeValueFromFilterAndInput(filter.id, filter.value)
    }, `${filter.label}: ${filter.value}`))
  });
};
const MemoizedFilterTags = memo(FilterTags);
MemoizedFilterTags.displayName = "FilterTags";
const DataFilters = ({
  onChangeSearch,
  onChangeFilters,
  hasSearchSubmitButton = false,
  searchDelayTime = 200,
  defaultSearchTerm = "",
  additionalActions,
  filters: filtersProp = [],
  isDisabled
}) => {
  const [filters, setFilters] = useState(filtersProp);
  const {
    t
  } = useTranslation();
  const odysseyDesignTokens = useOdysseyDesignTokens();
  const initialInputValues = useMemo(() => {
    return filtersProp.reduce((accumulator, filter) => {
      accumulator[filter.id] = filter.value;
      return accumulator;
    }, {});
  }, [filtersProp]);
  const [inputValues, setInputValues] = useState(initialInputValues);
  const [searchValue, setSearchValue] = useState(defaultSearchTerm);
  const activeFilters = useMemo(() => {
    return filters.filter(filter => filter.value);
  }, [filters]);
  const [isFiltersMenuOpen, setIsFiltersMenuOpen] = useState(false);
  const [filtersMenuAnchorElement, setFiltersMenuAnchorElement] = useState();
  const [isFilterPopoverOpen, setIsFilterPopoverOpen] = useState(false);
  const [filterPopoverAnchorElement, setFilterPopoverAnchorElement] = useState();
  const [filterPopoverCurrentFilter, setFilterPopoverCurrentFilter] = useState();
  const menuRef = useRef();
  useEffect(() => {
    onChangeFilters?.(filters);
  }, [filters, onChangeFilters]);
  const debouncer = useRef(undefined);
  useEffect(() => {
    if (!hasSearchSubmitButton) {
      if (debouncer.current) {
        clearTimeout(debouncer.current);
      }
      debouncer.current = setTimeout(() => {
        onChangeSearch?.(searchValue ?? "");
      }, searchDelayTime);
    }
  }, [onChangeSearch, searchValue, searchDelayTime, hasSearchSubmitButton]);
  const autocompleteOptions = useMemo(() => {
    return filterPopoverCurrentFilter?.options || [];
  }, [filterPopoverCurrentFilter]);
  const updateInputValue = useCallback(({
    filterId,
    value
  }) => {
    setInputValues({
      ...inputValues,
      [filterId]: value
    });
  }, [inputValues]);
  const updateFilters = useCallback(({
    filterId,
    value
  }) => {
    setInputValues(prevInputValues => ({
      ...prevInputValues,
      [filterId]: value
    }));
    const updatedFilters = filtersProp.map(filter => ({
      ...filter,
      value: filter.id === filterId ? value : inputValues[filter.id]
    }));
    setFilters(updatedFilters);
  }, [inputValues, filtersProp]);
  const updateFilterAndInputValues = useCallback(({
    filterId,
    value
  }) => {
    updateInputValue({
      filterId,
      value
    });
    updateFilters({
      filterId,
      value
    });
  }, [updateFilters, updateInputValue]);
  const handleCheckboxFilterAndInputValueChange = useCallback((filterId, option, checked) => {
    const currentValues = inputValues[filterId] || [];
    const updatedValues = checked ? [...currentValues, option] : currentValues.filter(inputValue => inputValue.value !== option.value);
    const normalizedUpdatedValues = updatedValues.length > 0 ? updatedValues : undefined;
    setInputValues({
      ...inputValues,
      [filterId]: normalizedUpdatedValues
    });
    const updatedFilters = filters.map(filter => ({
      ...filter,
      value: filter.id === filterId ? normalizedUpdatedValues : inputValues[filter.id]
    }));
    setFilters(updatedFilters);
  }, [filters, inputValues]);
  const handleAutocompleteFilterChange = useCallback((filterId, option) => {
    setInputValues({
      ...inputValues,
      [filterId]: option
    });
  }, [inputValues]);
  const clearAllFilters = useCallback(() => {
    const updatedInputValues = filtersProp.reduce((accumulator, filter) => {
      accumulator[filter.id] = undefined;
      return accumulator;
    }, {});
    setInputValues(updatedInputValues);
    const updatedFilters = filtersProp.map(filter => ({
      ...filter,
      value: undefined
    }));
    setFilters(updatedFilters);
  }, [filtersProp]);
  const handleFilterSubmit = useCallback(() => {
    const updatedFilters = filtersProp.map(filter => ({
      ...filter,
      value: inputValues[filter.id]
    }));
    setFilters(updatedFilters);
  }, [inputValues, filtersProp]);
  const filterMenu = useMemo(() => _jsxs(_Fragment, {
    children: [_jsx(Box, {
      children: _jsx(Button, {
        ariaControls: isFiltersMenuOpen ? "filters-menu" : undefined,
        ariaExpanded: isFiltersMenuOpen ? "true" : undefined,
        ariaHasPopup: "true",
        ariaLabel: t("filters.filters.arialabel"),
        endIcon: _jsx(FilterIcon, {}),
        isDisabled: isDisabled,
        onClick: event => {
          setFiltersMenuAnchorElement(event.currentTarget);
          setIsFiltersMenuOpen(true);
        },
        variant: "secondary"
      })
    }), _jsx(_Menu, {
      anchorEl: filtersMenuAnchorElement,
      anchorOrigin: {
        horizontal: "left",
        vertical: "bottom"
      },
      id: "filters-menu",
      onClose: () => setIsFiltersMenuOpen(false),
      open: isFiltersMenuOpen,
      PaperProps: {
        ref: menuRef
      },
      transformOrigin: {
        horizontal: "left",
        vertical: "top"
      },
      children: filtersProp.map(filter => {
        const latestFilterValue = filters.find(f => f.id === filter.id)?.value;
        return _jsx(_MenuItem, {
          "aria-controls": isFilterPopoverOpen ? "filter-form" : undefined,
          className: filterPopoverCurrentFilter === filter && isFilterPopoverOpen === true ? "isVisiblySelected" : undefined,
          onClick: event => {
            setIsFilterPopoverOpen(true);
            setFilterPopoverAnchorElement(event.currentTarget);
            setFilterPopoverCurrentFilter(filter);
          },
          selected: filterPopoverCurrentFilter === filter && isFilterPopoverOpen === true,
          children: _jsxs(Box, {
            sx: {
              display: "flex",
              alignItems: "center",
              justifyContent: "space-between",
              width: "100%",
              minWidth: 180,
              paddingBlock: 1,
              paddingInlineStart: 2
            },
            children: [_jsxs(Box, {
              sx: {
                marginRight: 2
              },
              children: [_jsx(_Typography, {
                fontWeight: "500",
                sx: {
                  marginBlockEnd: 2
                },
                children: filter.label
              }), _jsx(Subordinate, {
                component: "div",
                children: !latestFilterValue || Array.isArray(latestFilterValue) && latestFilterValue.length === 0 ? _jsx(Trans, {
                  i18nKey: "filters.menuitem.any",
                  values: {
                    label: filter.label.toLowerCase()
                  }
                }) : Array.isArray(latestFilterValue) ? _jsx(Trans, {
                  count: latestFilterValue.length,
                  i18nKey: "filters.menuitem.selected",
                  values: {
                    selected: latestFilterValue.length
                  }
                }) : latestFilterValue
              })]
            }), _jsx(ChevronRightIcon, {})]
          })
        }, filter.id);
      })
    })]
  }), [isFiltersMenuOpen, isDisabled, filterPopoverCurrentFilter, isFilterPopoverOpen, filtersMenuAnchorElement, filtersProp, filters, t]);
  const autoCompleteValue = useMemo(() => filterPopoverCurrentFilter?.id ? inputValues[filterPopoverCurrentFilter.id] : undefined, [filterPopoverCurrentFilter, inputValues]);
  return _jsxs(Box, {
    children: [_jsxs(Box, {
      sx: {
        display: "flex",
        justifyContent: "space-between"
      },
      children: [_jsxs(Box, {
        sx: {
          display: "flex",
          gap: 2,
          width: "50%",
          maxWidth: 480
        },
        children: [filters.length > 0 && _jsxs(_Fragment, {
          children: [filterMenu, _jsx(_Popover, {
            anchorEl: filterPopoverAnchorElement,
            anchorOrigin: {
              vertical: "top",
              horizontal: "right"
            },
            elevation: 2,
            id: "filter-form",
            onClose: ev => {
              if (menuRef.current) {
                const menuRect = menuRef.current.getBoundingClientRect();
                const clickInsideMenu = ev.clientX >= menuRect.left && ev.clientX <= menuRect.right && ev.clientY >= menuRect.top && ev.clientY <= menuRect.bottom;
                if (!clickInsideMenu) {
                  setIsFiltersMenuOpen(false);
                }
              }
              handleFilterSubmit();
              setIsFilterPopoverOpen(false);
            },
            open: isFilterPopoverOpen,
            sx: {
              marginLeft: 2,
              marginTop: -1
            },
            children: _jsx(Box, {
              sx: {
                padding: 4,
                minWidth: 320
              },
              children: _jsx("form", {
                noValidate: true,
                onSubmit: ev => {
                  ev.preventDefault();
                  handleFilterSubmit();
                  setIsFilterPopoverOpen(false);
                  setIsFiltersMenuOpen(false);
                },
                children: filterPopoverCurrentFilter?.render ? filterPopoverCurrentFilter.render(updateFilters) : _jsxs(_Fragment, {
                  children: [filterPopoverCurrentFilter?.variant === "autocomplete" && filterPopoverCurrentFilter?.options && _jsxs(StyledAutocompleteOuterContainer, {
                    odysseyDesignTokens: odysseyDesignTokens,
                    children: [_jsx(StyledAutocompleteInnerContainer, {
                      children: _jsx(Autocomplete, {
                        hasMultipleChoices: true,
                        isCustomValueAllowed: filterPopoverCurrentFilter?.isCustomValueAllowed,
                        label: filterPopoverCurrentFilter.label,
                        onChange: (_, value) => {
                          handleAutocompleteFilterChange(filterPopoverCurrentFilter.id, value);
                        },
                        options: autocompleteOptions,
                        value: autoCompleteValue
                      })
                    }), _jsx(Button, {
                      ariaLabel: t("filters.submit.label"),
                      endIcon: _jsx(CheckIcon, {}),
                      type: "submit",
                      variant: "primary"
                    })]
                  }), (filterPopoverCurrentFilter?.variant === "text" || filterPopoverCurrentFilter?.variant === "range" || filterPopoverCurrentFilter && filterPopoverCurrentFilter?.variant == undefined) && _jsxs(Box, {
                    sx: {
                      display: "flex",
                      gap: 2,
                      alignItems: "flex-end"
                    },
                    children: [_jsx(Box, {
                      sx: {
                        width: "100%"
                      },
                      children: _jsx(TextField, {
                        endAdornment: inputValues[filterPopoverCurrentFilter.id] && _jsx(_IconButton, {
                          "aria-label": t("filters.filter.clear"),
                          onClick: () => {
                            updateInputValue({
                              filterId: filterPopoverCurrentFilter.id,
                              value: undefined
                            });
                            updateFilters({
                              filterId: filterPopoverCurrentFilter.id,
                              value: undefined
                            });
                          },
                          size: "small",
                          children: _jsx(CloseCircleFilledIcon, {})
                        }),
                        hasInitialFocus: true,
                        label: filterPopoverCurrentFilter.label,
                        onChange: ev => updateInputValue({
                          filterId: filterPopoverCurrentFilter.id,
                          value: ev.currentTarget.value
                        }),
                        type: filterPopoverCurrentFilter.variant === "range" ? "number" : "text",
                        value: inputValues[filterPopoverCurrentFilter.id] ?? ""
                      })
                    }), _jsx(Button, {
                      ariaLabel: t("filters.submit.label"),
                      endIcon: _jsx(CheckIcon, {}),
                      type: "submit",
                      variant: "primary"
                    })]
                  }), filterPopoverCurrentFilter?.variant === "multi-select" && filterPopoverCurrentFilter?.options && _jsx(CheckboxGroup, {
                    isRequired: true,
                    label: filterPopoverCurrentFilter.label,
                    children: filterPopoverCurrentFilter.options.map(option => {
                      const checkFilterInputValuesAsArray = inputValues[filterPopoverCurrentFilter.id] || [];
                      const isOptionValueInInputValues = checkFilterInputValuesAsArray.some(inputValue => inputValue.value === option.value);
                      return _jsx(Checkbox, {
                        isChecked: isOptionValueInInputValues,
                        label: option.label,
                        onChange: (_, checked) => {
                          handleCheckboxFilterAndInputValueChange(filterPopoverCurrentFilter.id, option, checked);
                        },
                        value: option.value
                      }, option.value);
                    })
                  }), filterPopoverCurrentFilter?.variant === "select" && filterPopoverCurrentFilter?.options && _jsxs(RadioGroup, {
                    label: filterPopoverCurrentFilter.label,
                    onChange: (_, value) => {
                      updateFilterAndInputValues({
                        filterId: filterPopoverCurrentFilter.id,
                        value
                      });
                    },
                    children: [_jsx(Radio, {
                      isChecked: !inputValues[filterPopoverCurrentFilter.id],
                      label: t("filters.filter.any"),
                      value: ""
                    }), _jsx(_Fragment, {
                      children: filterPopoverCurrentFilter.options.map(option => _jsx(Radio, {
                        isChecked: inputValues[filterPopoverCurrentFilter.id] === option.value,
                        label: option.label,
                        value: option.value
                      }, option.value))
                    })]
                  })]
                })
              })
            })
          })]
        }), onChangeSearch && _jsx("form", {
          onSubmit: event => {
            event.preventDefault();
            if (hasSearchSubmitButton) {
              onChangeSearch(searchValue);
            }
          },
          style: {
            width: "100%"
          },
          children: _jsxs(Box, {
            sx: {
              display: "flex",
              gap: 2,
              width: "100%"
            },
            children: [_jsx(SearchField, {
              isDisabled: isDisabled,
              label: t("filters.search.label"),
              onChange: ev => setSearchValue(ev.target.value),
              onClear: () => {
                setSearchValue("");
                onChangeSearch("");
              },
              placeholder: t("filters.search.label"),
              value: searchValue
            }), hasSearchSubmitButton && _jsx(Box, {
              children: _jsx(Button, {
                isDisabled: isDisabled,
                label: t("filters.search.label"),
                onClick: () => onChangeSearch(searchValue),
                variant: "primary"
              })
            })]
          })
        })]
      }), _jsxs(Box, {
        sx: {
          display: "flex",
          gap: 2
        },
        children: [activeFilters.length > 0 && _jsx(Box, {
          children: _jsx(Button, {
            label: t("filters.clear.label"),
            onClick: clearAllFilters,
            variant: "secondary"
          })
        }), additionalActions]
      })]
    }), activeFilters.length > 0 && _jsx(Box, {
      sx: {
        borderTopWidth: 1,
        borderTopColor: "#eeeeee",
        borderTopStyle: "solid",
        paddingTop: 4,
        marginTop: 4
      },
      children: _jsx(MemoizedFilterTags, {
        activeFilters: activeFilters,
        updateFilterAndInputValues: updateFilterAndInputValues
      })
    })]
  });
};
const MemoizedDataFilters = memo(DataFilters);
MemoizedDataFilters.displayName = "DataFilters";
export { MemoizedDataFilters as DataFilters };
//# sourceMappingURL=DataFilters.js.map