import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { FiChevronRight, FiChevronLeft, FiGitBranch, FiLock, FiUnlock, FiInfo, FiRefreshCw } from 'react-icons/fi';
import DocumentationButton from './DocumentationButton';
import InfoPopup from './InfoPopup';
import type { InfoItem } from './InfoPopup';
import MultiSelectionPanel from './MultiSelectionPanel';
import NodePropertiesPanel from './NodePropertiesPanel';
import EdgePropertiesPanel from './EdgePropertiesPanel';
import { useStore, Node, Edge } from '../store/store';
import { PANEL_DIMENSIONS } from '../constants/dimensions';
import { t } from '../utils/translation';
import { getComponentIcon, getComponentLabel, getComponentTypeName } from '../utils/componentUtils';
import { useConfigurationLoader } from '../hooks/useConfigurationLoader';
import { useReplayLoader } from '../hooks/useReplayLoader';
import type { ReplayEntry } from '../hooks/useReplayLoader';
import { usePanelResize } from '../hooks/usePanelResize';
import { useDebouncedField } from '../hooks/useDebouncedField';
import type { Settings } from '../types/settings';
import { hasPermission } from '../utils/permissions';

interface PropertyPanelProps {
  node?: Node | null;
  edge?: Edge | null;
  selectedNodes?: Node[];
  selectedEdges?: Edge[];
  onConfigurationChange?: (nodeId: string, configuration: Record<string, any>) => void;
  onEdgeConfigurationChange?: (edgeId: string, configuration: Record<string, any> | null) => void;
  onNodeUpdate?: (nodeId: string, data: any) => void;
  onEdgeUpdate?: (edgeId: string, data: any) => void;
  onDeleteSelected?: () => void;
  isLocked?: boolean;
  settings?: Settings;
  isReplayMode?: boolean;
  onReplayEntriesLoaded?: (entries: ReplayEntry[]) => void;
}

