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

interface Props {
  position: 'left' | 'right' | 'bottom';
  defaultSize?: number;
  minSize?: number;
  maxSize?: number;
  collapsed?: boolean;
  onCollapsedChange?: (collapsed: boolean) => void;
  onResize?: (size: number) => void;
  leftPanelSize?: number;
  rightPanelSize?: number;
  leftPanelCollapsed?: boolean;
  rightPanelCollapsed?: boolean;
  children: React.ReactNode;
}

const ResizablePanel: React.FC<Props> = ({
  position,
  defaultSize = 250,
  minSize = 100,
  maxSize = 800,
  collapsed: controlledCollapsed,
  onCollapsedChange,
  onResize,
  leftPanelSize = 250,
  rightPanelSize = 300,
  leftPanelCollapsed = false,
  rightPanelCollapsed = false,
  children,
}) => {
  const [internalCollapsed, setInternalCollapsed] = useState(false);
  const [size, setSize] = useState(defaultSize);
  const [isResizing, setIsResizing] = useState(false);
  const panelRef = useRef<HTMLDivElement>(null);
  const startPosRef = useRef(0);
  const startSizeRef = useRef(0);
  const resizeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const isCollapsed = controlledCollapsed !== undefined ? controlledCollapsed : internalCollapsed;

  // Load saved size and collapsed state
  useEffect(() => {
    try {
      const savedSize = localStorage.getItem(`panel-size-${position}`);
      const savedCollapsed = localStorage.getItem(`panel-collapsed-${position}`);
      
      if (savedSize) {
        const parsedSize = parseInt(savedSize, 10);
        if (!isNaN(parsedSize) && parsedSize >= minSize && parsedSize <= maxSize) {
          setSize(parsedSize);
        }
      }
      
      if (savedCollapsed === 'true' && controlledCollapsed === undefined) {
        setInternalCollapsed(true);
        onCollapsedChange?.(true);
      }
    } catch (error) {
      console.warn('Failed to load panel state from localStorage:', error);
    }
  }, [position, minSize, maxSize, controlledCollapsed, onCollapsedChange]);

  // Debounced save function
  const savePanelState = useCallback(() => {
    if (resizeTimeoutRef.current) {
      clearTimeout(resizeTimeoutRef.current);
    }
    resizeTimeoutRef.current = setTimeout(() => {
      try {
        localStorage.setItem(`panel-size-${position}`, size.toString());
        localStorage.setItem(`panel-collapsed-${position}`, isCollapsed.toString());
      } catch (error) {
        console.warn('Failed to save panel state to localStorage:', error);
      }
    }, 300);
  }, [position, size, isCollapsed]);

  // Save on size or collapsed change
  useEffect(() => {
    savePanelState();
    return () => {
      if (resizeTimeoutRef.current) {
        clearTimeout(resizeTimeoutRef.current);
      }
    };
  }, [savePanelState]);

  const toggleCollapse = useCallback(() => {
    const newCollapsed = !isCollapsed;
    if (controlledCollapsed === undefined) {
      setInternalCollapsed(newCollapsed);
    }
    onCollapsedChange?.(newCollapsed);
  }, [isCollapsed, controlledCollapsed, onCollapsedChange]);

  const getToggleIcon = useCallback((): string => {
    if (isCollapsed) {
      if (position === 'left') return 'fas fa-chevron-right';
      if (position === 'right') return 'fas fa-chevron-left';
      return 'fas fa-chevron-up';
    } else {
      if (position === 'left') return 'fas fa-chevron-left';
      if (position === 'right') return 'fas fa-chevron-right';
      return 'fas fa-chevron-down';
    }
  }, [isCollapsed, position]);

  const handleResize = useCallback((e: MouseEvent | TouchEvent) => {
    if (!isResizing) return;
    e.preventDefault();
    
    const currentPos = 'touches' in e 
      ? e.touches[0][position === 'bottom' ? 'clientY' : 'clientX']
      : (e as MouseEvent)[position === 'bottom' ? 'clientY' : 'clientX'];
    
    const delta = position === 'left' 
      ? currentPos - startPosRef.current
      : position === 'right'
      ? startPosRef.current - currentPos
      : startPosRef.current - currentPos;
    
    let newSize = startSizeRef.current + delta;
    newSize = Math.max(minSize, Math.min(maxSize, newSize));
    
    setSize(newSize);
    onResize?.(newSize);
  }, [isResizing, position, minSize, maxSize, onResize]);

  const stopResize = useCallback(() => {
    setIsResizing(false);
    document.removeEventListener('mousemove', handleResize);
    document.removeEventListener('touchmove', handleResize);
    document.body.style.cursor = '';
    document.body.style.userSelect = '';
    document.body.style.pointerEvents = '';
  }, [handleResize]);

  const startResize = useCallback((e: React.MouseEvent | React.TouchEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setIsResizing(true);
    
    const clientPos = 'touches' in e ? e.touches[0].clientY : (e as React.MouseEvent).clientY;
    const clientX = 'touches' in e ? e.touches[0].clientX : (e as React.MouseEvent).clientX;
    
    startPosRef.current = position === 'bottom' ? clientPos : clientX;
    startSizeRef.current = size;
    
    document.addEventListener('mousemove', handleResize, { passive: false });
    document.addEventListener('mouseup', stopResize, { once: true });
    document.addEventListener('touchmove', handleResize, { passive: false });
    document.addEventListener('touchend', stopResize, { once: true });
    
    document.body.style.cursor = position === 'bottom' ? 'row-resize' : 'col-resize';
    document.body.style.userSelect = 'none';
    document.body.style.pointerEvents = 'none';
  }, [position, size, handleResize, stopResize]);

  const handleKeyboardResize = useCallback((e: React.KeyboardEvent) => {
    if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) return;
    
    e.preventDefault();
    const step = e.shiftKey ? 10 : 1;
    let newSize = size;
    
    if (position === 'left') {
      if (e.key === 'ArrowRight') newSize += step;
      if (e.key === 'ArrowLeft') newSize -= step;
    } else if (position === 'right') {
      if (e.key === 'ArrowLeft') newSize += step;
      if (e.key === 'ArrowRight') newSize -= step;
    } else {
      if (e.key === 'ArrowUp') newSize += step;
      if (e.key === 'ArrowDown') newSize -= step;
    }
    
    newSize = Math.max(minSize, Math.min(maxSize, newSize));
    setSize(newSize);
    onResize?.(newSize);
  }, [position, size, minSize, maxSize, onResize]);

  const panelStyle: React.CSSProperties = useMemo(() => {
    const baseStyle: React.CSSProperties = {
      position: 'fixed',
      background: 'white',
      boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)',
      transition: 'width 0.2s ease, height 0.2s ease, left 0.2s ease, right 0.2s ease',
      overflow: 'hidden',
      display: 'flex',
      flexDirection: 'column',
      zIndex: 100,
      willChange: 'width, height',
    };

    if (position === 'left') {
      return {
        ...baseStyle,
        left: 0,
        top: '64px',
        bottom: '15px',
        width: isCollapsed ? '0px' : `${size}px`,
        height: 'auto',
      };
    } else if (position === 'right') {
      return {
        ...baseStyle,
        right: 0,
        top: '64px',
        bottom: '15px',
        width: isCollapsed ? '0px' : `${size}px`,
        height: 'auto',
      };
    } else {
      // Bottom panel: sandwiched between left and right panels
      const left = leftPanelCollapsed ? 0 : leftPanelSize;
      const right = rightPanelCollapsed ? 0 : rightPanelSize;
      
      return {
        ...baseStyle,
        left: `${left}px`,
        right: `${right}px`,
        top: '64px',
        bottom: '15px',
        width: 'auto',
        height: isCollapsed ? '0px' : `${size}px`,
      };
    }
  }, [position, isCollapsed, size, leftPanelSize, rightPanelSize, leftPanelCollapsed, rightPanelCollapsed]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      stopResize();
      if (resizeTimeoutRef.current) {
        clearTimeout(resizeTimeoutRef.current);
      }
    };
  }, [stopResize]);

  return (
    <div
      ref={panelRef}
      className={`resizable-panel resizable-panel-${position} ${isCollapsed ? 'collapsed' : ''}`}
      style={panelStyle}
      aria-label={`${position} panel`}
    >
      {!isCollapsed && (
        <div
          className={`resize-handle resize-handle-${position}`}
          onMouseDown={startResize}
          onTouchStart={startResize}
          onKeyDown={handleKeyboardResize}
          aria-label={`Resize ${position} panel`}
          role="separator"
          aria-orientation={position === 'bottom' ? 'horizontal' : 'vertical'}
          tabIndex={0}
        >
          <div className="resize-handle-indicator"></div>
        </div>
      )}
      
      <button
        className={`collapse-toggle collapse-toggle-${position}`}
        onClick={toggleCollapse}
        title={isCollapsed ? `Expand ${position} panel` : `Collapse ${position} panel`}
        aria-label={isCollapsed ? `Expand ${position} panel` : `Collapse ${position} panel`}
        type="button"
      >
        <span className="sr-only">{isCollapsed ? `Expand ${position} panel` : `Collapse ${position} panel`}</span>
        <i className={getToggleIcon()} aria-hidden="true"></i>
      </button>
      
      {!isCollapsed && (
        <div className="panel-content">
          {children}
        </div>
      )}
    </div>
  );
};

export default ResizablePanel;
