import React, { useEffect, useRef, useCallback } from 'react';

export interface OffcanvasProps {
  /** Whether the offcanvas is open */
  isOpen: boolean;
  /** Callback when offcanvas should close */
  onClose: () => void;
  /** Placement of the offcanvas */
  placement?: 'start' | 'end' | 'top' | 'bottom';
  /** Title for the header */
  title?: React.ReactNode;
  /** Show backdrop */
  backdrop?: boolean | 'static';
  /** Allow scrolling body when open */
  scroll?: boolean;
  /** Enable keyboard (Escape) to close */
  keyboard?: boolean;
  /** Additional CSS classes */
  className?: string;
  /** Header CSS classes */
  headerClassName?: string;
  /** Body CSS classes */
  bodyClassName?: string;
  /** Children content */
  children?: React.ReactNode;
}

export const Offcanvas: React.FC<OffcanvasProps> = ({
  isOpen,
  onClose,
  placement = 'start',
  title,
  backdrop = true,
  scroll = false,
  keyboard = true,
  className = '',
  headerClassName = '',
  bodyClassName = '',
  children,
}) => {
  const offcanvasRef = useRef<HTMLDivElement>(null);

  // Handle escape key
  useEffect(() => {
    if (!keyboard || !isOpen) return;

    const handleKeydown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        onClose();
      }
    };

    document.addEventListener('keydown', handleKeydown);
    return () => document.removeEventListener('keydown', handleKeydown);
  }, [keyboard, isOpen, onClose]);

  // Handle body scroll
  useEffect(() => {
    if (isOpen && !scroll) {
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = '';
    }

    return () => {
      document.body.style.overflow = '';
    };
  }, [isOpen, scroll]);

  // Handle backdrop click
  const handleBackdropClick = useCallback((e: React.MouseEvent) => {
    if (backdrop === 'static') return;
    if (e.target === e.currentTarget) {
      onClose();
    }
  }, [backdrop, onClose]);

  // Focus trap
  useEffect(() => {
    if (!isOpen) return;

    const offcanvas = offcanvasRef.current;
    if (!offcanvas) return;

    const focusableElements = offcanvas.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    const firstElement = focusableElements[0] as HTMLElement;
    const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement;

    const handleTab = (e: KeyboardEvent) => {
      if (e.key !== 'Tab') return;

      if (e.shiftKey) {
        if (document.activeElement === firstElement) {
          lastElement?.focus();
          e.preventDefault();
        }
      } else {
        if (document.activeElement === lastElement) {
          firstElement?.focus();
          e.preventDefault();
        }
      }
    };

    firstElement?.focus();
    document.addEventListener('keydown', handleTab);
    return () => document.removeEventListener('keydown', handleTab);
  }, [isOpen]);

  const classes = [
    'll-offcanvas',
    `ll-offcanvas-${placement}`,
    isOpen && 'll-offcanvas-show',
    className,
  ].filter(Boolean).join(' ');

  if (!isOpen && !backdrop) return null;

  return (
    <>
      {/* Backdrop */}
      {backdrop && (
        <div
          className={`ll-offcanvas-backdrop ${isOpen ? 'll-offcanvas-backdrop-show' : ''}`}
          onClick={handleBackdropClick}
        />
      )}

      {/* Offcanvas */}
      <div
        ref={offcanvasRef}
        className={classes}
        tabIndex={-1}
        role="dialog"
        aria-modal="true"
        aria-labelledby={title ? 'll-offcanvas-title' : undefined}
      >
        {/* Header */}
        {title && (
          <div className={`ll-offcanvas-header ${headerClassName}`}>
            <h5 className="ll-offcanvas-title" id="ll-offcanvas-title">
              {title}
            </h5>
            <button
              type="button"
              className="ll-offcanvas-close"
              onClick={onClose}
              aria-label="Close"
            >
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
        )}

        {/* Body */}
        <div className={`ll-offcanvas-body ${bodyClassName}`}>
          {children}
        </div>
      </div>
    </>
  );
};

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

export const OffcanvasHeader: React.FC<OffcanvasHeaderProps> = ({
  className = '',
  children,
}) => (
  <div className={`ll-offcanvas-header ${className}`}>
    {children}
  </div>
);

export interface OffcanvasTitleProps {
  as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
  className?: string;
  children?: React.ReactNode;
}

export const OffcanvasTitle: React.FC<OffcanvasTitleProps> = ({
  as: Component = 'h5',
  className = '',
  children,
}) => (
  <Component className={`ll-offcanvas-title ${className}`}>
    {children}
  </Component>
);

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

export const OffcanvasBody: React.FC<OffcanvasBodyProps> = ({
  className = '',
  children,
}) => (
  <div className={`ll-offcanvas-body ${className}`}>
    {children}
  </div>
);
