/**
 * n8n-style visual funnel builder using ReactFlow v11.
 * Drag nodes from the left palette onto the canvas, connect them,
 * configure via the right panel. Saves nodes+edges to REST API.
 */
import { useState, useCallback, useRef, useEffect } from 'react';
import ReactFlow, {
  addEdge,
  useNodesState,
  useEdgesState,
  Controls,
  Background,
  MiniMap,
  Panel,
  MarkerType,
  Handle,
  Position,
  ReactFlowProvider,
  useReactFlow,
} from 'reactflow';
import 'reactflow/dist/style.css';
import Button from '../UI/Button';

// ── Node style helpers ────────────────────────────────────────────────────────

const NODE_META = {
  TRIGGER:     { label: 'Trigger',      icon: '⚡', color: '#4f46e5', bg: '#eef2ff', desc: 'Fires when a lead is abandoned' },
  EMAIL:       { label: 'Send Email',   icon: '📧', color: '#10b981', bg: '#ecfdf5', desc: 'Send a personalised email' },
  DELAY:       { label: 'Wait / Delay', icon: '⏰', color: '#f59e0b', bg: '#fffbeb', desc: 'Pause before next step' },
  CONDITION:   { label: 'Condition',    icon: '🔀', color: '#ef4444', bg: '#fef2f2', desc: 'Branch Yes / No on lead data' },
  LIST_ASSIGN: { label: 'Assign List',  icon: '📋', color: '#8b5cf6', bg: '#f5f3ff', desc: 'Move lead into a list' },
  WEBHOOK:     { label: 'Webhook',      icon: '🔗', color: '#06b6d4', bg: '#ecfeff', desc: 'HTTP POST to external URL' },
  END:         { label: 'End',          icon: '🏁', color: '#6b7280', bg: '#f9fafb', desc: 'Marks funnel complete' },
};

const handleStyle = (color) => ({
  background: color,
  border: '2px solid #fff',
  width: 12,
  height: 12,
  boxShadow: '0 0 0 2px ' + color,
});

// ── Custom node components (defined OUTSIDE App — stable ref for ReactFlow) ───

function BaseNode({ data, selected, children, hasInput = true, hasOutput = true }) {
  const meta = NODE_META[data.nodeType] || NODE_META.EMAIL;
  return (
    <div style={{
      background: selected ? '#fff' : meta.bg,
      border: `2px solid ${selected ? meta.color : meta.color + '99'}`,
      borderRadius: 10,
      padding: '10px 14px',
      minWidth: 180,
      maxWidth: 220,
      boxShadow: selected ? `0 0 0 3px ${meta.color}33, 0 4px 12px rgba(0,0,0,0.12)` : '0 2px 6px rgba(0,0,0,0.08)',
      transition: 'all 0.15s',
      cursor: 'pointer',
      position: 'relative',
    }}>
      {hasInput  && <Handle type="target" position={Position.Top}    style={handleStyle(meta.color)} />}
      {hasOutput && <Handle type="source" position={Position.Bottom} style={handleStyle(meta.color)} />}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
        <span style={{ fontSize: 18, lineHeight: 1 }}>{meta.icon}</span>
        <span style={{ fontWeight: 700, fontSize: 12, color: '#1e293b', letterSpacing: '0.01em' }}>{meta.label}</span>
      </div>
      <div style={{ fontSize: 11, color: '#64748b', lineHeight: 1.4 }}>{children}</div>
    </div>
  );
}

const TriggerNode = ({ data, selected }) => (
  <BaseNode data={data} selected={selected} hasInput={false}>
    <span>After <strong>{data.settings?.delay ?? 30} min</strong> of inactivity</span>
  </BaseNode>
);

const EmailNode = ({ data, selected }) => (
  <BaseNode data={data} selected={selected}>
    <span>{data.settings?.subject ? `"${data.settings.subject.substring(0,30)}${data.settings.subject.length > 30 ? '…' : ''}"` : 'Click to configure'}</span>
    {data.settings?.provider && data.settings.provider !== 'smtp' && (
      <span style={{ display: 'block', marginTop: 2, color: '#10b981', fontWeight: 600 }}>via {data.settings.provider}</span>
    )}
  </BaseNode>
);