const PropertyPanel: React.FC<PropertyPanelProps> = ({
  node,
  edge,
  selectedNodes = [],
  selectedEdges = [],
  onConfigurationChange,
  onEdgeConfigurationChange,
  onNodeUpdate,
  onEdgeUpdate,
  onDeleteSelected,
  isLocked = false,
  settings = {},
  isReplayMode = false,
  onReplayEntriesLoaded
}) => {
  const {
    panelWidth,
    panelIsResizing,
    setPanelWidth,
    setPanelResizing,
    propertyPanelCollapsed,
    togglePropertyPanelCollapse,
    components
  } = useStore();

  // Look up the documentation URL from the component definition
  const documentationUrl = useMemo(() => {
    if (!node?.data?.plugin || !components) return null;
    const component = components.find(c => c.plugin === node.data.plugin);
    return component?.documentationUrl || node.data?.documentationUrl || null;
  }, [node?.data?.plugin, node?.data?.documentationUrl, components]);
  
  // Use extracted hooks for cleaner architecture
  const { configurationForm, loading } = useConfigurationLoader({
    node,
    edge,
    settings,
    isReplayMode,
  });

  // Replay loader for event nodes — callback fires inside the hook, no useEffect bridge needed
  const { loading: replayLoading, error: replayError, loadReplayData } = useReplayLoader({
    settings,
    onEntriesLoaded: onReplayEntriesLoaded,
  });
  const isStartNode = node?.type === 'start';
  const isNewModel = !!settings.modeler_api?.isNew;
  const canReplay = hasPermission(settings, 'replay');
  const hasReplayUrl = !isNewModel && !!settings.modeler_api?.replay_url && canReplay;

  const handleLoadReplay = useCallback(() => {
    if (node && isStartNode && hasReplayUrl) {
      loadReplayData(node.id);
    }
  }, [node, isStartNode, hasReplayUrl, loadReplayData]);

  const { startResize } = usePanelResize({
    panelWidth,
    setPanelWidth,
    setPanelResizing: setPanelResizing,
    direction: 'left',
  });

  // Check if we have multiple selections
  const hasMultipleSelection: boolean = selectedNodes.length > 1 || selectedEdges.length > 1 ||
                               (selectedNodes.length > 0 && selectedEdges.length > 0);

  // Debounced field handlers for node label
  const handleNodeLabelChange = useCallback((value: string) => {
    if (node && onConfigurationChange && !isLocked && !node.data?.locked) {
      onConfigurationChange(node.id, { _componentLabel: value });
    }
  }, [node, onConfigurationChange, isLocked]);

  const nodeLabelField = useDebouncedField({
    initialValue: node?.data?.label || '',
    onDebouncedChange: handleNodeLabelChange,
    disabled: isLocked || node?.data?.locked,
  });

  // Debounced field handlers for node annotation
  const handleNodeAnnotationChange = useCallback((value: string) => {
    if (node && onNodeUpdate && !isLocked && !node.data?.locked) {
      onNodeUpdate(node.id, { ...node.data, annotation: value });
    }
  }, [node, onNodeUpdate, isLocked]);

  const nodeAnnotationField = useDebouncedField({
    initialValue: node?.data?.annotation || '',
    onDebouncedChange: handleNodeAnnotationChange,
    disabled: isLocked || node?.data?.locked,
  });

  // Debounced field handlers for edge condition label
  const edgeRef = React.useRef(edge);
  edgeRef.current = edge;
  
  const handleEdgeLabelChange = useCallback((value: string) => {
    const currentEdge = edgeRef.current;
    if (currentEdge && onEdgeConfigurationChange && !isLocked && !currentEdge.data?.locked) {
      onEdgeConfigurationChange(currentEdge.id, {
        _conditionLabel: value,
      });
    }
  }, [onEdgeConfigurationChange, isLocked]);

  const edgeLabelField = useDebouncedField({
    initialValue: edge?.data?.conditionLabel || '',
    onDebouncedChange: handleEdgeLabelChange,
    disabled: isLocked || edge?.data?.locked,
  });

  // Debounced field handlers for edge annotation
  const handleEdgeAnnotationChange = useCallback((value: string) => {
    if (edge && onEdgeUpdate && !isLocked && !edge.data?.locked) {
      onEdgeUpdate(edge.id, { ...edge.data, annotation: value });
    }
  }, [edge, onEdgeUpdate, isLocked]);

  const edgeAnnotationField = useDebouncedField({
    initialValue: edge?.data?.annotation || '',
    onDebouncedChange: handleEdgeAnnotationChange,
    disabled: isLocked || edge?.data?.locked,
  });

  // Reset field values when node/edge changes
  useEffect(() => {
    if (node) {
      nodeLabelField.setValue(node.data?.label || '');
      nodeAnnotationField.setValue(node.data?.annotation || '');
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [node?.id]);

  useEffect(() => {
    if (edge) {
      edgeLabelField.setValue(edge.data?.conditionLabel || '');
      edgeAnnotationField.setValue(edge.data?.annotation || '');
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [edge?.id]);

  // Handle click on collapsed panel to expand
  const handlePanelClick = useCallback((e: React.MouseEvent) => {
    if (propertyPanelCollapsed) {
      e.stopPropagation();
      togglePropertyPanelCollapse();
    }
  }, [propertyPanelCollapsed, togglePropertyPanelCollapse]);

  // Info popup state
  const [showInfoPopup, setShowInfoPopup] = useState(false);

  // Build metadata items for the info popup
  const infoItems: InfoItem[] = useMemo(() => {
    if (node) {
      return [
        { label: t('ID'), value: node.id, show: true },
        { label: t('Type'), value: node.type || '', show: true },
        { label: t('Plugin ID'), value: node.data?.plugin || '', show: !!node.data?.plugin },
      ];
    }
    if (edge) {
      return [
        { label: t('Connection Type'), value: t('Edge'), show: true },
        { label: t('Condition Plugin'), value: edge.data?.condition || '', show: !!edge.data?.condition },
        { label: t('Edge ID'), value: edge.id, show: true },
        { label: t('Source'), value: edge.source, show: true },
        { label: t('Target'), value: edge.target, show: true },
      ];
    }
    return [];
  }, [node, edge]);

  // Close info popup when selection changes
  useEffect(() => {
    setShowInfoPopup(false);
  }, [node?.id, edge?.id]);

  return (
    <div
      className={`workflow-property-panel ${panelIsResizing ? 'resizing' : ''} ${propertyPanelCollapsed ? 'collapsed' : ''}`}
      style={{ width: propertyPanelCollapsed ? `${PANEL_DIMENSIONS.PROPERTY_PANEL.COLLAPSED_WIDTH}px` : `${panelWidth}px` }}
      onClick={handlePanelClick}
      title={propertyPanelCollapsed ? t('Click to expand') : undefined}
    >
      <div
        className="resize-handle"
        onMouseDown={startResize}
        title={t('Drag to resize')}
      />
      <button
        className="panel-collapse-widget"
        onClick={togglePropertyPanelCollapse}
        title={propertyPanelCollapsed ? t('Expand panel') : t('Collapse panel')}
        aria-label={propertyPanelCollapsed ? t('Expand panel') : t('Collapse panel')}
      >
        <span className="collapse-icon">
          {propertyPanelCollapsed ? <FiChevronLeft /> : <FiChevronRight />}
        </span>
      </button>
      {propertyPanelCollapsed && (
        <div className="panel-collapsed-label">
          <span>{t('Properties')}</span>
        </div>
      )}
      <div className="panel-content">

      <div className="panel-header">
        {hasMultipleSelection ? (
          <h3>{t('Multiple Selection')}</h3>
        ) : node || edge ? (
          <div className="component-header">
            <div className="component-info">
              {node ? getComponentIcon(node.type || 'element') : <FiGitBranch />}
              <span className="component-type">
                {node ? getComponentTypeName(node.type || 'element') : getComponentLabel('link')}
              </span>
            </div>
            <div className="header-actions">
              {(loading || replayLoading) && <div className="loading-indicator">{t('Loading...')}</div>}
              {node && isStartNode && hasReplayUrl && (
                <button
                  className={`header-replay-btn ${replayLoading ? 'loading' : ''}`}
                  aria-label={t('Load replay data')}
                  onClick={handleLoadReplay}
                  disabled={replayLoading}
                  title={replayError || t('Load replay data')}
                >
                  <FiRefreshCw className={replayLoading ? 'spinning' : ''} />
                </button>
              )}
              {node && documentationUrl && (
                <DocumentationButton
                  url={documentationUrl}
                  title={node.data?.label || t('Component')}
                  className="header-documentation-btn"
                  size={16}
                />
              )}
              <button
                className="header-info-btn"
                aria-label={t('Show metadata')}
                onClick={() => setShowInfoPopup(prev => !prev)}
                title={t('Show metadata')}
              >
                <FiInfo />
              </button>
              <button
                className={`header-lock-btn ${(node?.data?.locked || edge?.data?.locked) ? 'locked' : ''}`}
                aria-label={(node?.data?.locked || edge?.data?.locked) ? t('Unlock') : t('Lock')}
                onClick={() => {
                  if (node && onConfigurationChange && !isLocked) {
                    onConfigurationChange(node.id, {
                      _componentLocked: !node.data?.locked
                    });
                  } else if (edge && onEdgeConfigurationChange && !isLocked) {
                    onEdgeConfigurationChange(edge.id, {
                      edgeLocked: !edge.data?.locked,
                      ...(edge.data?.conditionConfiguration || {})
                    });
                  }
                }}
                disabled={isLocked}
                title={(node?.data?.locked || edge?.data?.locked) ? t('Unlock') : t('Lock')}
              >
                {(node?.data?.locked || edge?.data?.locked) ? <FiLock /> : <FiUnlock />}
              </button>
            </div>
          </div>
        ) : (
          <div className="empty-header"></div>
        )}
      </div>

      {showInfoPopup && infoItems.length > 0 && (
        <InfoPopup items={infoItems} onClose={() => setShowInfoPopup(false)} />
      )}

      {hasMultipleSelection ? (
        <MultiSelectionPanel
          selectedNodes={selectedNodes}
          selectedEdges={selectedEdges}
          onConfigurationChange={onConfigurationChange}
          onEdgeConfigurationChange={onEdgeConfigurationChange}
          onDeleteSelected={onDeleteSelected}
          isLocked={isLocked}
        />
      ) : !node && !edge ? (
        <div className="panel-content empty">
          <p>{t('Select a component or connection to view its properties')}</p>
        </div>
      ) : node ? (
        <NodePropertiesPanel
          node={node}
          configurationForm={configurationForm}
          onConfigurationChange={onConfigurationChange}
          onNodeUpdate={onNodeUpdate}
          isLocked={isLocked}
          nodeLabelField={nodeLabelField}
          nodeAnnotationField={nodeAnnotationField}
        />
      ) : edge ? (
        <EdgePropertiesPanel
          edge={edge}
          configurationForm={configurationForm}
          onEdgeConfigurationChange={onEdgeConfigurationChange}
          onEdgeUpdate={onEdgeUpdate}
          isLocked={isLocked}
          edgeLabelField={edgeLabelField}
          edgeAnnotationField={edgeAnnotationField}
        />
      ) : null}
      </div>
    </div>
  );
};

export default PropertyPanel;
