import {
  useEffect,
  type ReactNode,
  type FormEvent,
  Children,
  isValidElement,
  cloneElement,
} from "react";
import { motion, AnimatePresence } from "framer-motion";
import useModalLock from "../hooks/useModalLock";
import useReducedMotion from "../hooks/useReducedMotion";

export interface FormModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSubmit?: () => void; // called when user clicks primary button (only if provided)
  title: string;
  /** Optional muted line shown under the title in the header. */
  subtitle?: ReactNode;
  children: ReactNode; // modal body (form fields)
  submitLabel?: string; // primary button text
  cancelLabel?: string; // cancel button text
  loading?: boolean;
  /** Disable the primary (submit) button — e.g. until the form is valid.
   *  Keeps the button visibly greyed out instead of clickable-but-inert. */
  submitDisabled?: boolean;
  hideFooter?: boolean; // for "view-only" modals
  size?: "sm" | "md" | "lg"; // optional
  closeOnBackdrop?: boolean; // default true
  closeOnEsc?: boolean; // default true
  /** Slot for footer-left actions (e.g. delete). Rendered to the LEFT of
   *  the standard cancel/submit group in the modal footer. */
  footerLeft?: ReactNode;
  /** Hide the close × in the header. Default false. */
  hideCloseButton?: boolean;
}

export default function FormModal({
  isOpen,
  onClose,
  onSubmit,
  title,
  subtitle,
  children,
  submitLabel = "Uložit",
  cancelLabel = "Zrušit",
  loading = false,
  submitDisabled = false,
  hideFooter = false,
  size = "md",
  closeOnBackdrop = true,
  closeOnEsc = true,
  footerLeft,
  hideCloseButton = false,
}: FormModalProps) {
  useModalLock(isOpen);
  const reducedMotion = useReducedMotion();

  useEffect(() => {
    if (!isOpen || !closeOnEsc) return;

    function handleKeyDown(e: KeyboardEvent) {
      if (e.key === "Escape" && !loading) {
        onClose();
      }
    }

    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [isOpen, closeOnEsc, loading, onClose]);

  const handleBackdropClick = () => {
    if (closeOnBackdrop && !loading) onClose();
  };

  const handlePrimaryClick = (e: FormEvent) => {
    e.preventDefault();
    if (onSubmit) onSubmit();
  };

  const titleId = "form-modal-title";
  const modalClassName =
    size === "lg" ? "admin-modal admin-modal-lg" : "admin-modal";

  // Snappier ease curve for modal entry — matches the "industrial/refined"
  // tone. Roughly equivalent to the cubic-bezier(0.16, 1, 0.3, 1) used by
  // a lot of design systems for "expo out" feel.
  const ease = [0.16, 1, 0.3, 1] as const;
  const duration = reducedMotion ? 0 : 0.22;
  // Stagger the body children slightly for a "drawing-in" reveal. We cap
  // the cascade so long forms don't drag on forever.
  const childrenArray = Children.toArray(children).filter(isValidElement);
  const stagger = reducedMotion ? 0 : Math.min(childrenArray.length, 5) * 0.03;

  return (
    <AnimatePresence>
      {isOpen && (
        <motion.div
          className="admin-modal-overlay"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: reducedMotion ? 0 : 0.18 }}
        >
          <div className="admin-modal-backdrop" onClick={handleBackdropClick} />
          <motion.div
            className={modalClassName}
            role="dialog"
            aria-modal="true"
            aria-labelledby={titleId}
            initial={{ opacity: 0, scale: 0.96, y: 16 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.97, y: 8 }}
            transition={{ duration, ease }}
          >
            <div className="admin-modal-header">
              <div className="admin-modal-heading">
                <h2 id={titleId} className="admin-modal-title">
                  {title}
                </h2>
                {subtitle && <p className="admin-modal-subtitle">{subtitle}</p>}
              </div>
              {!hideCloseButton && (
                <button
                  type="button"
                  className="admin-modal-close"
                  onClick={() => !loading && onClose()}
                  aria-label="Zavřít"
                  title="Zavřít (Esc)"
                  disabled={loading}
                >
                  <svg
                    width="18"
                    height="18"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    strokeWidth="2"
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    aria-hidden
                  >
                    <line x1="18" y1="6" x2="6" y2="18" />
                    <line x1="6" y1="6" x2="18" y2="18" />
                  </svg>
                </button>
              )}
            </div>

            <div className="admin-modal-body">
              {reducedMotion || stagger === 0
                ? children
                : Children.map(children, (child, i) => {
                    if (!isValidElement(child)) return child;
                    return (
                      <motion.div
                        initial={{ opacity: 0, y: 6 }}
                        animate={{ opacity: 1, y: 0 }}
                        transition={{
                          duration: 0.2,
                          delay: 0.04 + i * 0.03,
                          ease: "easeOut",
                        }}
                      >
                        {cloneElement(child)}
                      </motion.div>
                    );
                  })}
            </div>

            {!hideFooter && (
              <div className="admin-modal-footer">
                <div className="admin-modal-footer-left">{footerLeft}</div>
                <div className="admin-modal-footer-right">
                  <button
                    type="button"
                    onClick={() => !loading && onClose()}
                    className="admin-btn admin-btn-secondary"
                    disabled={loading}
                  >
                    {cancelLabel}
                  </button>
                  {onSubmit && (
                    <button
                      type="button"
                      onClick={handlePrimaryClick}
                      className="admin-btn admin-btn-primary"
                      disabled={loading || submitDisabled}
                    >
                      {loading ? "Zpracování..." : submitLabel}
                    </button>
                  )}
                </div>
              </div>
            )}
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
