/**
 * Loop node - Datenquelle für Iteration mit benutzerfreundlichen Labels.
 * Zeigt nur iterierbare Quellen: Arrays und Objekte (Formularfelder → {name, value}).
 */

import React from 'react';
import { createRef, isRef, type DataRef } from './dataRef';
import { refToOptionValue, optionValueToRef } from './RefSourceSelect';
import { useWorkflowDataFlow } from '../../context/WorkflowDataFlowContext';
import styles from '../../editor/WorkflowFlowEditor.module.css';

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

interface LoopOption {
  ref: DataRef;
  label: string;
}

function getValueAtPath(obj: unknown, path: (string | number)[]): unknown {
  let current: unknown = obj;
  for (const seg of path) {
    if (current == null) return undefined;
    const key = typeof seg === 'number' ? String(seg) : seg;
    if (Array.isArray(current) && /^\d+$/.test(key)) {
      current = current[parseInt(key, 10)];
    } else if (typeof current === 'object' && key in (current as object)) {
      current = (current as Record<string, unknown>)[key];
    } else return undefined;
  }
  return current;
}

/** Build iterable options with friendly labels for Loop node */
function buildLoopOptions(
  sourceIds: string[],
  nodes: Array<{ id: string; type?: string; title?: string; parameters?: Record<string, unknown> }>,
  nodeOutputsPreview: Record<string, unknown>,
  getNodeLabel: (n: { id: string; type?: string; title?: string }) => string,
  translate: (key: string) => string
): LoopOption[] {
  const options: LoopOption[] = [];

  for (const nodeId of sourceIds) {
    const node = nodes.find((n) => n.id === nodeId);
    if (node?.type === 'trigger.manual') continue;

    const nodeLabel = getNodeLabel(node ?? { id: nodeId });
    const preview = nodeOutputsPreview[nodeId];

    // Special cases with friendly labels
    if (node?.type === 'trigger.form') {
      options.push({
        ref: createRef(nodeId, ['payload']),
        label: `${translate('Alle Formularfelder')} (${nodeLabel})`,
      });
      const filesVal = getValueAtPath(preview, ['files']);
      if (Array.isArray(filesVal)) {
        options.push({
          ref: createRef(nodeId, ['files']),
          label: `${translate('Alle Dateien aus Formular')} (${nodeLabel})`,
        });
      }
      continue;
    }

    if (node?.type === 'input.form') {
      options.push({
        ref: createRef(nodeId, []),
        label: `${translate('Alle Formularfelder')} (${nodeLabel})`,
      });
      continue;
    }

    if (node?.type === 'input.upload') {
      options.push({
        ref: createRef(nodeId, ['files']),
        label: `${translate('Alle hochgeladenen Dateien')} (${nodeLabel})`,
      });
      options.push({
        ref: createRef(nodeId, ['fileIds']),
        label: `${translate('Alle Datei-IDs')} (${nodeLabel})`,
      });
      continue;
    }

    if (node?.type === 'flow.loop') {
      options.push({
        ref: createRef(nodeId, ['items']),
        label: `${translate('Alle Elemente aus Schleife')} (${nodeLabel})`,
      });
      continue;
    }

    if (node?.type === 'email.searchEmail') {
      options.push({
        ref: createRef(nodeId, ['data', 'searchResults', 'results']),
        label: `${translate('Alle gefundenen E-Mails')} (${nodeLabel})`,
      });
      continue;
    }

    if (node?.type === 'email.checkEmail') {
      options.push({
        ref: createRef(nodeId, ['data', 'emails', 'emails']),
        label: `${translate('Alle E-Mails')} (${nodeLabel})`,
      });
      continue;
    }

    if (node?.type === 'sharepoint.listFiles') {
      options.push({
        ref: createRef(nodeId, ['files']),
        label: `${translate('Alle Dateien')} (${nodeLabel})`,
      });
      continue;
    }

    // Generic: find top-level arrays and root object in preview
    if (preview != null && typeof preview === 'object') {
      for (const [k, v] of Object.entries(preview as Record<string, unknown>)) {
        const path: (string | number)[] = [k];
        const pathStr = path.join('.');
        if (Array.isArray(v)) {
          options.push({
            ref: createRef(nodeId, path),
            label: `${nodeLabel}.${pathStr}`,
          });
        } else if (v != null && typeof v === 'object' && !Array.isArray(v)) {
          const inner = v as Record<string, unknown>;
          for (const [k2, v2] of Object.entries(inner)) {
            if (Array.isArray(v2)) {
              options.push({
                ref: createRef(nodeId, [k, k2]),
                label: `${nodeLabel}.${k}.${k2}`,
              });
            }
          }
        }
      }
    }
  }

  // Deduplicate by ref (path might repeat from different collection)
  const seen = new Set<string>();
  return options.filter((o) => {
    const key = refToOptionValue(o.ref);
    if (seen.has(key)) return false;
    seen.add(key);
    return true;
  });
}

interface LoopItemsSelectProps {
  value: DataRef | { type: 'value'; value: unknown } | null;
  onChange: (ref: DataRef | null) => void;
  placeholder?: string;
}

export const LoopItemsSelect: React.FC<LoopItemsSelectProps> = ({ value,
  onChange,
  placeholder,
}) => {
  const { t } = useLanguage();
  const dataFlow = useWorkflowDataFlow();
  if (!dataFlow) return null;

  const sourceIds = dataFlow.getAvailableSourceIds();
  if (sourceIds.length === 0) {
    return (
      <p className={styles.dynamicValueEmptyHint}>
        {t('Keine vorherigen Nodes verbunden. Verbinden Sie zuerst Nodes mit der Schleife.')}
      </p>
    );
  }

  const options = buildLoopOptions(
    sourceIds,
    dataFlow.nodes,
    dataFlow.nodeOutputsPreview,
    dataFlow.getNodeLabel,
    t
  );

  const ref = isRef(value) ? value : null;
  const currentValue = ref ? refToOptionValue(ref) : '';

  return (
    <div className={styles.ifElseConditionRow}>
      <label>{t('Datenquelle für Iteration')}</label>
      <select
        value={currentValue}
        onChange={(e) => {
          const v = e.target.value;
          if (!v) {
            onChange(null);
            return;
          }
          const r = optionValueToRef(v);
          if (r) onChange(r);
        }}
        className={styles.startsInput}
      >
        <option value="">{placeholder ?? t('Über was soll iteriert werden?')}</option>
        {options.map((o) => (
          <option key={refToOptionValue(o.ref)} value={refToOptionValue(o.ref)}>
            {o.label}
          </option>
        ))}
      </select>
      <p className={styles.nodeConfigNameHint}>
        {t('Z.B. für jedes Formularfeld, jede Datei aus Upload, jede E-Mail aus Suche.')}
      </p>
    </div>
  );
};