const DelayNode = ({ data, selected }) => (
  <BaseNode data={data} selected={selected}>
    <span>Wait <strong>{data.settings?.duration ?? 1} {data.settings?.unit ?? 'hours'}</strong></span>
  </BaseNode>
);

const ConditionNode = ({ data, selected }) => {
  const meta = NODE_META.CONDITION;
  return (
    <div style={{
      background: selected ? '#fff' : meta.bg,
      border: `2px solid ${selected ? meta.color : meta.color + '99'}`,
      borderRadius: 10,
      padding: '10px 14px',
      minWidth: 200,
      maxWidth: 240,
      boxShadow: selected ? `0 0 0 3px ${meta.color}33, 0 4px 12px rgba(0,0,0,0.12)` : '0 2px 6px rgba(0,0,0,0.08)',
      transition: 'all 0.15s',
      cursor: 'pointer',
    }}>
      <Handle type="target" position={Position.Top} style={handleStyle(meta.color)} />
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
        <span style={{ fontSize: 18, lineHeight: 1 }}>{meta.icon}</span>
        <span style={{ fontWeight: 700, fontSize: 12, color: '#1e293b' }}>{meta.label}</span>
      </div>
      <div style={{ fontSize: 11, color: '#64748b', marginBottom: 8 }}>
        {data.settings?.field ?? 'email'} {data.settings?.operator ?? 'equals'} "{data.settings?.value ?? ''}"
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10, fontWeight: 700 }}>
        <span style={{ color: '#10b981' }}>✓ YES</span>
        <span style={{ color: '#ef4444' }}>✗ NO</span>
      </div>
      <Handle type="source" position={Position.Bottom} id="yes" style={{ ...handleStyle('#10b981'), left: '25%' }} />
      <Handle type="source" position={Position.Bottom} id="no"  style={{ ...handleStyle('#ef4444'), left: '75%' }} />
    </div>
  );
};

const ListAssignNode = ({ data, selected }) => (
  <BaseNode data={data} selected={selected}>
    <span>{data.settings?.list_name ? `→ "${data.settings.list_name}"` : 'Select a list'}</span>
  </BaseNode>
);

const WebhookNode = ({ data, selected }) => (
  <BaseNode data={data} selected={selected}>
    <span style={{ wordBreak: 'break-all' }}>
      {data.settings?.url ? data.settings.url.replace('https://', '').substring(0, 28) + '…' : 'Enter URL'}
    </span>
  </BaseNode>
);

const EndNode = ({ data, selected }) => (
  <BaseNode data={data} selected={selected} hasOutput={false}>
    <span>Funnel complete</span>
  </BaseNode>
);

// Must be defined outside — stable reference prevents ReactFlow re-mounting nodes
const NODE_TYPES = {
  TRIGGER:     TriggerNode,
  EMAIL:       EmailNode,
  DELAY:       DelayNode,
  CONDITION:   ConditionNode,
  LIST_ASSIGN: ListAssignNode,
  WEBHOOK:     WebhookNode,
  END:         EndNode,
};

// ── Default settings per node type ────────────────────────────────────────────

function defaultSettings(type) {
  switch (type) {
    case 'TRIGGER':     return { delay: 30 };
    case 'EMAIL':       return { subject: '', body: '', provider: 'smtp' };
    case 'DELAY':       return { duration: 1, unit: 'hours' };
    case 'CONDITION':   return { field: 'country_code', operator: 'equals', value: '' };
    case 'LIST_ASSIGN': return { list_id: '', list_name: '' };
    case 'WEBHOOK':     return { url: '' };
    case 'END':         return {};
    default:            return {};
  }
}

// ── Edge defaults ─────────────────────────────────────────────────────────────

