"use client";

import {
  useEffect,
  useRef,
  type CSSProperties,
  type KeyboardEvent,
  type MouseEvent,
  type ReactNode,
} from "react";

export interface DrawerProps {
  open: boolean;
  onClose: () => void;
  side: "right" | "bottom";
  /** CSS width string — default "360px" for right, "100%" for bottom */
  width?: string;
  children: ReactNode;
}

const FOCUSABLE_SELECTORS =
  'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';

/**
 * Drawer — accessible slide-in overlay panel.
 * - side="right"  → right side panel (default 360px width)
 * - side="bottom" → bottom-sheet (full width, mobile-first)
 * Click outside / Escape → onClose.
 * Focus trap: Tab cycles within open drawer.
 */
export function Drawer({ open, onClose, side, width, children }: DrawerProps) {
  const drawerRef = useRef<HTMLDivElement>(null);
  const previousFocusRef = useRef<Element | null>(null);

  // Save focus and restore on close
  useEffect(() => {
    if (open) {
      previousFocusRef.current = document.activeElement;
      // Move focus into drawer on next frame
      const id = requestAnimationFrame(() => {
        const el =
          drawerRef.current?.querySelector<HTMLElement>(FOCUSABLE_SELECTORS);
        el?.focus();
      });
      return () => cancelAnimationFrame(id);
    } else {
      if (previousFocusRef.current instanceof HTMLElement) {
        previousFocusRef.current.focus();
      }
    }
  }, [open]);

  // Escape key
  useEffect(() => {
    if (!open) return;
    const handleKeyDown = (e: globalThis.KeyboardEvent) => {
      if (e.key === "Escape") {
        onClose();
      }
    };
    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [open, onClose]);

  // Prevent body scroll while open
  useEffect(() => {
    if (open) {
      const prev = document.body.style.overflow;
      document.body.style.overflow = "hidden";
      return () => {
        document.body.style.overflow = prev;
      };
    }
  }, [open]);

  const handleOverlayClick = (e: MouseEvent<HTMLDivElement>) => {
    if (e.target === e.currentTarget) {
      onClose();
    }
  };

  const handleDrawerKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
    if (e.key !== "Tab") return;
    const drawer = drawerRef.current;
    if (!drawer) return;
    const focusable = Array.from(
      drawer.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS),
    ).filter((el) => !el.closest("[aria-hidden]"));
    if (focusable.length === 0) return;
    const first = focusable[0] as HTMLElement;
    const last = focusable[focusable.length - 1] as HTMLElement;
    if (e.shiftKey) {
      if (document.activeElement === first) {
        e.preventDefault();
        last.focus();
      }
    } else {
      if (document.activeElement === last) {
        e.preventDefault();
        first.focus();
      }
    }
  };

  const defaultWidth = side === "right" ? "360px" : "100%";
  const resolvedWidth = width ?? defaultWidth;

  const panelStyle: CSSProperties =
    side === "right"
      ? {
          position: "fixed",
          top: 0,
          right: 0,
          bottom: 0,
          width: resolvedWidth,
          maxWidth: "100vw",
          background: "var(--bg-card)",
          boxShadow: "0 0 32px rgba(0,0,0,0.18)",
          display: "flex",
          flexDirection: "column",
          transform: open ? "translateX(0)" : "translateX(100%)",
          transition: "transform 180ms ease",
          zIndex: 200,
          overflowY: "auto",
        }
      : {
          position: "fixed",
          left: 0,
          right: 0,
          bottom: 0,
          width: "100%",
          maxHeight: "85vh",
          background: "var(--bg-card)",
          boxShadow: "0 -4px 32px rgba(0,0,0,0.14)",
          borderRadius: "12px 12px 0 0",
          display: "flex",
          flexDirection: "column",
          transform: open ? "translateY(0)" : "translateY(100%)",
          transition: "transform 180ms ease",
          zIndex: 200,
          overflowY: "auto",
        };

  if (!open) {
    // Keep in DOM for transition but aria-hide
    return (
      <div
        aria-hidden="true"
        style={{
          position: "fixed",
          inset: 0,
          pointerEvents: "none",
          zIndex: 199,
        }}
      >
        <div ref={drawerRef} style={panelStyle} />
      </div>
    );
  }

  return (
    <div
      role="dialog"
      aria-modal="true"
      onClick={handleOverlayClick}
      style={{
        position: "fixed",
        inset: 0,
        background: "rgba(0,0,0,0.32)",
        zIndex: 199,
        display: "flex",
        alignItems: side === "bottom" ? "flex-end" : "stretch",
        justifyContent: side === "right" ? "flex-end" : "stretch",
      }}
    >
      <div
        ref={drawerRef}
        style={panelStyle}
        onKeyDown={handleDrawerKeyDown}
        tabIndex={-1}
      >
        {children}
      </div>
    </div>
  );
}
