'use client';

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

interface DialogProps {
    isOpen: boolean;
    onClose: () => void;
    title: string;
    children: ReactNode;
    /** Optional footer (actions). */
    footer?: ReactNode;
}

/**
 * Reusable modal shell with the accessibility behaviour ConfirmDialog pioneered
 * (T4): role=dialog + aria-modal, Escape-to-close, focus trap, initial focus,
 * focus restoration on close (WCAG 2.1.2 / 2.4.3). Composes into feature dialogs.
 */
export function Dialog({ isOpen, onClose, title, children, footer }: DialogProps) {
    const panelRef = useRef<HTMLDivElement>(null);
    const previousFocusRef = useRef<HTMLElement | null>(null);
    // Keep the latest onClose in a ref so it is NOT an effect dependency.
    // Parents pass an inline onClose (new identity every render); if it were a
    // dep, the focus-management effect below would re-run on every keystroke and
    // panel.focus() would steal focus out of the input after each character.
    const onCloseRef = useRef(onClose);
    useEffect(() => {
        onCloseRef.current = onClose;
    });
    const titleId = useId();

    useEffect(() => {
        if (!isOpen) return;
        previousFocusRef.current = document.activeElement as HTMLElement | null;
        const panel = panelRef.current;
        const selector =
            'button:not([disabled]), [href], input, textarea, select, [tabindex]:not([tabindex="-1"])';
        panel?.focus();
        document.body.style.overflow = 'hidden';

        function onKeyDown(e: KeyboardEvent) {
            if (e.key === 'Escape') {
                e.preventDefault();
                onCloseRef.current();
                return;
            }
            if (e.key === 'Tab' && panel) {
                const f = Array.from(panel.querySelectorAll<HTMLElement>(selector));
                if (f.length === 0) return;
                const first = f[0];
                const last = f[f.length - 1];
                const active = document.activeElement;
                if (e.shiftKey && (active === first || active === panel)) {
                    e.preventDefault();
                    last.focus();
                } else if (!e.shiftKey && active === last) {
                    e.preventDefault();
                    first.focus();
                }
            }
        }

        document.addEventListener('keydown', onKeyDown);
        return () => {
            document.removeEventListener('keydown', onKeyDown);
            document.body.style.overflow = 'unset';
            previousFocusRef.current?.focus?.();
        };
    }, [isOpen]);

    if (!isOpen) return null;

    return (
        <div
            className="fixed inset-0 z-[100] flex items-center justify-center p-4"
            role="dialog"
            aria-modal="true"
            aria-labelledby={titleId}
        >
            <div className="fixed inset-0 bg-slate-900/40 backdrop-blur-sm" aria-hidden="true" onClick={onClose} />
            <div
                ref={panelRef}
                tabIndex={-1}
                className="relative w-full max-w-lg rounded-2xl border border-border bg-surface p-6 shadow-2xl focus:outline-none"
            >
                <h3 id={titleId} className="text-lg font-bold text-fg">
                    {title}
                </h3>
                <div className="mt-2">{children}</div>
                {footer ? <div className="mt-5 flex justify-end gap-2">{footer}</div> : null}
            </div>
        </div>
    );
}
