import { useState, useEffect, useMemo } from 'react'

/**
 * LogicExpressionEditor - Visueller Baukasten für Logik-Bedingungen
 *
 * KEIN JSON-Editor! Visuelles Drag & Drop Interface.
 *
 * Props:
 * - node: React Flow Node object (type='logic')
 * - nodes: Array of all nodes (for signal reference lookup)
 * - edges: Array of all edges (for topological sort)
 * - onChange: (nodeId, updates) => void
 */
export function LogicExpressionEditor({ node, nodes, edges, onChange }) {
  const [expression, setExpression] = useState(node.data.condition || {
    operator: 'and',
    operands: []
  })

  // Verfügbare Signale aus vorangegangenen Nodes
  const availableSignals = useMemo(() => {
    return getAvailableSignals(node.id, nodes, edges)
  }, [node.id, nodes, edges])

  // Sync to parent when expression changes
  useEffect(() => {
    onChange(node.id, { condition: expression })
  }, [expression])

  const handleOperatorChange = (e) => {
    setExpression({ ...expression, operator: e.target.value })
  }

  const handleAddCondition = () => {
    setExpression({
      ...expression,
      operands: [...(expression.operands || []), {
        ref: '',
        operator: 'eq',
        value: ''
      }]
    })
  }

  const handleAddGroup = () => {
    setExpression({
      ...expression,
      operands: [...(expression.operands || []), {
        operator: 'and',
        operands: []
      }]
    })
  }

  const handleOperandChange = (index, updates) => {
    const updated = [...(expression.operands || [])]
    updated[index] = { ...updated[index], ...updates }
    setExpression({ ...expression, operands: updated })
  }

  const handleRemoveOperand = (index) => {
    setExpression({
      ...expression,
      operands: (expression.operands || []).filter((_, i) => i !== index)
    })
  }

  return (
    <div className="config-section">
      <h3>Logik-Bedingung</h3>

      {availableSignals.length === 0 && (
        <div className="help-text" style={{ color: 'var(--danger)', marginBottom: '12px' }}>
          ⚠️ Keine Signale verfügbar. Fügen Sie zuerst einen Analysis-Node VOR diesem Node hinzu.
        </div>
      )}

      <div className="logic-root">
        <label>Verknüpfung (Root-Operator)</label>
        <select value={expression.operator || 'and'} onChange={handleOperatorChange}>
          <option value="and">UND (alle müssen zutreffen)</option>
          <option value="or">ODER (mind. eine muss zutreffen)</option>
          <option value="not">NICHT (umkehren)</option>
        </select>
      </div>

      <div className="logic-operands">
        {(expression.operands || []).map((operand, idx) => (
          <ConditionBlock
            key={idx}
            operand={operand}
            availableSignals={availableSignals}
            onChange={(updates) => handleOperandChange(idx, updates)}
            onRemove={() => handleRemoveOperand(idx)}
          />
        ))}

        {(!expression.operands || expression.operands.length === 0) && (
          <div className="help-text" style={{ marginBottom: '12px' }}>
            Keine Bedingungen definiert. Fügen Sie Bedingungen oder Gruppen hinzu.
          </div>
        )}
      </div>

      <div className="logic-actions">
        <button className="btn-secondary" onClick={handleAddCondition}>
          + Bedingung
        </button>
        <button className="btn-secondary" onClick={handleAddGroup}>
          + Gruppe (AND/OR)
        </button>
      </div>

      <div className="help-text" style={{ marginTop: '12px', fontSize: '11px', color: 'var(--text3)' }}>
        💡 Signale: {availableSignals.length} verfügbar
      </div>
    </div>
  )
}

/**
 * ConditionBlock - Einzelne Bedingung oder Gruppe (rekursiv)
 */
