import React, { useEffect } from 'react';

/** Tone hint used to colour the confirm button. */
export type ConfirmDialogTone = 'default' | 'destructive';

/** Props for {@link ConfirmDialog}. */
export interface ConfirmDialogProps {
  /** Controls visibility - mirror this in the caller's state. */
  open: boolean;
  /** Called when the modal requests to close (Esc, backdrop, cancel). */
  onOpenChange: (next: boolean) => void;
  /** Short headline rendered as the dialog title. */
  title: string;
  /** Longer body copy explaining what will happen on confirm. */
  description: string;
  /** Label of the affirmative button. Defaults to "Yes". */
  confirmLabel?: string;
  /** Label of the dismissive button. Defaults to "No". */
  cancelLabel?: string;
  /** Visual tone of the confirm button. Defaults to ``"default"``. */
  tone?: ConfirmDialogTone;
  /** Disables both buttons while a parent-side request is in flight. */
  busy?: boolean;
  /** Optional label shown on the confirm button while ``busy`` is true. */
  busyLabel?: string;
  /** Fired when the user confirms; the parent runs the actual side effect. */
  onConfirm: () => void;
}

/**
 * Generic Yes/No confirmation modal styled with the plugin's Tailwind
 * palette. Replaces ``window.confirm`` so destructive actions get a real,
 * themed dialog with Esc/backdrop handling. The caller owns the side effect
 * and the open/close state - this component is intentionally dumb.
 */
const ConfirmDialog = ({
  open,
  onOpenChange,
  title,
  description,
  confirmLabel = 'Yes',
  cancelLabel = 'No',
  tone = 'default',
  busy = false,
  busyLabel,
  onConfirm,
}: ConfirmDialogProps): JSX.Element | null => {
  useEffect(() => {
    if (!open) return undefined;
    const handleKey = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && !busy) onOpenChange(false);
    };
    window.addEventListener('keydown', handleKey);

    return () => window.removeEventListener('keydown', handleKey);
  }, [open, busy, onOpenChange]);

  if (!open) return null;

  const confirmClass =
    tone === 'destructive'
      ? 'bg-red-600 hover:bg-red-700 text-white'
      : 'bg-black hover:bg-gray-800 text-white';

  return (
    <div className="fixed inset-0 z-[1000] flex items-center justify-center">
      <div
        className="absolute inset-0 bg-black/40"
        onClick={() => {
          if (!busy) onOpenChange(false);
        }}
      />
      <div
        role="dialog"
        aria-modal="true"
        aria-label={title}
        className="relative z-10 w-full max-w-sm rounded-xl bg-white p-5 shadow-xl"
      >
        <h3 className="text-base font-semibold text-gray-900">{title}</h3>
        <p className="mt-2 text-sm text-gray-600">{description}</p>
        <div className="mt-5 flex justify-end gap-2">
          <button
            type="button"
            disabled={busy}
            onClick={() => onOpenChange(false)}
            className="rounded-md border border-gray-200 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-60"
          >
            {cancelLabel}
          </button>
          <button
            type="button"
            disabled={busy}
            onClick={onConfirm}
            className={`rounded-md px-3 py-1.5 text-sm font-medium disabled:opacity-60 ${confirmClass}`}
          >
            {busy && busyLabel ? busyLabel : confirmLabel}
          </button>
        </div>
      </div>
    </div>
  );
};

export default ConfirmDialog;