function makeEdge(params) {
  return {
    ...params,
    id: `e-${params.source}-${params.sourceHandle || ''}-${params.target}`,
    type: 'smoothstep',
    animated: false,
    style: { strokeWidth: 2, stroke: '#94a3b8' },
    markerEnd: { type: MarkerType.ArrowClosed, color: '#94a3b8', width: 18, height: 18 },
    label: params.sourceHandle === 'yes' ? 'YES' : params.sourceHandle === 'no' ? 'NO' : '',
    labelStyle: { fontSize: 10, fontWeight: 700 },
    labelBgStyle: { fill: params.sourceHandle === 'yes' ? '#ecfdf5' : params.sourceHandle === 'no' ? '#fef2f2' : '#f8fafc', fillOpacity: 0.9 },
  };
}

// ── Inner builder (needs ReactFlowProvider ancestor) ──────────────────────────

function FunnelBuilderInner({ funnel, onSave, onBack, lists }) {
  const { project } = useReactFlow();
  const wrapperRef   = useRef(null);
  const rfInstance   = useRef(null);

  // Convert stored funnel data → ReactFlow nodes/edges
  const initNodes = () => {
    const stored = Array.isArray(funnel?.nodes) ? funnel.nodes : [];
    if (stored.length === 0) {
      return [{
        id: 'trigger-1',
        type: 'TRIGGER',
        position: { x: 300, y: 60 },
        data: { nodeType: 'TRIGGER', settings: { delay: 30 } },
      }];
    }
    return stored.map(n => ({
      id: n.id,
      type: n.nodeType || n.type || 'EMAIL',
      position: n.position || { x: 100, y: 100 },
      data: { nodeType: n.nodeType || n.type || 'EMAIL', settings: n.settings || {} },
    }));
  };

  const initEdges = () => {
    const stored = Array.isArray(funnel?.edges) ? funnel.edges : [];
    return stored.map(e => makeEdge({
      source: e.source,
      target: e.target,
      sourceHandle: e.sourceHandle,
      targetHandle: e.targetHandle,
    }));
  };

  const [nodes, setNodes, onNodesChange] = useNodesState(initNodes());
  const [edges, setEdges, onEdgesChange] = useEdgesState(initEdges());
  const [selected,    setSelected]    = useState(null);  // selected node
  const [funnelName,  setFunnelName]  = useState(funnel?.name || 'Untitled Funnel');
  const [saving,      setSaving]      = useState(false);
  const [saveStatus,  setSaveStatus]  = useState(null);  // 'saved' | error msg
  const [dragOver,    setDragOver]    = useState(false);

  // Update selected node when nodes change (e.g. after settings update)
  useEffect(() => {
    if (!selected) return;
    const found = nodes.find(n => n.id === selected.id);
    if (found) setSelected(found);
  }, [nodes]);

  const onConnect = useCallback((params) => {
    setEdges(eds => addEdge(makeEdge(params), eds));
  }, [setEdges]);

  const onNodeClick = useCallback((_, node) => setSelected(node), []);
  const onPaneClick = useCallback(() => setSelected(null), []);

  // ── Drag from palette ────────────────────────────────────────────────────────
  const onDragStart = (e, nodeType) => {
    e.dataTransfer.setData('rf/nodeType', nodeType);
    e.dataTransfer.effectAllowed = 'move';
  };

  const onDragOver = useCallback((e) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = 'move';
    setDragOver(true);
  }, []);

  const onDragLeave = useCallback(() => setDragOver(false), []);

  const onDrop = useCallback((e) => {
    e.preventDefault();
    setDragOver(false);
    const nodeType = e.dataTransfer.getData('rf/nodeType');
    if (!nodeType || !wrapperRef.current) return;

    const bounds = wrapperRef.current.getBoundingClientRect();
    const position = project({
      x: e.clientX - bounds.left,
      y: e.clientY - bounds.top,
    });

    const id = `${nodeType.toLowerCase()}-${Date.now()}`;
    setNodes(nds => [...nds, {
      id,
      type: nodeType,
      position,
      data: { nodeType, settings: defaultSettings(nodeType) },
    }]);
  }, [project, setNodes]);

  // ── Update selected node settings ─────────────────────────────────────────
  const updateSettings = useCallback((settings, extra = {}) => {
    if (!selected) return;
    setNodes(nds => nds.map(n =>
      n.id === selected.id
        ? { ...n, data: { ...n.data, settings, ...extra } }
        : n
    ));
  }, [selected, setNodes]);

  // ── Delete selected node ───────────────────────────────────────────────────
  const deleteSelected = useCallback(() => {
    if (!selected || selected.data.nodeType === 'TRIGGER') return;
    setNodes(nds => nds.filter(n => n.id !== selected.id));
    setEdges(eds => eds.filter(e => e.source !== selected.id && e.target !== selected.id));
    setSelected(null);
  }, [selected, setNodes, setEdges]);

  // ── Keyboard delete ────────────────────────────────────────────────────────
  useEffect(() => {
    const handler = (e) => {
      if ((e.key === 'Delete' || e.key === 'Backspace') &&
          document.activeElement.tagName !== 'INPUT' &&
          document.activeElement.tagName !== 'TEXTAREA') {
        deleteSelected();
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [deleteSelected]);

  // ── Save ───────────────────────────────────────────────────────────────────
  const handleSave = async (status = 'draft') => {
    setSaving(true);
    setSaveStatus(null);
    try {
      await onSave({
        name:   funnelName,
        nodes:  nodes.map(n => ({
          id:       n.id,
          nodeType: n.data.nodeType,
          type:     n.data.nodeType,
          position: n.position,
          settings: n.data.settings,
        })),
        edges: edges.map(e => ({
          source:       e.source,
          target:       e.target,
          sourceHandle: e.sourceHandle || null,
          targetHandle: e.targetHandle || null,
        })),
        status,
      });
      setSaveStatus('saved');
      setTimeout(() => setSaveStatus(null), 2500);
    } catch (err) {
      setSaveStatus(err.message || 'Save failed');
    } finally {
      setSaving(false);
    }
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 90px)', background: '#f8fafc' }}>

      {/* ── Top bar ──────────────────────────────────────────────────────────── */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 12,
        padding: '10px 16px', background: '#fff',
        borderBottom: '1px solid #e2e8f0',
        flexShrink: 0, zIndex: 10,
        boxShadow: '0 1px 3px rgba(0,0,0,0.06)',
      }}>
        <button onClick={onBack} style={{
          display: 'flex', alignItems: 'center', gap: 6,
          background: 'none', border: '1px solid #e2e8f0',
          borderRadius: 8, padding: '6px 12px', cursor: 'pointer',
          fontSize: 13, color: '#64748b', fontWeight: 600,
          transition: 'all 0.15s',
        }}>
          ← Back
        </button>

        <div style={{ width: 1, height: 24, background: '#e2e8f0', flexShrink: 0 }} />

        <input
          value={funnelName}
          onChange={e => setFunnelName(e.target.value)}
          style={{
            border: 'none', outline: 'none', fontSize: 15,
            fontWeight: 700, color: '#0f172a', background: 'transparent',
            minWidth: 160, flex: 1, maxWidth: 320,
          }}
          placeholder="Funnel Name…"
        />

        <div style={{ flex: 1 }} />

        {saveStatus === 'saved' && (
          <span style={{ fontSize: 12, color: '#10b981', fontWeight: 600 }}>✓ Saved!</span>
        )}
        {saveStatus && saveStatus !== 'saved' && (
          <span style={{ fontSize: 12, color: '#ef4444', fontWeight: 600 }}>✗ {saveStatus}</span>
        )}

        <span style={{
          fontSize: 11, fontWeight: 700, padding: '3px 8px', borderRadius: 20,
          background: funnel?.status === 'active' ? '#ecfdf5' : '#f1f5f9',
          color: funnel?.status === 'active' ? '#059669' : '#64748b',
          textTransform: 'uppercase', letterSpacing: '0.05em',
        }}>
          {funnel?.status || 'draft'}
        </span>

        <Button variant="secondary" size="sm" onClick={() => handleSave('draft')} loading={saving}>
          Save Draft
        </Button>
        <Button variant="success" size="sm" onClick={() => handleSave('active')} loading={saving}>
          ✓ Publish
        </Button>
      </div>

      {/* ── Main area ────────────────────────────────────────────────────────── */}
      <div style={{ flex: 1, display: 'flex', overflow: 'hidden', minHeight: 0 }}>

        {/* ── Left: Node palette ──────────────────────────────────────────────── */}
        <div style={{
          width: 200, flexShrink: 0, background: '#fff',
          borderRight: '1px solid #e2e8f0',
          overflowY: 'auto', padding: '16px 12px',
        }}>
          <p style={{ fontSize: 10, fontWeight: 700, color: '#94a3b8', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 10 }}>
            Drag &amp; Drop
          </p>
          {Object.entries(NODE_META).map(([type, meta]) => (
            <div
              key={type}
              draggable
              onDragStart={e => onDragStart(e, type)}
              style={{
                display: 'flex', alignItems: 'center', gap: 10,
                padding: '9px 10px', borderRadius: 8, marginBottom: 6,
                border: `1.5px solid ${meta.color}44`,
                background: meta.bg,
                cursor: 'grab', userSelect: 'none',
                transition: 'all 0.15s',
              }}
              onMouseEnter={e => { e.currentTarget.style.borderColor = meta.color; e.currentTarget.style.boxShadow = '0 2px 8px rgba(0,0,0,0.1)'; }}
              onMouseLeave={e => { e.currentTarget.style.borderColor = meta.color + '44'; e.currentTarget.style.boxShadow = 'none'; }}
            >
              <span style={{ fontSize: 18, flexShrink: 0 }}>{meta.icon}</span>
              <div>
                <p style={{ fontSize: 11, fontWeight: 700, color: '#1e293b', lineHeight: 1.3 }}>{meta.label}</p>
                <p style={{ fontSize: 9.5, color: '#94a3b8', lineHeight: 1.3, marginTop: 1 }}>{meta.desc}</p>
              </div>
            </div>
          ))}

          <div style={{ marginTop: 16, padding: '10px', background: '#f0fdf4', borderRadius: 8, border: '1px solid #bbf7d0' }}>
            <p style={{ fontSize: 10, fontWeight: 700, color: '#15803d', marginBottom: 4 }}>Tip</p>
            <p style={{ fontSize: 10, color: '#166534', lineHeight: 1.5 }}>
              Drag nodes onto the canvas, then click &amp; drag between handles to connect them.
            </p>
          </div>
        </div>

        {/* ── Center: Canvas ───────────────────────────────────────────────────── */}
        <div ref={wrapperRef} style={{
          flex: 1, position: 'relative', overflow: 'hidden',
          background: dragOver ? '#f0f9ff' : '#f8fafc',
          transition: 'background 0.2s',
        }}>
          <ReactFlow
            nodes={nodes}
            edges={edges}
            onNodesChange={onNodesChange}
            onEdgesChange={onEdgesChange}
            onConnect={onConnect}
            onNodeClick={onNodeClick}
            onPaneClick={onPaneClick}
            onInit={inst => { rfInstance.current = inst; }}
            onDrop={onDrop}
            onDragOver={onDragOver}
            onDragLeave={onDragLeave}
            nodeTypes={NODE_TYPES}
            fitView
            fitViewOptions={{ padding: 0.3 }}
            deleteKeyCode={null}          // we handle delete manually
            defaultEdgeOptions={{
              type: 'smoothstep',
              style: { strokeWidth: 2, stroke: '#94a3b8' },
              markerEnd: { type: MarkerType.ArrowClosed, color: '#94a3b8', width: 18, height: 18 },
            }}
            connectionLineStyle={{ strokeWidth: 2, stroke: '#6366f1' }}
            attributionPosition="bottom-left"
          >
            <Controls style={{ bottom: 16, left: 16 }} />
            <MiniMap
              nodeColor={n => NODE_META[n.type]?.color || '#94a3b8'}
              maskColor="rgba(248,250,252,0.85)"
              style={{ bottom: 16, right: selected ? 326 : 16, width: 140, height: 90 }}
            />
            <Background gap={20} size={1} color="#e2e8f0" />
            <Panel position="top-right" style={{ background: '#fff', padding: '8px 12px', borderRadius: 8, border: '1px solid #e2e8f0', fontSize: 11, color: '#64748b', boxShadow: '0 1px 3px rgba(0,0,0,0.06)' }}>
              <strong style={{ color: '#1e293b' }}>{nodes.length}</strong> nodes &nbsp;·&nbsp; <strong style={{ color: '#1e293b' }}>{edges.length}</strong> connections
            </Panel>

            {dragOver && (
              <Panel position="top-center" style={{ background: '#dbeafe', border: '2px dashed #6366f1', borderRadius: 10, padding: '8px 20px', fontSize: 12, fontWeight: 700, color: '#4f46e5' }}>
                Drop to add node
              </Panel>
            )}
          </ReactFlow>
        </div>

        {/* ── Right: Config panel ──────────────────────────────────────────────── */}
        {selected && (
          <ConfigPanel
            node={selected}
            lists={lists}
            onUpdate={updateSettings}
            onDelete={selected.data.nodeType !== 'TRIGGER' ? deleteSelected : null}
            onClose={() => setSelected(null)}
          />
        )}
      </div>
    </div>
  );
}

