// Copyright (c) 2026 PowerOn AG
// All rights reserved.
/**
 * NodeSidebar - Sidebar with searchable, collapsible node list.
 * Groups node types by category (start, input, flow, data, ai, email, sharepoint).
 */

import React, { useMemo } from 'react';
import { FaChevronDown, FaChevronRight } from 'react-icons/fa';
import type { NodeType, NodeTypeCategory } from '../../../api/workflowAutomationApi';
import { CATEGORY_ORDER, HIDDEN_NODE_IDS } from '../nodes/shared/constants';
import { getLabel } from '../nodes/shared/utils';
import { NodeListItem } from './NodeListItem';
import styles from './WorkflowFlowEditor.module.css';

import { useLanguage } from '../../../providers/language/LanguageContext';

interface NodeSidebarProps {
  nodeTypes: NodeType[];
  categories: NodeTypeCategory[];
  filter: string;
  onFilterChange: (value: string) => void;
  language: string;
  expandedCategories: Set<string>;
  onToggleCategory: (id: string) => void;
  /** Hide palette categories (optional; e.g. feature flags) */
  excludedCategories?: Set<string>;
  style?: React.CSSProperties;
}

export const NodeSidebar: React.FC<NodeSidebarProps> = ({ nodeTypes,
  categories,
  filter,
  onFilterChange,
  language,
  expandedCategories,
  onToggleCategory,
  excludedCategories,
  style,
}) => {
  const { t } = useLanguage();
  const filteredNodeTypes = useMemo(() => {
    const visible = nodeTypes.filter(
      (n) =>
        !HIDDEN_NODE_IDS.has(n.id) &&
        !(excludedCategories?.has(n.category || ''))
    );
    if (!filter.trim()) return visible;
    const q = filter.toLowerCase();
    return visible.filter(
      (n) =>
        n.id.toLowerCase().includes(q) ||
        getLabel(n.label, language).toLowerCase().includes(q) ||
        getLabel(n.description, language).toLowerCase().includes(q)
    );
  }, [nodeTypes, filter, language]);

  const groupedByCategory = useMemo(() => {
    const map: Record<string, NodeType[]> = {};
    filteredNodeTypes.forEach((n) => {
      const cat = n.category || 'other';
      if (!map[cat]) map[cat] = [];
      map[cat].push(n);
    });
    return map;
  }, [filteredNodeTypes]);

  const orderedCategories = useMemo(() => {
    const seen = new Set<string>();
    const result: string[] = [];
    CATEGORY_ORDER.forEach((id) => {
      if (groupedByCategory[id]) {
        result.push(id);
        seen.add(id);
      }
    });
    Object.keys(groupedByCategory).forEach((id) => {
      if (!seen.has(id)) result.push(id);
    });
    return result;
  }, [groupedByCategory]);

  const getLabelFn = (multilingual: string | Record<string, string> | undefined, lang?: string) =>
    getLabel(multilingual, lang ?? language);

  return (
    <div className={styles.sidebar} style={style}>
      <div className={styles.sidebarHeader}>
        <h3 className={styles.sidebarTitle}>{t('Knoten')}</h3>
        <input
          type="text"
          className={styles.sidebarSearch}
          placeholder={t('Nodes durchsuchen')}
          value={filter}
          onChange={(e) => onFilterChange(e.target.value)}
        />
      </div>
      <div className={styles.nodeList}>
        {orderedCategories.map((catId) => {
          const isExpanded = expandedCategories.has(catId);
          const catLabel = categories.find((c) => c.id === catId);
          const label = getLabel(catLabel?.label, language) || catId;
          const items = groupedByCategory[catId] || [];
          return (
            <div key={catId} className={styles.categoryGroup}>
              <button
                type="button"
                className={styles.categoryHeader}
                onClick={() => onToggleCategory(catId)}
              >
                {isExpanded ? (
                  <FaChevronDown className={styles.categoryIcon} />
                ) : (
                  <FaChevronRight className={styles.categoryIcon} />
                )}
                <span className={styles.categoryLabel}>{label}</span>
                <span className={styles.categoryCount}>{items.length}</span>
              </button>
              {isExpanded &&
                items.map((node) => (
                  <NodeListItem
                    key={node.id}
                    node={node}
                    language={language}
                    getLabel={getLabelFn}
                  />
                ))}
            </div>
          );
        })}
      </div>
    </div>
  );
};