function ConditionBlock({ operand, availableSignals, onChange, onRemove }) {
  // Verschachtelte Gruppe? (AND/OR/NOT)
  const isGroup = operand.operator === 'and' || operand.operator === 'or' || operand.operator === 'not'

  if (isGroup) {
    return (
      <div className="condition-group">
        <div className="group-header">
          <select
            value={operand.operator}
            onChange={(e) => onChange({ operator: e.target.value })}
            style={{ flex: 1 }}
          >
            <option value="and">UND</option>
            <option value="or">ODER</option>
            <option value="not">NICHT</option>
          </select>
          <button className="btn-icon" onClick={onRemove}>🗑️</button>
        </div>

        {/* Rekursiv: Nested operands */}
        <div style={{ paddingLeft: '12px', borderLeft: '3px solid var(--accent)' }}>
          {(operand.operands || []).map((subOp, idx) => (
            <ConditionBlock
              key={idx}
              operand={subOp}
              availableSignals={availableSignals}
              onChange={(updates) => {
                const updated = [...(operand.operands || [])]
                updated[idx] = { ...updated[idx], ...updates }
                onChange({ operands: updated })
              }}
              onRemove={() => {
                onChange({ operands: (operand.operands || []).filter((_, i) => i !== idx) })
              }}
            />
          ))}

          <button
            className="btn-secondary"
            onClick={() => {
              onChange({
                operands: [...(operand.operands || []), { ref: '', operator: 'eq', value: '' }]
              })
            }}
            style={{ marginTop: '8px', fontSize: '12px' }}
          >
            + Bedingung
          </button>
        </div>
      </div>
    )
  }

  // Einfache Bedingung
  const selectedSignal = availableSignals.find(s => s.ref === operand.ref)

  return (
    <div className="condition-simple">
      {/* Signal-Referenz (Dropdown) */}
      <select
        value={operand.ref || ''}
        onChange={(e) => onChange({ ref: e.target.value })}
        className="signal-select"
        style={{ flex: 2 }}
      >
        <option value="">-- Signal wählen --</option>
        {availableSignals.map(sig => (
          <option key={sig.ref} value={sig.ref}>
            {sig.label}
          </option>
        ))}
      </select>

      {/* Operator */}
      <select
        value={operand.operator || 'eq'}
        onChange={(e) => onChange({ operator: e.target.value })}
        className="operator-select"
        style={{ flex: 1 }}
      >
        <option value="eq">==</option>
        <option value="neq">!=</option>
        <option value="in">IN</option>
        <option value="not_in">NOT IN</option>
        <option value="gt">&gt;</option>
        <option value="lt">&lt;</option>
        <option value="gte">&gt;=</option>
        <option value="lte">&lt;=</option>
        <option value="contains">CONTAINS</option>
      </select>

      {/* Wert (abhängig von Operator) */}
      {(operand.operator === 'in' || operand.operator === 'not_in') ? (
        <MultiSelect
          options={selectedSignal?.spectrum || []}
          value={operand.value || []}
          onChange={(val) => onChange({ value: val })}
          placeholder="Werte wählen"
        />
      ) : (
        <input
          type="text"
          value={operand.value || ''}
          onChange={(e) => onChange({ value: e.target.value })}
          placeholder="Wert"
          className="value-input"
          style={{ flex: 1 }}
        />
      )}

      <button className="btn-icon" onClick={onRemove}>🗑️</button>
    </div>
  )
}

/**
 * MultiSelect - Multi-Auswahl für IN/NOT_IN Operatoren
 */
function MultiSelect({ options, value, onChange, placeholder }) {
  const [isOpen, setIsOpen] = useState(false)
  const selected = Array.isArray(value) ? value : []

  const handleToggle = (option) => {
    if (selected.includes(option)) {
      onChange(selected.filter(v => v !== option))
    } else {
      onChange([...selected, option])
    }
  }

  return (
    <div className="multi-select" style={{ flex: 1, position: 'relative' }}>
      <div
        className="multi-select-display"
        onClick={() => setIsOpen(!isOpen)}
        style={{
          padding: '6px',
          border: '1px solid var(--border)',
          borderRadius: '4px',
          cursor: 'pointer',
          fontSize: '12px',
          background: 'var(--bg)'
        }}
      >
        {selected.length > 0 ? selected.join(', ') : placeholder}
      </div>

      {isOpen && (
        <div
          className="multi-select-dropdown"
          style={{
            position: 'absolute',
            top: '100%',
            left: 0,
            right: 0,
            background: 'var(--surface)',
            border: '1px solid var(--border)',
            borderRadius: '4px',
            marginTop: '4px',
            maxHeight: '200px',
            overflowY: 'auto',
            zIndex: 1000
          }}
        >
          {options.map((option, i) => (
            <div
              key={i}
              onClick={() => handleToggle(option)}
              style={{
                padding: '8px',
                cursor: 'pointer',
                fontSize: '12px',
                background: selected.includes(option) ? 'var(--accent)' : 'transparent',
                color: selected.includes(option) ? 'white' : 'var(--text1)'
              }}
            >
              {selected.includes(option) && '✓ '}
              {option}
            </div>
          ))}

          {options.length === 0 && (
            <div style={{ padding: '8px', fontSize: '12px', color: 'var(--text3)' }}>
              Keine Optionen verfügbar
            </div>
          )}
        </div>
      )}
    </div>
  )
}

/**
 * Helper: Verfügbare Signale aus vorangegangenen Nodes extrahieren
 */
function getAvailableSignals(nodeId, nodes, edges) {
  // Topologische Sortierung: Alle Nodes VOR diesem Node
  const predecessors = new Set()

  function collectPredecessors(currentId) {
    const incoming = edges.filter(e => e.target === currentId)
    for (const edge of incoming) {
      if (!predecessors.has(edge.source)) {
        predecessors.add(edge.source)
        collectPredecessors(edge.source)
      }
    }
  }

  collectPredecessors(nodeId)

  // Signale extrahieren (nur von ANALYSIS Nodes)
  const signals = []
  for (const predId of predecessors) {
    const predNode = nodes.find(n => n.id === predId)
    if (predNode && predNode.type === 'analysis') {
      const questions = predNode.data.questions || []
      for (const q of questions) {
        signals.push({
          ref: `${predId}.${q.id}`,
          label: `${predNode.data.label} → ${q.question || q.id}`,
          spectrum: q.answer_spectrum || []
        })
      }
    }
  }

  return signals
}
