import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import { useTheme, Box, CircularProgress, IconButton, MenuItem, Select, Chip, FormHelperText, TextField } from '@mui/material';
import { keyframes } from '@emotion/react';
import CloseIcon from '@mui/icons-material/Close';
import DoneIcon from '@mui/icons-material/Done';
import Required from './required';
import FormWrapper from './form-wrapper';
import InputTriggers from './input-triggers';
/**
 * 抖动动画
 */
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
const shakeKeyframes = keyframes`
  0%, 100% {
    transform: scale(1) translateX(0);
  }
  50% {
    transform: scale(1.05) translateX(-3px);
  }
  25%, 75% {
    transform: scale(1.1) translateX(3px);
  }
`;
function LogoImage({
  src,
  alt,
  size = 20
}) {
  return /*#__PURE__*/_jsx("img", {
    src: src,
    alt: alt,
    style: {
      width: size,
      height: size,
      display: 'block',
      objectFit: 'contain',
      borderRadius: '2px',
      flexShrink: 0
    },
    onError: e => {
      e.target.style.display = 'none';
    }
  });
}
LogoImage.propTypes = {
  src: PropTypes.string.isRequired,
  alt: PropTypes.string.isRequired,
  size: PropTypes.number
};
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      width: 250
    }
  }
};
const getStyles = (current, selected, theme) => {
  return {
    fontWeight: selected.indexOf(current) === -1 ? theme.typography.fontWeightRegular : theme.typography.fontWeightMedium
  };
};
export default function FormSelectInput({
  label = '',
  disabled = false,
  required = false,
  initialValue = '',
  onChange = () => {},
  sx = {},
  onSubmit = () => {},
  triggers = [],
  options = [],
  formatterBeforeSubmit = x => x.join(','),
  helperText = '',
  config = {},
  directEditing = false,
  searchable = true,
  ...rest
}) {
  const theme = useTheme();
  const [editing, setEditing] = useState(directEditing);
  const [loading, setLoading] = useState(false);
  const [filterText, setFilterText] = useState('');
  const {
    multiple = false,
    labelField = 'name',
    valueField = 'code'
  } = config;
  const [defaultValue, setDefaultValue] = useState(initialValue);
  const [value, setValue] = useState(defaultValue);
  const [isEdited, setIsEdited] = useState(false);
  const [isShaking, setIsShaking] = useState(false);
  const handleShake = useCallback(() => {
    // 触发按钮的抖动动画，持续 500 毫秒
    setIsShaking(true);

    // 在 500 毫秒后移除抖动动画
    setTimeout(() => {
      setIsShaking(false);
    }, 500);
  }, []);
  const handleSubmit = async () => {
    setLoading(true);
    try {
      const shouldUpdate = await onSubmit(typeof formatterBeforeSubmit === 'function' && multiple ? formatterBeforeSubmit(value) : value);
      if (shouldUpdate === false) {
        setValue(defaultValue);
      } else {
        setValue(value);
        setDefaultValue(value);
        setIsEdited(false);
      }
    } catch (err) {
      setValue(defaultValue);
    } finally {
      setLoading(false);
      setEditing(false);
    }
  };
  const onFocusOut = useCallback(() => {
    if (directEditing && !disabled && !loading) {
      handleSubmit();
    }
    if (isEdited) {
      handleShake();
    }
    if (!isEdited && !disabled && !loading) {
      setEditing(false);
      setIsEdited(false);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [directEditing, disabled, loading, isEdited, handleShake]);
  useEffect(() => {
    const newDefaultValue = initialValue;
    if (newDefaultValue !== defaultValue) {
      setDefaultValue(newDefaultValue);
      setValue(newDefaultValue);
      setIsEdited(false);
    }
  }, [initialValue, defaultValue]);

  // 筛选选项
  const filteredOptions = options.filter(option => {
    if (!filterText) return true;
    const searchText = filterText.toLowerCase();
    return option[labelField]?.toLowerCase().includes(searchText) || option[valueField]?.toLowerCase().includes(searchText);
  });
  const onInputChange = e => {
    let {
      value: selected
    } = e.target;
    if (multiple) {
      selected = typeof selected === 'string' ? selected.split(',') : selected;
    }
    setIsEdited(selected !== value);
    setValue(selected);
    onChange(selected);
  };
  const input = editing || directEditing ? /*#__PURE__*/_jsxs(Select, {
    value: value,
    onChange: onInputChange,
    fullWidth: true,
    multiple: multiple,
    variant: "outlined",
    margin: "dense",
    onBlur: onFocusOut,
    disabled: disabled,
    renderValue: selected => {
      if (multiple) {
        return /*#__PURE__*/_jsx(Box, {
          sx: {
            display: 'flex',
            flexWrap: 'wrap'
          },
          children: selected.filter(x => options.some(o => o[valueField] === x)).map(x => /*#__PURE__*/_jsx(Chip, {
            label: options.find(o => o[valueField] === x)[labelField],
            style: {
              marginRight: 8
            },
            size: "small"
          }, x))
        });
      }
      if (!selected) {
        return null;
      }
      const option = options.find(o => o[valueField] === selected);
      return /*#__PURE__*/_jsxs(Box, {
        sx: {
          display: 'flex',
          alignItems: 'center',
          gap: 1
        },
        children: [option?.logo && /*#__PURE__*/_jsx(LogoImage, {
          src: option.logo,
          alt: option[labelField],
          size: 20
        }), /*#__PURE__*/_jsx("span", {
          children: option ? option[labelField] : ''
        })]
      });
    },
    MenuProps: {
      ...MenuProps,
      PaperProps: {
        ...MenuProps.PaperProps
      }
    },
    error: !!helperText,
    ...rest,
    children: [searchable ? /*#__PURE__*/_jsx(Box, {
      sx: {
        p: 1,
        borderBottom: 1,
        borderColor: 'divider'
      },
      children: /*#__PURE__*/_jsx(TextField, {
        size: "small",
        placeholder: "Search...",
        value: filterText,
        onChange: e => setFilterText(e.target.value),
        onClick: e => e.stopPropagation(),
        onKeyDown: e => e.stopPropagation(),
        fullWidth: true,
        variant: "outlined"
      })
    }) : null, filteredOptions.map(x => /*#__PURE__*/_jsx(MenuItem, {
      value: x[valueField],
      style: getStyles(x[valueField], value, theme),
      children: /*#__PURE__*/_jsxs(Box, {
        sx: {
          display: 'flex',
          alignItems: 'center',
          gap: 1
        },
        children: [x.logo && /*#__PURE__*/_jsx(LogoImage, {
          src: x.logo,
          alt: x[labelField],
          size: 20
        }), /*#__PURE__*/_jsx("span", {
          children: x[labelField]
        })]
      })
    }, x[valueField]))]
  }) : /*#__PURE__*/_jsx(Box, {
    "data-cy": "schema-form-item-edit",
    className: "form-item-input slot",
    style: {
      whiteSpace: 'pre-wrap'
    },
    sx: {
      px: 1
    },
    onClick: () => {
      if (!disabled) {
        setEditing(true);
      }
    },
    children: multiple ? value.filter(x => options.some(o => o[valueField] === x)).map(x => /*#__PURE__*/_jsx(Chip, {
      label: options.find(o => o[valueField] === x)[labelField],
      style: {
        marginRight: 8
      },
      size: "small"
    }, x)) : value && options.some(o => o[valueField] === value) && /*#__PURE__*/_jsxs(Box, {
      sx: {
        display: 'flex',
        alignItems: 'center',
        gap: 1
      },
      children: [(() => {
        const option = options.find(o => o[valueField] === value);
        return option?.logo ? /*#__PURE__*/_jsx(LogoImage, {
          src: option.logo,
          alt: option[labelField],
          size: 20
        }) : null;
      })(), /*#__PURE__*/_jsx("span", {
        children: options.find(o => o[valueField] === value)[labelField]
      })]
    })
  });
  return /*#__PURE__*/_jsx(FormWrapper, {
    className: "form",
    sx: sx,
    children: /*#__PURE__*/_jsxs(Box, {
      className: "form-item",
      children: [/*#__PURE__*/_jsxs(Box, {
        className: "form-item-label",
        children: [label, required && /*#__PURE__*/_jsx(Required, {})]
      }), /*#__PURE__*/_jsxs(Box, {
        className: "form-item-body",
        children: [/*#__PURE__*/_jsx(Box, {
          className: "form-item-input",
          children: input
        }), /*#__PURE__*/_jsx(Box, {
          className: "form-item-action",
          style: !editing || directEditing ? {
            marginLeft: 0
          } : {},
          children: editing && !directEditing ? /*#__PURE__*/_jsxs(_Fragment, {
            children: [isEdited ? /*#__PURE__*/_jsx(IconButton, {
              "data-cy": "schema-form-item-confirm",
              onClick: handleSubmit,
              disabled: disabled || loading,
              sx: {
                animation: isShaking ? `${shakeKeyframes} 0.5s linear` : 'none'
              },
              size: "large",
              children: loading ? /*#__PURE__*/_jsx(CircularProgress, {
                size: 24
              }) : /*#__PURE__*/_jsx(DoneIcon, {})
            }) : null, /*#__PURE__*/_jsx(IconButton, {
              "data-cy": "schema-form-item-cancel",
              onClick: () => {
                setValue(defaultValue);
                setEditing(false);
              },
              disabled: disabled || loading,
              size: "large",
              children: /*#__PURE__*/_jsx(CloseIcon, {})
            })]
          }) : /*#__PURE__*/_jsx(Box, {
            children: triggers.length ? /*#__PURE__*/_jsx(InputTriggers, {
              triggers: triggers,
              disabled: disabled
            }) : null
          })
        })]
      }), editing && helperText && /*#__PURE__*/_jsx(FormHelperText, {
        error: true,
        children: helperText
      })]
    })
  });
}
FormSelectInput.propTypes = {
  sx: PropTypes.object,
  onSubmit: PropTypes.func,
  onChange: PropTypes.func,
  label: PropTypes.string,
  initialValue: PropTypes.string,
  required: PropTypes.bool,
  disabled: PropTypes.bool,
  triggers: PropTypes.array,
  options: PropTypes.array,
  helperText: PropTypes.string,
  formatterBeforeSubmit: PropTypes.func,
  config: PropTypes.object,
  directEditing: PropTypes.bool,
  searchable: PropTypes.bool
};