import React, { useState, useMemo, useCallback } from 'react';
import { useStore, Component } from '../store/store';
import { PANEL_DIMENSIONS } from '../constants/dimensions';
import { FiSearch, FiZap, FiActivity, FiHelpCircle, FiGitBranch, FiInfo, FiFilter, FiChevronDown, FiChevronRight, FiChevronLeft, FiLink, FiCpu, FiLayers, FiStar } from 'react-icons/fi';
import classNames from 'classnames';
import DocumentationButton from './DocumentationButton';
import { t } from '../utils/translation';

interface ComponentPanelProps {
  ownerComponents?: Record<string, any[]>;
  onComponentDrag?: (event: React.DragEvent, plugin: any) => void;
  onComponentDragEnd?: () => void;
  onConditionDragStart?: () => void;
  onConditionDragEnd?: () => void;
  onComponentDragStart?: (component: any) => void;
  collapsed?: boolean;
  width?: number;
  onResize?: (width: number) => void;
  onToggleCollapse?: () => void;
  activeTab?: 'components' | 'replay';
  onTabChange?: (tab: 'components' | 'replay') => void;
  forceActiveTab?: 'components' | 'replay' | null;
  replayData?: any[];
  currentReplayStep?: number;
  isReplayMode?: boolean;
  onReplayStepSelect?: (step: number) => void;
  onToggleReplay?: () => void;
  nodes?: any[];
  edges?: any[];
  searchTerm?: string;
  onSearchChange?: (term: string) => void;
  onHighlight?: (result: any) => void;
  onFocus?: (data: any) => void;
}

interface ComponentTypeConfig {
  label: string;
  icon: React.ComponentType<any>;
}

