'use client';

import { Button } from '@/components/actions/Button';
import { useScrollLock } from '@/components/foundation/client-hooks';
import { classNames } from '@/lib/components/classNames';
import { useEffect, useId, useRef, type ReactNode, type RefObject } from 'react';
import styles from './Dialog.module.css';

interface DialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  title: string;
  description?: string;
  children: ReactNode;
  closeLabel: string;
  initialFocusRef?: RefObject<HTMLElement | null>;
  returnFocusRef?: RefObject<HTMLElement | null>;
  variant?: 'modal' | 'drawer';
  dismissible?: boolean;
  className?: string;
}

export function Dialog({
  open,
  onOpenChange,
  title,
  description,
  children,
  closeLabel,
  initialFocusRef,
  returnFocusRef,
  variant = 'modal',
  dismissible = true,
  className,
}: DialogProps) {
  const dialogRef = useRef<HTMLDialogElement>(null);
  const closeRef = useRef<HTMLButtonElement>(null);
  const titleId = useId();
  const descriptionId = useId();
  useScrollLock(open);

  useEffect(() => {
    const dialog = dialogRef.current;
    if (!dialog) return;
    if (open && !dialog.open) {
      dialog.showModal();
      window.requestAnimationFrame(() => (initialFocusRef?.current ?? closeRef.current)?.focus());
    } else if (!open && dialog.open) {
      dialog.close();
    }
  }, [initialFocusRef, open]);

  const close = () => {
    dialogRef.current?.close();
    onOpenChange(false);
    window.requestAnimationFrame(() => returnFocusRef?.current?.focus());
  };

  return (
    <dialog
      ref={dialogRef}
      className={classNames(styles.dialog, styles[variant], className)}
      aria-labelledby={titleId}
      aria-describedby={description ? descriptionId : undefined}
      onCancel={(event) => {
        if (!dismissible) {
          event.preventDefault();
          return;
        }
        event.preventDefault();
        close();
      }}
      onClose={() => onOpenChange(false)}
      onClick={(event) => {
        if (dismissible && event.target === dialogRef.current) close();
      }}
    >
      <div className={styles.panel}>
        <header className={styles.header}>
          <div>
            <h2 id={titleId}>{title}</h2>
            {description ? <p id={descriptionId}>{description}</p> : null}
          </div>
          {dismissible ? (
            <Button
              ref={closeRef}
              intent="ghost"
              size="small"
              icon="close"
              aria-label={closeLabel}
              onClick={close}
            />
          ) : null}
        </header>
        <div className={styles.content}>{children}</div>
      </div>
    </dialog>
  );
}
