/**
 * Automation2 Flow Editor - Schema-based Data Picker.
 * Builds pickable paths from portTypeCatalog + node outputPorts.
 * Resolves Transit chains to show the real upstream schema.
 * Includes a System Variables section.
 */

import React, { useState } from 'react';
import { createRef, createSystemVar, type DataRef, type SystemVarRef } from './dataRef';
import { useAutomation2DataFlow } from '../../context/Automation2DataFlowContext';
import type { NodeType, PortSchema } from '../../../../api/workflowApi';
import styles from '../../editor/Automation2FlowEditor.module.css';

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

interface DataPickerProps {
  open: boolean;
  onClose: () => void;
  onPick: (ref: DataRef | SystemVarRef) => void;
  availableSourceIds: string[];
  nodes: Array<{ id: string; title?: string; type?: string }>;
  nodeOutputsPreview: Record<string, unknown>;
  getNodeLabel: (node: { id: string; title?: string }) => string;
}

interface PickablePath {
  path: (string | number)[];
  label: string;
  type?: string;
}

function _buildPathsFromSchema(
  schema: PortSchema | undefined,
  basePath: (string | number)[] = [],
): PickablePath[] {
  if (!schema || !schema.fields) return [];
  const result: PickablePath[] = [];
  for (const field of schema.fields) {
    const fieldPath = [...basePath, field.name];
    const label = fieldPath.map(String).join(' → ');
    result.push({ path: fieldPath, label, type: field.type });
  }
  result.push({ path: [...basePath, '_success'], label: [...basePath, '_success'].map(String).join(' → '), type: 'bool' });
  result.push({ path: [...basePath, '_error'], label: [...basePath, '_error'].map(String).join(' → '), type: 'str' });
  return result;
}

function _buildPathsFromPreview(
  obj: unknown,
  basePath: (string | number)[] = [],
  wholeOutputLabel = '(ganze Ausgabe)',
): PickablePath[] {
  const pathLabel = basePath.length ? basePath.map(String).join(' → ') : wholeOutputLabel;
  if (obj == null || typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean') {
    return [{ path: [...basePath], label: pathLabel }];
  }
  if (Array.isArray(obj)) {
    const result: PickablePath[] = [{ path: [...basePath], label: pathLabel }];
    for (let i = 0; i < Math.min(obj.length, 5); i++) {
      result.push(..._buildPathsFromPreview(obj[i], [...basePath, i], wholeOutputLabel));
    }
    return result;
  }
  if (typeof obj === 'object') {
    const result: PickablePath[] = [{ path: [...basePath], label: pathLabel }];
    for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {
      if (k.startsWith('_')) continue;
      result.push(..._buildPathsFromPreview(v, [...basePath, k], wholeOutputLabel));
    }
    return result;
  }
  return [{ path: [...basePath], label: pathLabel }];
}

function _resolveSchemaForNode(
  nodeId: string,
  nodes: Array<{ id: string; type?: string }>,
  nodeTypes: NodeType[],
  connections: Array<{ source: string; target: string; sourceOutput?: number }>,
  catalog: Record<string, PortSchema>,
  visited: Set<string> = new Set(),
): PortSchema | undefined {
  if (visited.has(nodeId)) return undefined;
  visited.add(nodeId);

  const node = nodes.find((n) => n.id === nodeId);
  if (!node) return undefined;
  const typeDef = nodeTypes.find((nt) => nt.id === node.type);
  if (!typeDef?.outputPorts) return undefined;

  const port0 = typeDef.outputPorts[0];
  if (!port0) return undefined;

  if (port0.schema !== 'Transit') {
    return catalog[port0.schema];
  }

  // Transit: follow the incoming connection to find the real producer
  const incoming = connections.find((c) => c.target === nodeId);
  if (!incoming) return undefined;
  return _resolveSchemaForNode(incoming.source, nodes, nodeTypes, connections, catalog, visited);
}