// ── Config panel ─────────────────────────────────────────────────────────────

function ConfigPanel({ node, lists, onUpdate, onDelete, onClose }) {
  const meta = NODE_META[node.data.nodeType] || NODE_META.EMAIL;
  const [s, setS] = useState({ ...node.data.settings });

  // Sync if selected node changes externally
  useEffect(() => { setS({ ...node.data.settings }); }, [node.id]);

  const set = (key, val) => {
    const next = { ...s, [key]: val };
    setS(next);
    onUpdate(next);
  };

  const renderFields = () => {
    switch (node.data.nodeType) {
      case 'TRIGGER':
        return (
          <div className="space-y-4">
            <Field label="Delay after abandonment (minutes)">
              <input type="number" min={0} value={s.delay ?? 30} onChange={e => set('delay', +e.target.value)} className="rf-input" />
              <p className="text-xs text-slate-500 mt-1">Funnel starts this many minutes after the lead is marked abandoned.</p>
            </Field>
          </div>
        );

      case 'EMAIL':
        return (
          <div className="space-y-4">
            <Field label="Provider">
              <select value={s.provider || 'smtp'} onChange={e => set('provider', e.target.value)} className="rf-input">
                <option value="smtp">WordPress SMTP (free)</option>
                <option value="brevo">Brevo (Sendinblue)</option>
                <option value="sendgrid">SendGrid</option>
              </select>
            </Field>
            <Field label="Subject">
              <input type="text" value={s.subject || ''} onChange={e => set('subject', e.target.value)} className="rf-input" placeholder="You left something behind, {name}…" />
            </Field>
            <Field label="Body">
              <textarea rows={7} value={s.body || ''} onChange={e => set('body', e.target.value)} className="rf-input font-mono text-xs resize-y"
                placeholder={"Hi {name},\n\nWe noticed you started filling out our form...\n\n{recovery_link}"}
              />
              <p className="text-xs text-slate-500 mt-1">Tags: {'{name}'} {'{email}'} {'{recovery_link}'} {'{site_name}'} {'{form_name}'} {'{city}'} {'{country}'}</p>
            </Field>
          </div>
        );

      case 'DELAY':
        return (
          <div className="space-y-4">
            <div className="grid grid-cols-2 gap-3">
              <Field label="Duration">
                <input type="number" min={1} value={s.duration ?? 1} onChange={e => set('duration', +e.target.value)} className="rf-input" />
              </Field>
              <Field label="Unit">
                <select value={s.unit || 'hours'} onChange={e => set('unit', e.target.value)} className="rf-input">
                  <option value="minutes">Minutes</option>
                  <option value="hours">Hours</option>
                  <option value="days">Days</option>
                  <option value="weeks">Weeks</option>
                </select>
              </Field>
            </div>
          </div>
        );

      case 'CONDITION': {
        const FIELDS = ['country_code','country_name','city','region','email','status','form_id','form_name'];
        const OPS    = ['equals','not_equals','contains','not_contains','is_empty','is_not_empty'];
        const noValue = ['is_empty','is_not_empty'].includes(s.operator);
        return (
          <div className="space-y-4">
            <Field label="Field">
              <select value={s.field || 'country_code'} onChange={e => set('field', e.target.value)} className="rf-input">
                {FIELDS.map(f => <option key={f} value={f}>{f}</option>)}
              </select>
            </Field>
            <Field label="Operator">
              <select value={s.operator || 'equals'} onChange={e => set('operator', e.target.value)} className="rf-input">
                {OPS.map(op => <option key={op} value={op}>{op.replace(/_/g,' ')}</option>)}
              </select>
            </Field>
            {!noValue && (
              <Field label="Value">
                <input type="text" value={s.value || ''} onChange={e => set('value', e.target.value)} className="rf-input" placeholder="e.g. US" />
              </Field>
            )}
            <div className="bg-slate-50 rounded-lg p-3 text-xs text-slate-600">
              <p className="font-semibold mb-1">Branch outputs:</p>
              <p><span className="text-emerald-600 font-bold">● YES</span> — condition is true</p>
              <p className="mt-0.5"><span className="text-red-500 font-bold">● NO</span> — condition is false</p>
            </div>
          </div>
        );
      }

      case 'LIST_ASSIGN':
        return (
          <Field label="Assign lead to list">
            <select value={s.list_id || ''} onChange={e => {
              const sel = (lists || []).find(l => String(l.id) === e.target.value);
              setS({ list_id: e.target.value, list_name: sel?.name || '' });
              onUpdate({ list_id: e.target.value, list_name: sel?.name || '' });
            }} className="rf-input">
              <option value="">— Select a list —</option>
              {(lists || []).map(l => <option key={l.id} value={l.id}>{l.name}</option>)}
            </select>
          </Field>
        );

      case 'WEBHOOK':
        return (
          <div className="space-y-4">
            <Field label="Endpoint URL">
              <input type="url" value={s.url || ''} onChange={e => set('url', e.target.value)} className="rf-input" placeholder="https://hooks.zapier.com/…" />
            </Field>
            <div className="bg-blue-50 border border-blue-200 rounded-lg p-3 text-xs text-blue-700">
              RescueFill will POST lead data (JSON) to this URL when this node executes. HMAC-SHA256 signed.
            </div>
          </div>
        );

      case 'END':
        return <p className="text-sm text-slate-500">No configuration needed. This node marks the funnel enrollment as complete.</p>;

      default:
        return null;
    }
  };

  return (
    <div style={{
      width: 310, flexShrink: 0, background: '#fff',
      borderLeft: '1px solid #e2e8f0', overflowY: 'auto',
      display: 'flex', flexDirection: 'column',
    }}>
      {/* Header */}
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '12px 16px', borderBottom: '1px solid #e2e8f0',
        background: meta.bg, flexShrink: 0,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ fontSize: 20 }}>{meta.icon}</span>
          <div>
            <p style={{ fontSize: 13, fontWeight: 700, color: '#0f172a', lineHeight: 1.2 }}>{meta.label}</p>
            <p style={{ fontSize: 10, color: '#64748b', marginTop: 1 }}>Node settings</p>
          </div>
        </div>
        <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#94a3b8', fontSize: 18, lineHeight: 1, padding: '2px 4px' }}>×</button>
      </div>

      {/* Fields */}
      <div style={{ flex: 1, padding: '16px', overflowY: 'auto' }}>
        {renderFields()}
      </div>

      {/* Delete */}
      {onDelete && (
        <div style={{ padding: '12px 16px', borderTop: '1px solid #e2e8f0', flexShrink: 0 }}>
          <button
            onClick={onDelete}
            style={{
              width: '100%', padding: '8px', borderRadius: 8,
              background: '#fef2f2', border: '1.5px solid #fecaca',
              color: '#dc2626', fontSize: 12, fontWeight: 700, cursor: 'pointer',
            }}>
            🗑 Delete Node
          </button>
        </div>
      )}
    </div>
  );
}

function Field({ label, children }) {
  return (
    <div>
      <label style={{ display: 'block', fontSize: 12, fontWeight: 600, color: '#374151', marginBottom: 5 }}>{label}</label>
      {children}
    </div>
  );
}

// ── Public export wrapped in provider ────────────────────────────────────────

export default function FunnelBuilder(props) {
  return (
    <ReactFlowProvider>
      <FunnelBuilderInner {...props} />
    </ReactFlowProvider>
  );
}
