import * as React from "react";
import { X } from "lucide-react";

export interface SheetProps {
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
  children?: React.ReactNode;
}

export interface SheetTriggerProps {
  children?: React.ReactNode;
  asChild?: boolean;
}

export interface SheetContentProps {
  children?: React.ReactNode;
  className?: string;
}

export interface SheetHeaderProps {
  children?: React.ReactNode;
  className?: string;
}

export interface SheetTitleProps {
  children?: React.ReactNode;
  className?: string;
}

export interface SheetDescriptionProps {
  children?: React.ReactNode;
  className?: string;
}

const SheetContext = React.createContext<{
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
}>({});

export function Sheet({ open, onOpenChange, children }: SheetProps): React.JSX.Element {
  const contextValue: { open?: boolean; onOpenChange?: (open: boolean) => void } = {};

  if (open !== undefined) {
    contextValue.open = open;
  }

  if (onOpenChange !== undefined) {
    contextValue.onOpenChange = onOpenChange;
  }

  return <SheetContext.Provider value={contextValue}>{children}</SheetContext.Provider>;
}

export function SheetTrigger({ children, asChild }: SheetTriggerProps): React.JSX.Element {
  const { onOpenChange } = React.useContext(SheetContext);

  if (asChild && React.isValidElement(children)) {
    return React.cloneElement(children, {
      onClick: () => onOpenChange?.(true),
    } as React.HTMLAttributes<HTMLElement>);
  }

  return (
    <button type="button" onClick={() => onOpenChange?.(true)}>
      {children}
    </button>
  );
}

export function SheetContent({
  children,
  className = "",
}: SheetContentProps): React.JSX.Element | null {
  const { open, onOpenChange } = React.useContext(SheetContext);

  React.useEffect(() => {
    if (!open) {
      return;
    }

    const onKeyDown = (event: KeyboardEvent): void => {
      if (event.key === "Escape") {
        onOpenChange?.(false);
      }
    };

    window.addEventListener("keydown", onKeyDown);
    return (): void => {
      window.removeEventListener("keydown", onKeyDown);
    };
  }, [onOpenChange, open]);

  if (!open) {
    return null;
  }

  return (
    <div className="fixed inset-0 z-50">
      <button
        type="button"
        aria-label="Close sheet"
        className="absolute inset-0 h-full w-full bg-black/50"
        onClick={() => onOpenChange?.(false)}
      />

      <div
        className={`absolute inset-y-0 right-0 z-10 flex h-full w-full max-w-3xl flex-col border-l border-border bg-background p-6 shadow-xl ${className}`}
      >
        <button
          type="button"
          onClick={() => onOpenChange?.(false)}
          className="absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100"
        >
          <X className="h-4 w-4" />
          <span className="sr-only">Close</span>
        </button>

        {children}
      </div>
    </div>
  );
}

export function SheetHeader({ children, className = "" }: SheetHeaderProps): React.JSX.Element {
  return <div className={`space-y-1 pr-8 ${className}`}>{children}</div>;
}

export function SheetTitle({ children, className = "" }: SheetTitleProps): React.JSX.Element {
  return <h2 className={`text-lg font-semibold ${className}`}>{children}</h2>;
}

export function SheetDescription({
  children,
  className = "",
}: SheetDescriptionProps): React.JSX.Element {
  return <p className={`text-sm text-muted-foreground ${className}`}>{children}</p>;
}
