/**
 * PanelContainer - Orchestrates all floating panels in the canvas view
 * 
 * This component renders floating panels (Introspection, Validation, Error, Results)
 * in a portal, positioned absolutely within the canvas area.
 * 
 * Features:
 * - Draggable panels
 * - Z-index management (click to bring to front)
 * - Keyboard shortcuts (Escape to close all)
 * - Position persistence via usePanelStore
 */

import { useState, useCallback, useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import {
  usePanelStore,
  useIntrospectionPanel,
  useValidationPanel,
  useErrorPanel,
  useResultsPanel,
  PanelPosition,
} from '../../../hooks/usePanelStore';
import { FloatingIntrospectionPanel } from './FloatingIntrospectionPanel';
import { FloatingValidationPanel } from './ValidationPanel';
import { ErrorPanel } from './ErrorPanel';
import { ResultsPanel } from './ResultsPanel';

interface PanelContainerProps {
  /** Container element to render panels into (defaults to document.body) */
  container?: HTMLElement;
  /** Callback when retry is requested from error panel */
  onRetry?: (trial?: number) => void;
  /** Callback when skip trial is requested */
  onSkipTrial?: (trial: number) => void;
}

type PanelName = 'introspection' | 'validation' | 'error' | 'results';

export function PanelContainer({ container, onRetry, onSkipTrial }: PanelContainerProps) {
  const { closePanel, setPanelPosition, closeAllPanels } = usePanelStore();
  
  const introspectionPanel = useIntrospectionPanel();
  const validationPanel = useValidationPanel();
  const errorPanel = useErrorPanel();
  const resultsPanel = useResultsPanel();

  // Track which panel is on top (for z-index)
  const [topPanel, setTopPanel] = useState<PanelName | null>(null);
  
  // Dragging state
  const [dragging, setDragging] = useState<{ panel: PanelName; offset: { x: number; y: number } } | null>(null);
  const dragRef = useRef<{ panel: PanelName; offset: { x: number; y: number } } | null>(null);

  // Escape key to close all panels
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        closeAllPanels();
      }
    };
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [closeAllPanels]);

  // Mouse move handler for dragging
  useEffect(() => {
    const handleMouseMove = (e: MouseEvent) => {
      if (!dragRef.current) return;
      
      const { panel, offset } = dragRef.current;
      const newPosition: PanelPosition = {
        x: e.clientX - offset.x,
        y: e.clientY - offset.y,
      };
      
      // Clamp to viewport
      newPosition.x = Math.max(0, Math.min(window.innerWidth - 100, newPosition.x));
      newPosition.y = Math.max(0, Math.min(window.innerHeight - 50, newPosition.y));
      
      setPanelPosition(panel, newPosition);
    };

    const handleMouseUp = () => {
      dragRef.current = null;
      setDragging(null);
    };

    if (dragging) {
      window.addEventListener('mousemove', handleMouseMove);
      window.addEventListener('mouseup', handleMouseUp);
    }

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('mouseup', handleMouseUp);
    };
  }, [dragging, setPanelPosition]);

  // Start dragging a panel
  const handleDragStart = useCallback((panel: PanelName, e: React.MouseEvent, position: PanelPosition) => {
    const offset = {
      x: e.clientX - position.x,
      y: e.clientY - position.y,
    };
    dragRef.current = { panel, offset };
    setDragging({ panel, offset });
    setTopPanel(panel);
  }, []);

  // Click to bring panel to front
  const handlePanelClick = useCallback((panel: PanelName) => {
    setTopPanel(panel);
  }, []);

  // Get z-index for a panel
  const getZIndex = (panel: PanelName) => {
    const baseZ = 100;
    if (panel === topPanel) return baseZ + 10;
    return baseZ;
  };

  // Render a draggable wrapper
  const renderDraggable = (
    panel: PanelName,
    position: PanelPosition,
    isOpen: boolean,
    children: React.ReactNode
  ) => {
    if (!isOpen) return null;

    return (
      <div
        key={panel}
        className="fixed select-none"
        style={{
          left: position.x,
          top: position.y,
          zIndex: getZIndex(panel),
          cursor: dragging?.panel === panel ? 'grabbing' : 'default',
        }}
        onClick={() => handlePanelClick(panel)}
      >
        {/* Drag handle - the header area */}
        <div
          className="absolute top-0 left-0 right-0 h-12 cursor-grab active:cursor-grabbing"
          onMouseDown={(e) => handleDragStart(panel, e, position)}
          style={{ zIndex: 1 }}
        />
        {/* Panel content */}
        <div className="relative" style={{ zIndex: 0 }}>
          {children}
        </div>
      </div>
    );
  };

  // Determine what to render
  const panels = (
    <>
      {/* Introspection Panel */}
      {renderDraggable(
        'introspection',
        introspectionPanel.position || { x: 100, y: 100 },
        introspectionPanel.open,
        <FloatingIntrospectionPanel onClose={() => closePanel('introspection')} />
      )}

      {/* Validation Panel */}
      {renderDraggable(
        'validation',
        validationPanel.position || { x: 150, y: 150 },
        validationPanel.open,
        <FloatingValidationPanel onClose={() => closePanel('validation')} />
      )}

      {/* Error Panel */}
      {renderDraggable(
        'error',
        errorPanel.position || { x: 200, y: 100 },
        errorPanel.open,
        <ErrorPanel 
          onClose={() => closePanel('error')} 
          onRetry={onRetry}
          onSkipTrial={onSkipTrial}
        />
      )}

      {/* Results Panel */}
      {renderDraggable(
        'results',
        resultsPanel.position || { x: 250, y: 150 },
        resultsPanel.open,
        <ResultsPanel onClose={() => closePanel('results')} />
      )}
    </>
  );

  // Use portal if container specified, otherwise render in place
  if (container) {
    return createPortal(panels, container);
  }

  return panels;
}

export default PanelContainer;
