import {
  useEffect,
  useId,
  useRef,
  useState,
  type CSSProperties,
  type MouseEvent,
  type ReactNode,
} from 'react';

export interface DebugOverlayPayload {
  /** Stable id surfaced in the inspector — falls back to React key. */
  id?: string;
  /** Free-form title for the modal header. */
  title?: string;
  /** Arbitrary plain-data payload — rendered as syntax-light JSON. */
  data: unknown;
}

export interface DebugOverlayProps {
  /** What the user normally sees — wrap an AI bubble, tool card, etc. */
  children: ReactNode;
  /** The structured payload to reveal on Shift-click. */
  payload: DebugOverlayPayload;
  /**
   * Modifier required to open the inspector.
   *   - `shift` (default) — accessible, no platform-conflict
   *   - `alt`             — for cases where Shift is already used
   *   - `meta`            — ⌘ on mac, Win key elsewhere
   */
  modifier?: 'shift' | 'alt' | 'meta';
  /** Bypass entirely (production mode). */
  disabled?: boolean;
  /** Optional className applied to the wrapper. */
  className?: string;
  style?: CSSProperties;
}

/**
 * `<DebugOverlay>` — Shift-click any wrapped surface to inspect its
 * underlying data. Wave 13.C.5 (MAG.8).
 *
 * Wraps a single child element and patches its onClick. The modifier
 * is configurable; production sites can pass `disabled` to render the
 * child unchanged.
 *
 * Render JSON via a built-in `<pre>`; the host can wrap a custom
 * formatter by stringifying upstream.
 */
export function DebugOverlay({
  children,
  payload,
  modifier = 'shift',
  disabled = false,
  className,
  style,
}: DebugOverlayProps) {
  const [open, setOpen] = useState(false);
  const triggerRef = useRef<HTMLElement | null>(null);

  // Style cursor hint on the wrapper when active.
  const wrapperStyle: CSSProperties = {
    display: 'inline-block',
    cursor: disabled ? undefined : 'help',
    ...style,
  };

  // Patch the single child to intercept clicks.
  const onWrapperClick = (e: MouseEvent) => {
    if (disabled) return;
    const matchMod =
      modifier === 'shift'
        ? e.shiftKey
        : modifier === 'alt'
          ? e.altKey
          : e.metaKey || e.ctrlKey;
    if (!matchMod) return;
    e.preventDefault();
    e.stopPropagation();
    triggerRef.current = (e.currentTarget as HTMLElement) ?? null;
    setOpen(true);
  };

  return (
    <>
      <span
        data-testid="bl-debug-overlay-wrapper"
        data-modifier={modifier}
        data-disabled={disabled ? 'true' : 'false'}
        className={className}
        style={wrapperStyle}
        onClick={onWrapperClick}
      >
        {children}
      </span>
      {open && (
        <DebugOverlayModal
          payload={payload}
          onClose={() => {
            setOpen(false);
            triggerRef.current?.focus?.();
          }}
        />
      )}
    </>
  );
}

function DebugOverlayModal({
  payload,
  onClose,
}: {
  payload: DebugOverlayPayload;
  onClose: () => void;
}) {
  const titleId = useId();
  const closeRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    closeRef.current?.focus();
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        onClose();
      }
    };
    window.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [onClose]);

  let pretty = '';
  try {
    pretty = JSON.stringify(payload.data, null, 2);
  } catch {
    pretty = '[unserialisable payload]';
  }

  return (
    <div
      data-testid="bl-debug-overlay-modal-root"
      style={{
        position: 'fixed',
        inset: 0,
        zIndex: 70,
        display: 'grid',
        placeItems: 'center',
        padding: 24,
      }}
    >
      <button
        type="button"
        aria-label="Close inspector"
        onClick={onClose}
        data-testid="bl-debug-overlay-backdrop"
        style={{
          position: 'absolute',
          inset: 0,
          background: 'rgba(0,0,0,0.55)',
          backdropFilter: 'blur(4px)',
          border: 0,
          cursor: 'pointer',
        }}
      />
      <section
        role="dialog"
        aria-modal="true"
        aria-labelledby={titleId}
        data-testid="bl-debug-overlay-modal"
        style={{
          position: 'relative',
          width: 'min(720px, 96vw)',
          maxHeight: '88vh',
          display: 'flex',
          flexDirection: 'column',
          background: 'var(--bl-surface-card, #fff)',
          color: 'var(--bl-text-primary, #111)',
          borderRadius: 16,
          border: '1px solid var(--bl-border, rgba(0,0,0,0.12))',
          boxShadow: '0 24px 64px rgba(0,0,0,0.32)',
          overflow: 'hidden',
        }}
      >
        <header
          style={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'space-between',
            padding: '12px 16px',
            borderBottom: '1px solid var(--bl-border-subtle, rgba(0,0,0,0.06))',
          }}
        >
          <h3
            id={titleId}
            style={{ margin: 0, fontSize: 14, fontWeight: 600 }}
          >
            {payload.title ?? 'Inspector'}
            {payload.id && (
              <span style={{ opacity: 0.55, fontWeight: 400 }}>
                {' · '}
                <code style={{ fontSize: 12 }}>{payload.id}</code>
              </span>
            )}
          </h3>
          <button
            ref={closeRef}
            type="button"
            aria-label="Close"
            onClick={onClose}
            style={{
              border: 0,
              background: 'transparent',
              cursor: 'pointer',
              fontSize: 18,
              lineHeight: 1,
              padding: 4,
              color: 'var(--bl-text-secondary, #555)',
            }}
          >
            ×
          </button>
        </header>
        <pre
          data-testid="bl-debug-overlay-payload"
          style={{
            margin: 0,
            padding: 16,
            overflow: 'auto',
            background: 'var(--bl-surface-muted, #f6f6f6)',
            color: 'var(--bl-text-primary, #111)',
            fontFamily:
              'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
            fontSize: 12,
            lineHeight: 1.5,
            whiteSpace: 'pre',
          }}
        >
          {pretty}
        </pre>
      </section>
    </div>
  );
}
