import React from 'react';
import Box from '@mui/material/Box';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import SwapVertIcon from '@mui/icons-material/SwapVert';
import type { SxProps, Theme } from '@mui/material/styles';
import { Button } from '../../atoms/Button';

// ─── Types ──────────────────────────────────────────────────────────────────

/** A sort option shown in the menu */
export interface SortOption {
  /** Machine-readable value (e.g. 'price_low'). Passed back via `onChange`. */
  value: string;
  /** Human-readable label (e.g. 'Price low to high'). Shown in the menu and,
   *  in the `verbose` variant, on the trigger button. */
  label: string;
}

/** Props for the FA SortMenu molecule */
export interface SortMenuProps {
  /** Current sort value (controlled). Must match one of the options' values. */
  value: string;
  /** Fires when the user picks a different sort option. */
  onChange: (value: string) => void;
  /** Sort options to surface in the menu, in display order. */
  options: SortOption[];
  /** Trigger label variant:
   *  - `compact` (default): button reads just "Sort by"; current value
   *    surfaces only in the menu's selected item and in the aria-label.
   *    Best for narrow surfaces (mobile, chip-strip floating controls).
   *  - `verbose`: button reads "Sort: <current label>" with a leading
   *    swap-vertical icon. Best for desktop where horizontal space is
   *    cheap and the current value is worth surfacing inline. */
  variant?: 'compact' | 'verbose';
  /** MUI sx prop — applied to the trigger Button. Callers pass chrome
   *  (bgcolor, border, shadow, radius, height) here. */
  sx?: SxProps<Theme>;
}

// ─── Component ──────────────────────────────────────────────────────────────

/**
 * Dropdown sort control — a trigger Button + anchored Menu.
 *
 * Tap the button → menu opens anchored to the button's bottom-right; pick
 * an option → menu closes and `onChange` fires with the new value. The
 * currently-selected option is visually marked in the menu (MUI's
 * `selected` state on MenuItem).
 *
 * **Accessibility:** trigger button has `aria-haspopup="listbox"` and an
 * `aria-label` that spells out the current sort ("Sort by Recommended"),
 * so screen-reader users get the state regardless of which label variant
 * is rendered. Selected MenuItem has `aria-selected="true"` via MUI.
 *
 * Originally extracted from ProvidersStep (which had the same Button +
 * Menu pattern inline in two places with a minor "Sort by" vs
 * "Sort: <label>" difference). Intended for reuse on VenueStep,
 * CoffinsStep, or anywhere a sort menu is needed.
 */
export const SortMenu = React.forwardRef<HTMLButtonElement, SortMenuProps>(
  ({ value, onChange, options, variant = 'compact', sx }, ref) => {
    const [anchor, setAnchor] = React.useState<null | HTMLElement>(null);
    const current = options.find((o) => o.value === value);
    const ariaLabel = `Sort by ${current?.label ?? 'default'}`;

    return (
      <>
        <Button
          ref={ref}
          variant="outlined"
          color="secondary"
          size="small"
          startIcon={variant === 'verbose' ? <SwapVertIcon sx={{ fontSize: 16 }} /> : undefined}
          onClick={(e) => setAnchor(e.currentTarget)}
          aria-haspopup="listbox"
          aria-label={ariaLabel}
          sx={sx}
        >
          {variant === 'compact' ? (
            'Sort by'
          ) : (
            <>
              <Box component="span" sx={{ color: 'text.secondary', fontWeight: 400, mr: 0.5 }}>
                Sort:
              </Box>
              {current?.label ?? ''}
            </>
          )}
        </Button>
        <Menu
          anchorEl={anchor}
          open={Boolean(anchor)}
          onClose={() => setAnchor(null)}
          anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
          transformOrigin={{ vertical: 'top', horizontal: 'right' }}
        >
          {options.map((opt) => (
            <MenuItem
              key={opt.value}
              selected={opt.value === value}
              onClick={() => {
                onChange(opt.value);
                setAnchor(null);
              }}
              sx={{ fontSize: '0.813rem' }}
            >
              {opt.label}
            </MenuItem>
          ))}
        </Menu>
      </>
    );
  },
);

SortMenu.displayName = 'SortMenu';
export default SortMenu;
