import {
  CircularProgress,
  IconButton,
  ListItemIcon,
  ListItemText,
  Menu,
  MenuItem,
} from '@mui/material'
import type { DownloadItem, DownloadProps } from './types'
import { FileDownloadOutlined } from '@mui/icons-material'
import { useState, type MouseEvent } from 'react'
import { useWidgetSelector } from '../../stores/use-widget-selector'

const EMPTY_LABELS: NonNullable<DownloadProps['labels']> = {}

/**
 * Dropdown menu action for exporting widget data in various formats (CSV, PNG, etc.).
 *
 * Reads widget data from the store and triggers downloads using the modifier
 * function defined in each `DownloadItem`.
 *
 * @example
 * ```tsx
 * <Download id={widgetId} items={barDownloadConfig({ refUI })} />
 * ```
 */
export function Download({
  id,
  items,
  labels = EMPTY_LABELS,
  Icon,
  IconButtonProps,
}: DownloadProps) {
  const { data } = useWidgetSelector(id, (w) => ({
    data: w?.data,
  }))

  const [isDownloading, setIsDownloading] = useState(false)
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)

  const handleToggle = (event: MouseEvent<HTMLElement>) => {
    event.stopPropagation()
    setAnchorEl(event.currentTarget)
  }

  const handleDownload = (data: string, option: DownloadItem) => {
    const link = document.createElement('a')
    link.href = data
    link.download = option.filename ?? id
    link.style.display = 'none'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    option.callback?.(link.href)
  }

  const handleClick = async (
    event: MouseEvent<HTMLElement>,
    option: DownloadItem,
  ) => {
    event.stopPropagation()

    setIsDownloading(true)
    setAnchorEl(null)

    const result = await option.modifier(data)

    if (!result) {
      setIsDownloading(false)
      return
    }

    handleDownload(result, option)
    setIsDownloading(false)
  }

  return (
    <>
      <IconButton
        size='small'
        aria-label={labels.ariaLabel ?? 'download options'}
        aria-controls='options-menu'
        aria-haspopup='true'
        onClick={handleToggle}
        {...IconButtonProps}
        disabled={isDownloading || items.length === 0}
        className={isDownloading || anchorEl ? 'active' : ''}
      >
        {isDownloading ? (
          <CircularProgress size={18} color='inherit' />
        ) : (
          (Icon ?? <FileDownloadOutlined />)
        )}
      </IconButton>
      <Menu
        variant='menu'
        elevation={8}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'right',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'right',
        }}
        anchorEl={anchorEl}
        open={Boolean(anchorEl)}
        onClose={() => setAnchorEl(null)}
        MenuListProps={{
          sx: {
            paddingBottom: 0,
          },
        }}
      >
        {items.map((option) => (
          <MenuItem
            key={option.id}
            disabled={option.disabled}
            onClick={(e) => void handleClick(e, option)}
          >
            {option.icon && (
              <ListItemIcon sx={{ color: 'text.primary' }}>
                {option.icon}
              </ListItemIcon>
            )}
            <ListItemText>{option.label}</ListItemText>
          </MenuItem>
        ))}
      </Menu>
    </>
  )
}
