/**
 * ResizablePanel — a flex panel with drag-to-resize handle.
 * No external dependencies; uses React + mouse events only.
 *
 * The panel renders an outer fixed-width container with the resize handle
 * positioned absolutely on the right edge (z-index above scrollbars).
 * Scrollable content goes into an inner div so that the scrollbar never
 * overlaps the drag handle.
 *
 * Performance: during drag, width is applied directly to the DOM via ref —
 * no React re-render happens until mouseup. This prevents janky resizing
 * when panel children (mail list, mail detail) are expensive to render.
 */

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

export interface ResizablePanelProps {
  /** Initial width in pixels (only used when resizable=true) */
  initialWidth?: number;
  /** Minimum width in pixels */
  minWidth?: number;
  /** Maximum width in pixels */
  maxWidth?: number;
  /** Panel content */
  children: React.ReactNode;
  /** Extra className for the panel container */
  className?: string;
  /** When false, panel becomes flex-1 with no drag handle */
  resizable?: boolean;
  /** Which side the drag handle is on ('right' default, 'left' for right-aligned panels) */
  handleSide?: 'left' | 'right';
  /** testid forwarded to the container div */
  'data-testid'?: string;
}

export function ResizablePanel({
  initialWidth = 224,
  minWidth = 150,
  maxWidth = 600,
  children,
  className,
  resizable = true,
  handleSide = 'right',
  ...rest
}: ResizablePanelProps) {
  const [width, setWidth] = useState(initialWidth);
  const isResizing = useRef(false);
  const startX = useRef(0);
  const startWidth = useRef(0);
  const panelRef = useRef<HTMLDivElement>(null);
  const contentRef = useRef<HTMLDivElement>(null);

  const handleMouseDown = useCallback(
    (e: React.MouseEvent) => {
      e.preventDefault();
      e.stopPropagation();
      isResizing.current = true;
      startX.current = e.clientX;
      startWidth.current = width;
      document.body.style.cursor = 'col-resize';
      document.body.style.userSelect = 'none';
      // Disable pointer events on content during drag to prevent reflows
      if (contentRef.current) {
        contentRef.current.style.pointerEvents = 'none';
      }
    },
    [width],
  );

  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (!isResizing.current) return;
      const delta = e.clientX - startX.current;
      const adjustedDelta = handleSide === 'left' ? -delta : delta;
      const newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth.current + adjustedDelta));
      // Apply width directly to DOM — no React re-render during drag
      if (panelRef.current) {
        panelRef.current.style.width = `${newWidth}px`;
      }
    };

    const handleMouseUp = () => {
      if (isResizing.current) {
        isResizing.current = false;
        document.body.style.cursor = '';
        document.body.style.userSelect = '';
        if (contentRef.current) {
          contentRef.current.style.pointerEvents = '';
        }
        // Sync final width to React state (single re-render on mouseup)
        if (panelRef.current) {
          const finalWidth = panelRef.current.style.width;
          if (finalWidth) {
            setWidth(parseInt(finalWidth));
          }
        }
      }
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);

    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, [minWidth, maxWidth, handleSide]);

  return (
    <div
      ref={panelRef}
      className={clsx(
        resizable ? 'relative flex-shrink-0 flex flex-col' : 'relative flex-1 flex flex-col',
        className,
      )}
      style={resizable ? { width: `${width}px` } : undefined}
      data-testid={rest['data-testid']}
    >
      {/* Inner scrollable content area — scrollbar stays inside, never overlaps handle */}
      <div
        ref={contentRef}
        className="flex-1 overflow-y-auto overflow-x-hidden min-h-0"
        style={{
          contain: 'strict',
        }}
      >
        {children}
      </div>
      {resizable && (
        <div
          className={clsx(
            'absolute top-0 h-full w-1.5 cursor-col-resize bg-transparent hover:bg-primary-300 active:bg-primary-400 transition-colors z-50 pointer-events-auto',
            handleSide === 'left' ? 'left-0' : 'right-0',
          )}
          style={handleSide === 'left' ? { marginLeft: '-3px' } : { marginRight: '-3px' }}
          onMouseDown={handleMouseDown}
          data-testid="resize-handle"
          role="separator"
          aria-orientation="vertical"
        />
      )}
    </div>
  );
}