export const DataPicker: React.FC<DataPickerProps> = ({ open,
  onClose,
  onPick,
  availableSourceIds,
  nodes,
  nodeOutputsPreview,
  getNodeLabel,
}) => {
  const { t } = useLanguage();
  const [expandedNodes, setExpandedNodes] = useState<Set<string>>(new Set());
  const [showSystem, setShowSystem] = useState(false);
  const ctx = useAutomation2DataFlow();

  if (!open) return null;

  const catalog = ctx?.portTypeCatalog ?? {};
  const systemVars = ctx?.systemVariables ?? {};
  const nodeTypes = ctx?.nodeTypes ?? [];
  const connectionsRaw = ctx?.connections ?? [];
  const connections = connectionsRaw.map((c) => ({
    source: c.sourceId,
    target: c.targetId,
    sourceOutput: c.sourceHandle,
  }));

  const toggleExpand = (nodeId: string) => {
    setExpandedNodes((prev) => {
      const next = new Set(prev);
      if (next.has(nodeId)) next.delete(nodeId);
      else next.add(nodeId);
      return next;
    });
  };

  const handlePick = (nodeId: string, path: (string | number)[]) => {
    onPick(createRef(nodeId, path));
    onClose();
  };

  const handlePickSystemVar = (variable: string) => {
    onPick(createSystemVar(variable));
    onClose();
  };

  return (
    <div className={styles.dataPickerOverlay} onClick={onClose}>
      <div className={styles.dataPickerModal} onClick={(e) => e.stopPropagation()}>
        <div className={styles.dataPickerHeader}>
          <h4 className={styles.dataPickerTitle}>{t('Datenquelle wählen')}</h4>
          <button type="button" className={styles.dataPickerClose} onClick={onClose} aria-label={t('Schließen')}>
            ×
          </button>
        </div>
        <div className={styles.dataPickerBody}>
          {/* System Variables Section */}
          {Object.keys(systemVars).length > 0 && (
            <div className={styles.dataPickerNodeSection}>
              <button
                type="button"
                className={styles.dataPickerNodeHeader}
                onClick={() => setShowSystem(!showSystem)}
              >
                <span className={styles.dataPickerExpandIcon}>{showSystem ? '▼' : '▶'}</span>
                <span className={styles.dataPickerNodeLabel}>{t('System')}</span>
              </button>
              {showSystem && (
                <div className={styles.dataPickerTree}>
                  {Object.entries(systemVars).map(([key, info]) => (
                    <button
                      key={key}
                      type="button"
                      className={styles.dataPickerLeaf}
                      onClick={() => handlePickSystemVar(key)}
                      title={info.description}
                    >
                      {key} <span style={{ color: '#888', fontSize: 10 }}>({info.type})</span>
                    </button>
                  ))}
                </div>
              )}
            </div>
          )}

          {/* Node outputs */}
          {(() => {
            const filteredIds = availableSourceIds.filter((nodeId) => {
              const node = nodes.find((n) => n.id === nodeId);
              return node?.type !== 'trigger.manual';
            });
            if (filteredIds.length === 0 && Object.keys(systemVars).length === 0) {
              return <p className={styles.dataPickerEmpty}>{t('Keine vorherigen Nodes verfügbar')}</p>;
            }
            return filteredIds.map((nodeId) => {
              const node = nodes.find((n) => n.id === nodeId);
              const label = node ? getNodeLabel(node) : nodeId;
              const isExpanded = expandedNodes.has(nodeId);

              const resolvedSchema = _resolveSchemaForNode(
                nodeId, nodes, nodeTypes, connections, catalog,
              );
              const schemaPaths = _buildPathsFromSchema(resolvedSchema);
              const paths = schemaPaths.length > 0
                ? schemaPaths
                : _buildPathsFromPreview(nodeOutputsPreview[nodeId], [], t('(ganze Ausgabe)'));

              return (
                <div key={nodeId} className={styles.dataPickerNodeSection}>
                  <button
                    type="button"
                    className={styles.dataPickerNodeHeader}
                    onClick={() => toggleExpand(nodeId)}
                  >
                    <span className={styles.dataPickerExpandIcon}>{isExpanded ? '▼' : '▶'}</span>
                    <span className={styles.dataPickerNodeLabel}>{label}</span>
                    {resolvedSchema && (
                      <span style={{ color: '#888', fontSize: 10, marginLeft: 4 }}>
                        ({resolvedSchema.name})
                      </span>
                    )}
                  </button>
                  {isExpanded && (
                    <div className={styles.dataPickerTree}>
                      {paths.map((p, i) => (
                        <button
                          key={`${p.path.join('.')}-${i}`}
                          type="button"
                          className={styles.dataPickerLeaf}
                          onClick={() => handlePick(nodeId, p.path)}
                        >
                          {p.label}
                          {p.type && (
                            <span style={{ color: '#888', fontSize: 10, marginLeft: 4 }}>
                              ({p.type})
                            </span>
                          )}
                        </button>
                      ))}
                    </div>
                  )}
                </div>
              );
            });
          })()}
        </div>
      </div>
    </div>
  );
};
