import * as React from 'react';
import { ReactElement } from 'react';
import PropTypes from 'prop-types';
import ActionDelete from '@mui/icons-material/Delete';
import inflection from 'inflection';
import { SxProps, alpha, styled, useTheme } from '@mui/material/styles';
import {
  DeleteManyParams,
  MutationMode,
  RaRecord,
  useDeleteMany,
  useListContext,
  useNotify,
  useRefresh,
  useResourceContext,
  useSafeSetState,
  useTranslate
} from 'ra-core';
import { BulkActionProps, Button, ButtonProps, Confirm } from 'react-admin';
import { UseMutationOptions } from 'react-query';
import _ from 'lodash';
import { Box, Typography } from '@mui/material';
import { DeleteFilled } from '@ant-design/icons';

/**
 * BulkDeleteWithConfirmButton component allows you to delete multiple records with a confirmation dialog.
 *
 * This component extends the functionality of the react-admin BulkDeleteWithConfirmButton by adding
 * two optional methods, `onSuccess` and `onError`, to the props. These methods allow users
 * to extend what happens in the `onSuccess` and `onError` methods of the `useDeleteMany` hook.
 *
 * @example
 * <BulkDeleteWithConfirmButton
 *   onSuccess={() => {
 *     // Custom success logic
 *   }}
 *   onError={() => {
 *     // Custom error logic
 *   }}
 * />
 */
function BulkDeleteWithConfirmButton(props: BulkDeleteWithConfirmButtonProps) {
  const {
    confirmTitle,
    confirmContent,
    confirmColor = 'primary',
    dialogSx,
    icon = defaultIcon,
    label = 'ra.action.delete',
    mutationMode = 'pessimistic',
    mutationOptions = {},
    onClick,
    onSuccess: externalOnSuccess,
    onError: externalOnError,
    ...rest
  } = props;
  const { meta: mutationMeta, ...otherMutationOptions } = mutationOptions;
  const { selectedIds, onUnselectItems } = useListContext(props);
  const [isOpen, setOpen] = useSafeSetState(false);
  const notify = useNotify();
  const resource = useResourceContext(props);
  const refresh = useRefresh();
  const translate = useTranslate();
  const theme = useTheme();
  const [deleteMany, { isLoading }] = useDeleteMany(
    resource,
    { ids: selectedIds, meta: mutationMeta },
    {
      // @ts-ignore
      onSuccess: () => {
        refresh();
        notify('ra.notification.deleted', {
          type: 'info',
          messageArgs: { smart_count: selectedIds.length },
          undoable: mutationMode === 'undoable'
        });
        onUnselectItems();
        setOpen(false);
        if (externalOnSuccess && _.isFunction(externalOnSuccess)) {
          externalOnSuccess();
        }
      },
      // @ts-ignore
      onError: (error: Error) => {
        notify(typeof error === 'string' ? error : error.message || 'ra.notification.http_error', {
          type: 'error',
          messageArgs: {
            _: typeof error === 'string' ? error : error && error.message ? error.message : undefined
          }
        });
        setOpen(false);
        if (externalOnError && _.isFunction(externalOnError)) {
          externalOnError();
        }
      },
      mutationMode,
      ...otherMutationOptions
    }
  );

  function handleClick(e: any) {
    setOpen(true);
    e.stopPropagation();
  }

  function handleDialogClose() {
    setOpen(false);
  }

  function handleDelete(e: any) {
    deleteMany();

    if (typeof onClick === 'function') {
      onClick(e);
    }
  }

  return (
    <>
      <StyledButton onClick={handleClick} label={label} {...sanitizeRestProps(rest)}>
        {icon}
      </StyledButton>
      <Confirm
        isOpen={isOpen}
        loading={isLoading}
        sx={
          dialogSx || {
            '& .MuiPaper-root': {
              p: 2
            },
            '& .MuiDialogActions-root': {
              display: 'flex',
              justifyContent: 'space-between',
              width: '100%',
              '& .RaConfirm-confirmPrimary': {
                backgroundColor: theme.palette.primary.main,
                color: theme.palette.primary.contrastText,
                ml: 2,
                '&:hover': {
                  backgroundColor: theme.palette.primary.dark
                }
              },
              '& .MuiButtonBase-root': {
                width: '50%',
                border: `1px solid ${theme.palette.action.disabled}`
              },
              '& .MuiButton-icon': {
                display: 'none'
              }
            }
          }
        }
        title={
          confirmTitle ? (
            typeof confirmTitle === 'string' ? (
              translate(confirmTitle)
            ) : (
              confirmTitle
            )
          ) : (
            <Box
              sx={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center'
              }}
            >
              <Box
                sx={{
                  color: 'primary.main',
                  fontSize: '28px',
                  borderRadius: '50%',
                  backgroundColor: 'primary.lighter',
                  width: '56px',
                  height: '56px',
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center'
                }}
              >
                <DeleteFilled />
              </Box>
            </Box>
          )
        }
        content={
          confirmContent || (
            <Typography maxWidth="300px" variant="h4" align="center">
              {translate('ra.message.bulk_delete_content', {
                _: 'ra.message.bulk_delete_content',
                smart_count: selectedIds.length,
                name: translate(`resources.${resource}.forcedCaseName`, {
                  smart_count: selectedIds.length,
                  _: inflection.humanize(
                    translate(`resources.${resource}.name`, {
                      smart_count: selectedIds.length,
                      _: inflection.inflect(resource, selectedIds.length)
                    }),
                    true
                  )
                })
              })}
            </Typography>
          )
        }
        confirmColor={confirmColor}
        translateOptions={{
          smart_count: selectedIds.length,
          name: translate(`resources.${resource}.forcedCaseName`, {
            smart_count: selectedIds.length,
            _: inflection.humanize(
              translate(`resources.${resource}.name`, {
                smart_count: selectedIds.length,
                _: inflection.inflect(resource, selectedIds.length)
              }),
              true
            )
          })
        }}
        onConfirm={handleDelete}
        onClose={handleDialogClose}
      />
    </>
  );
}