const ComponentPanel: React.FC<ComponentPanelProps> = ({
  ownerComponents: _ownerComponents,
  onComponentDrag,
  onComponentDragEnd,
  onConditionDragStart,
  onConditionDragEnd,
  onComponentDragStart,
  collapsed: _collapsed,
  width: _width,
  onResize: _onResize,
  onToggleCollapse: _onToggleCollapse,
  activeTab: _activeTab,
  onTabChange: _onTabChange,
  forceActiveTab: _forceActiveTab,
  replayData: _replayData,
  currentReplayStep: _currentReplayStep,
  isReplayMode: _isReplayMode,
  onReplayStepSelect: _onReplayStepSelect,
  onToggleReplay: _onToggleReplay,
  nodes: _nodes,
  edges: _edges,
  searchTerm,
  onSearchChange: _onSearchChange,
  onHighlight: _onHighlight,
  onFocus: _onFocus
}) => {
  const components = useStore((state) => state.components);
  const favoriteComponents = useStore((state) => state.favoriteComponents);
  const componentPanelWidth = useStore((state) => state.componentPanelWidth);
  const componentPanelIsResizing = useStore((state) => state.componentPanelIsResizing);
  const setComponentPanelWidth = useStore((state) => state.setComponentPanelWidth);
  const setComponentPanelResizing = useStore((state) => state.setComponentPanelResizing);
  const componentPanelCollapsed = useStore((state) => state.componentPanelCollapsed);
  const toggleComponentPanelCollapse = useStore((state) => state.toggleComponentPanelCollapse);

  const [localSearchTerm, setLocalSearchTerm] = useState(searchTerm || '');
  const [selectedType, setSelectedType] = useState<string | null>(null);
  const [selectedProviders, setSelectedProviders] = useState(new Set<string>());
  const [filterExpanded, setFilterExpanded] = useState(false);

  // Get available component types (types that have at least one component)
  const availableTypes = useMemo(() => {
    const typeMap: Record<string, number> = {};
    if (Array.isArray(components)) {
      components.forEach(comp => {
        if (comp.category) {
          if (!typeMap[comp.category]) {
            typeMap[comp.category] = 0;
          }
          typeMap[comp.category]++;
        }
      });
    }
    return typeMap;
  }, [components]);

  // Get available providers for the selected type
  const availableProviders = useMemo(() => {
    if (!selectedType || !Array.isArray(components)) return [];
    const providers = new Set<string>();
    components
      .filter(comp => comp.category === selectedType)
      .forEach(comp => {
        if (comp.provider) {
          providers.add(comp.provider);
        }
      });
    return Array.from(providers).sort();
  }, [components, selectedType]);

  // Set initial selected type to first available type
  useMemo(() => {
    if (!selectedType && Object.keys(availableTypes).length > 0) {
      setSelectedType(Object.keys(availableTypes)[0]);
    }
  }, [availableTypes, selectedType]);

  // Get filtered count for each component type (after search and provider filters)
  const filteredCountsByType = useMemo(() => {
    const countMap: Record<string, number> = {};
    if (Array.isArray(components)) {
      Object.keys(availableTypes).forEach(typeId => {
        countMap[typeId] = components.filter(comp => {
          const matchesSearch = comp.label.toLowerCase().includes(localSearchTerm.toLowerCase()) ||
                               comp.plugin.toLowerCase().includes(localSearchTerm.toLowerCase());
          const matchesType = comp.category === typeId;
          const matchesProvider = selectedProviders.size === 0 || (comp.provider && selectedProviders.has(comp.provider));
          return matchesSearch && matchesType && matchesProvider;
        }).length;
      });
    }
    return countMap;
  }, [components, localSearchTerm, selectedProviders, availableTypes]);

  // Helper function to check if a component is a favorite
  const isFavorite = useCallback((component: Component): boolean => {
    if (!favoriteComponents || !component.componentType) return false;
    const favoritesForType = favoriteComponents[component.componentType];
    if (!favoritesForType || !Array.isArray(favoritesForType)) return false;
    return favoritesForType.includes(component.plugin);
  }, [favoriteComponents]);

  // Filter components by selected type, provider, and search term, then sort with favorites at top
  const filteredComponents = useMemo(() => {
    if (!selectedType || !Array.isArray(components)) return [];
    return components.filter(comp => {
      const matchesSearch = comp.label.toLowerCase().includes(localSearchTerm.toLowerCase()) ||
                           comp.plugin.toLowerCase().includes(localSearchTerm.toLowerCase());
      const matchesType = comp.category === selectedType;
      const matchesProvider = selectedProviders.size === 0 || (comp.provider && selectedProviders.has(comp.provider));
      return matchesSearch && matchesType && matchesProvider;
    }).sort((a, b) => {
      const aIsFav = isFavorite(a);
      const bIsFav = isFavorite(b);

      // Sort favorites to the top
      if (aIsFav && !bIsFav) return -1;
      if (!aIsFav && bIsFav) return 1;

      // Sort alphabetically by label (both favorites and non-favorites)
      return a.label.localeCompare(b.label);
    });
  }, [components, localSearchTerm, selectedType, selectedProviders, isFavorite]);

  // Count of favorite components in current filtered list
  const favoriteCount = useMemo(() => {
    return filteredComponents.filter(comp => isFavorite(comp)).length;
  }, [filteredComponents, isFavorite]);

  const onDragStart = (event: React.DragEvent, component: Component) => {
    event.dataTransfer.setData('application/reactflow', component.type || 'element');
    event.dataTransfer.setData('component', JSON.stringify(component));
    event.dataTransfer.effectAllowed = 'move';

    // Notify parent about component drag
    if (onComponentDrag) {
      onComponentDrag(event, component);
    }

    // Notify parent if this is a condition/decision component
    if ((component.category === 'Conditions' || component.category === 'Decisions') && onConditionDragStart) {
      onConditionDragStart();
    } else if (onComponentDragStart) {
      // Notify parent about regular component drag with type info
      onComponentDragStart(component);
    }
  };

  // Default component type configuration - can be overridden by data from API
  // Labels are translated when displayed to support i18n
  const defaultComponentTypeConfig: Record<string, ComponentTypeConfig> = {
    'Events': { label: t('Events'), icon: FiZap },
    'Actions': { label: t('Actions'), icon: FiActivity },
    'Conditions': { label: t('Conditions'), icon: FiHelpCircle },
    'Gateways': { label: t('Gateways'), icon: FiGitBranch },
    'Triggers': { label: t('Triggers'), icon: FiZap },
    'Tasks': { label: t('Tasks'), icon: FiActivity },
    'Decisions': { label: t('Decisions'), icon: FiHelpCircle },
    'Connectors': { label: t('Connectors'), icon: FiLink },
    'Processors': { label: t('Processors'), icon: FiCpu },
    'Others': { label: t('Others'), icon: FiLayers }
  };

  const getComponentIcon = (category: string): React.ReactNode => {
    const iconMap: Record<string, React.ReactNode> = {
      'Events': <FiZap />,
      'Actions': <FiActivity />,
      'Conditions': <FiHelpCircle />,
      'Gateways': <FiGitBranch />,
      'Triggers': <FiZap />,
      'Tasks': <FiActivity />,
      'Decisions': <FiHelpCircle />,
      'Connectors': <FiLink />,
      'Processors': <FiCpu />,
      'Others': <FiLayers />
    };
    return iconMap[category] || <FiActivity />;
  };

  // Build component type config from available types in data
  const componentTypeConfig = availableTypes ?
    Object.keys(availableTypes).reduce((config: Record<string, ComponentTypeConfig>, typeId) => {
      config[typeId] = defaultComponentTypeConfig[typeId] || {
        label: typeId,
        icon: FiActivity
      };
      return config;
    }, {}) :
    defaultComponentTypeConfig;

  // Resize handler
  const startResize = useCallback((e: React.MouseEvent) => {
    e.preventDefault();
    setComponentPanelResizing(true);

    const startX = e.clientX;
    const startWidth = componentPanelWidth;

    const handleMouseMove = (e: MouseEvent) => {
      const deltaX = e.clientX - startX;
      const newWidth = startWidth + deltaX;
      setComponentPanelWidth(newWidth);
    };

    const handleMouseUp = () => {
      setComponentPanelResizing(false);
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  }, [componentPanelWidth, setComponentPanelWidth, setComponentPanelResizing]);

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

  return (
    <div
      className={`workflow-component-panel ${componentPanelIsResizing ? 'resizing' : ''} ${componentPanelCollapsed ? 'collapsed' : ''}`}
      style={{ width: componentPanelCollapsed ? `${PANEL_DIMENSIONS.COMPONENT_PANEL.COLLAPSED_WIDTH}px` : `${componentPanelWidth}px` }}
      onClick={handlePanelClick}
      title={componentPanelCollapsed ? t('Click to expand') : undefined}
    >
      <div
        className="resize-handle resize-handle-right"
        onMouseDown={startResize}
        title={t('Drag to resize')}
      />
      <button
        className="panel-collapse-widget"
        onClick={toggleComponentPanelCollapse}
        title={componentPanelCollapsed ? t('Expand panel') : t('Collapse panel')}
        aria-label={componentPanelCollapsed ? t('Expand panel') : t('Collapse panel')}
      >
        <span className="collapse-icon">
          {componentPanelCollapsed ? <FiChevronRight /> : <FiChevronLeft />}
        </span>
      </button>
      {componentPanelCollapsed && (
        <div className="panel-collapsed-label">
          <span>{t('Components')}</span>
        </div>
      )}
      <div className="panel-content">
        <div className="component-type-selector">
        {Object.keys(availableTypes).map(typeId => {
          const config = componentTypeConfig[typeId];
          if (!config) return null;
          const Icon = config.icon;
          const filteredCount = filteredCountsByType[typeId] || 0;
          const totalCount = availableTypes[typeId];
          return (
            <button
              key={typeId}
              className={classNames('type-selector-btn', {
                active: selectedType === typeId
              })}
              onClick={() => {
                setSelectedType(typeId);
                setFilterExpanded(false); // Collapse filter when changing type
              }}
              title={t('@label (@count of @total shown)', { '@label': config.label, '@count': filteredCount, '@total': totalCount })}
            >
              <Icon />
              <span>{config.label}</span>
              <span className="component-count">({filteredCount})</span>
            </button>
          );
        })}
      </div>

      <div className="panel-header">
        <div className="search-box">
          <FiSearch className="search-icon component-search-icon" />
          <input
            type="text"
            placeholder={selectedType ? t('Search @type...', { '@type': selectedType.toLowerCase() }) : t('Search components...')}
            aria-label={selectedType ? t('Search @type', { '@type': selectedType.toLowerCase() }) : t('Search components')}
            value={localSearchTerm}
            onChange={(e) => setLocalSearchTerm(e.target.value)}
          />
        </div>
        {availableProviders.length > 0 && (
          <div className="provider-filter-container">
            <button
              className="filter-toggle"
              onClick={() => setFilterExpanded(!filterExpanded)}
            >
              {filterExpanded ? <FiChevronDown size={14} /> : <FiChevronRight size={14} />}
              <FiFilter size={14} />
              <span>{t('Filter by provider')}</span>
              {selectedProviders.size > 0 && (
                <span className="filter-count">{selectedProviders.size}</span>
              )}
            </button>
            {filterExpanded && (
              <div className="provider-checkboxes">
                {availableProviders.map(provider => (
                  <label key={provider} className="provider-checkbox">
                    <input
                      type="checkbox"
                      checked={selectedProviders.has(provider)}
                      onChange={(e) => {
                        const newProviders = new Set(selectedProviders);
                        if (e.target.checked) {
                          newProviders.add(provider);
                        } else {
                          newProviders.delete(provider);
                        }
                        setSelectedProviders(newProviders);
                      }}
                    />
                    <span>{provider}</span>
                  </label>
                ))}
                {selectedProviders.size > 0 && (
                  <button
                    className="clear-filters-btn"
                    onClick={() => setSelectedProviders(new Set())}
                  >
                    {t('Clear filters')}
                  </button>
                )}
              </div>
            )}
          </div>
        )}
      </div>

      <div className="component-list">
        {!selectedType ? (
          <div className="no-components">
            {t('No component types available')}
          </div>
        ) : filteredComponents.length === 0 ? (
          <div className="no-components">
            {t('No @type found', { '@type': selectedType.toLowerCase() })}
          </div>
        ) : (
          <>
            {/* Favorites section header - only show if there are favorites */}
            {favoriteCount > 0 && (
              <div className="component-section-header favorites-header">
                <FiStar size={12} />
                <span>{t('Favorites (@count)', { '@count': favoriteCount })}</span>
              </div>
            )}
            {filteredComponents.map((component, index) => {
              const isComponentFavorite = isFavorite(component);
              const isLastFavorite = isComponentFavorite &&
                (index + 1 >= filteredComponents.length || !isFavorite(filteredComponents[index + 1]));

              return (
                <React.Fragment key={component.plugin}>
                  <div
                    className={classNames('component-item', {
                      [selectedType.toLowerCase()]: true,
                      'has-description': component.description && component.description.trim() !== '',
                      'favorite': isComponentFavorite
                    })}
                    draggable
                    onDragStart={(e) => onDragStart(e, component)}
                    onDragEnd={() => {
                      if ((component.category === 'Conditions' || component.category === 'Decisions') && onConditionDragEnd) {
                        onConditionDragEnd();
                      } else if (onComponentDragEnd) {
                        onComponentDragEnd();
                      }
                    }}
                    {...(component.description && component.description.trim() !== '' ? { title: component.description } : {})}
                  >
                    {isComponentFavorite && (
                      <div className="favorite-indicator">
                        <FiStar size={12} />
                      </div>
                    )}
                    <div className="component-icon">
                      {getComponentIcon(selectedType)}
                    </div>
                    <div className="component-info">
                      <div className="component-label">{component.label}</div>
                    </div>
                    {component.description && component.description.trim() !== '' && !component.documentationUrl && (
                      <div className="component-description-indicator">
                        <FiInfo size={14} />
                      </div>
                    )}
                    {component.documentationUrl && (
                      <DocumentationButton
                        url={component.documentationUrl}
                        title={component.label}
                        className="component-documentation-btn"
                        size={14}
                      />
                    )}
                  </div>
                  {/* Show divider after the last favorite */}
                  {isLastFavorite && favoriteCount < filteredComponents.length && (
                    <div className="component-section-divider">
                      <span>{t('All @type', { '@type': selectedType })}</span>
                    </div>
                  )}
                </React.Fragment>
              );
            })}
          </>
        )}
      </div>
      </div>
    </div>
  );
};

export default ComponentPanel;
