import { useState, type ComponentProps } from "react";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import { StatusChip, ConfirmDialog } from "../ui";

/** One entry in a {@link StatusChipMenu}. */
export interface StatusChipAction {
  /** Stable identifier, e.g. the target status. */
  key: string;
  /** Menu item text, e.g. "Dokončit". */
  label: string;
  /** Red menu-item text + danger ConfirmDialog variant. */
  danger?: boolean;
  /**
   * Confirmation dialog content. When omitted the action fires directly from
   * the menu without confirmation (used by "Vytvořit objednávku…", which
   * opens its own modal).
   */
  confirm?: { title: string; message: string; confirmText: string };
  /**
   * Executed on pick (after confirmation when `confirm` is set). Awaited:
   * while pending the ConfirmDialog shows its loading state and cannot be
   * closed; on resolve the dialog closes; on rejection it stays open (the
   * caller is responsible for toasting the error).
   */
  onAction: () => void | Promise<void>;
}

interface StatusChipMenuProps {
  /** Chip text (current status label). */
  label: string;
  /** Chip color, same palette as {@link StatusChip}. */
  color: ComponentProps<typeof StatusChip>["color"];
  /** Quick actions. Empty/undefined renders a plain non-clickable chip. */
  actions?: StatusChipAction[];
  /** Force a plain chip (e.g. the user lacks the edit permission). */
  disabled?: boolean;
  /** Tooltip on the clickable chip. */
  title?: string;
}

/**
 * Status chip with a quick-action menu, shared by the list pages
 * (offers / received orders / projects).
 *
 * Clicking the chip (stopPropagation, so row navigation never fires) opens a
 * dense MUI Menu of the valid next actions. Picking one closes the menu and
 * either fires `onAction` directly (no `confirm` given) or opens the single
 * shared ConfirmDialog instance — danger variant for destructive actions,
 * `loading` while the awaited `onAction` is pending, staying open when it
 * rejects per app convention (the caller toasts errors).
 *
 * With no actions — or with `disabled` — it renders a plain non-clickable
 * StatusChip without a tooltip.
 */
export default function StatusChipMenu({
  label,
  color,
  actions,
  disabled = false,
  title = "Změnit stav",
}: StatusChipMenuProps) {
  const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
  const [pending, setPending] = useState<StatusChipAction | null>(null);
  const [loading, setLoading] = useState(false);

  if (disabled || !actions || actions.length === 0) {
    return <StatusChip label={label} color={color} />;
  }

  const handlePick = (action: StatusChipAction) => {
    setAnchorEl(null);
    if (action.confirm) {
      setPending(action);
    } else {
      void (async () => {
        try {
          await action.onAction();
        } catch {
          // Expected: the caller toasts its own errors; nothing to close here.
        }
      })();
    }
  };

  const handleConfirm = async () => {
    if (!pending) return;
    setLoading(true);
    try {
      await pending.onAction();
      // Success → close; ConfirmDialog freezes its content through the fade.
      setPending(null);
    } catch {
      // Expected: rejection keeps the dialog open; the caller toasts the error.
    } finally {
      setLoading(false);
    }
  };

  return (
    <>
      <StatusChip
        label={label}
        color={color}
        title={title}
        aria-haspopup="menu"
        aria-expanded={Boolean(anchorEl)}
        onClick={(e) => {
          e.stopPropagation();
          setAnchorEl(e.currentTarget);
        }}
      />
      <Menu
        anchorEl={anchorEl}
        open={Boolean(anchorEl)}
        onClose={() => setAnchorEl(null)}
        anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
        transformOrigin={{ vertical: "top", horizontal: "left" }}
        slotProps={{ list: { dense: true } }}
      >
        {actions.map((action) => (
          <MenuItem
            key={action.key}
            // stopPropagation: MUI portals re-bubble synthetic events to
            // React-tree ancestors — a future onRowClick row must not fire.
            onClick={(e) => {
              e.stopPropagation();
              handlePick(action);
            }}
            sx={action.danger ? { color: "error.main" } : undefined}
          >
            {action.label}
          </MenuItem>
        ))}
      </Menu>
      <ConfirmDialog
        isOpen={pending !== null}
        onClose={() => setPending(null)}
        onConfirm={() => void handleConfirm()}
        title={pending?.confirm?.title ?? ""}
        message={pending?.confirm?.message ?? ""}
        confirmText={pending?.confirm?.confirmText}
        confirmVariant={pending?.danger ? "danger" : "primary"}
        loading={loading}
      />
    </>
  );
}