function sanitizeRestProps({
  classes,
  filterValues,
  label,
  selectedIds,
  ...rest
}: Omit<BulkDeleteWithConfirmButtonProps, 'resource' | 'icon' | 'mutationMode'>) {
  return rest;
}

interface BulkDeleteWithConfirmButtonProps<RecordType extends RaRecord = any, MutationOptionsError = unknown>
  extends BulkActionProps,
    ButtonProps {
  confirmContent?: React.ReactNode;
  confirmTitle?: React.ReactNode;
  confirmColor?: 'primary' | 'warning';
  dialogSx?: SxProps;
  icon?: ReactElement;
  mutationMode: MutationMode;
  mutationOptions?: UseMutationOptions<RecordType, MutationOptionsError, DeleteManyParams<RecordType>> & {
    meta?: any;
  };
  /**
   * Optional custom success logic to be executed after the default onSuccess logic.
   * This method allows users to extend what happens in the onSuccess method of the useDeleteMany hook.
   */
  onSuccess?: () => void;
  /**
   * Optional custom error logic to be executed after the default onError logic.
   * This method allows users to extend what happens in the onError method of the useDeleteMany hook.
   */
  onError?: () => void;
}

const PREFIX = 'RaBulkDeleteWithConfirmButton';

const StyledButton = styled(Button, {
  name: PREFIX,
  overridesResolver: (styles) => styles.root
})(({ theme }) => ({
  color: theme.palette.error.main,
  '&:hover': {
    backgroundColor: alpha(theme.palette.error.main, 0.12),
    // Reset on mouse devices
    '@media (hover: none)': {
      backgroundColor: 'transparent'
    }
  }
}));

const defaultIcon = <ActionDelete />;

BulkDeleteWithConfirmButton.propTypes = {
  confirmTitle: PropTypes.node,
  confirmContent: PropTypes.node,
  confirmColor: PropTypes.string,
  dialogSx: PropTypes.object,
  icon: PropTypes.element,
  label: PropTypes.string,
  mutationMode: PropTypes.oneOf(['pessimistic', 'optimistic', 'undoable']),
  resource: PropTypes.string,
  selectedIds: PropTypes.arrayOf(PropTypes.any),
  onSuccess: PropTypes.func,
  onError: PropTypes.func
};

export { BulkDeleteWithConfirmButton };
export type { BulkDeleteWithConfirmButtonProps };
