import React, { useState, useRef, useEffect, useCallback } from 'react';
import { Button, Switch, Input, InputNumber, Select, Tabs, Tooltip, message, Spin, Collapse, Dropdown, Modal, Radio } from 'antd';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
  faHashtag, faArrowLeft, faArrowUp, faArrowDown, faFloppyDisk, faEye, faRotateLeft, faRotateRight,
  faCopy, faTrash, faGear, faPalette, faPlus, faCircleInfo, faCode, faClock, faEyeSlash, faEllipsisVertical, faShieldHalved, faArrowsUpDownLeftRight,
} from '@fortawesome/free-solid-svg-icons';
import { _pg } from '../components/Header';
import EditorHeader from '../components/EditorHeader';
import * as api from '../services/api';
import { FIELD_TYPES, createField, getAllFieldTypes, getEnabledFieldTypes, isContainerField, flattenFields } from '../fields/fieldTypes.jsx';
import DynamicFieldOptions from '../fields/DynamicFieldOptions.jsx';
import ConditionalLogicOptions from '../fields/ConditionalLogicOptions.jsx';
import { getStyleGroups, STYLE_BLOCKS, NO_BOX_TYPES } from '../fields/SharedOptions.jsx';
import { __ } from '@wordpress/i18n';
import FieldPreview, { submitButtonStyles } from '../fields/FieldPreview.jsx';
import './form-editor.css';
import { applyFilters } from '../extend';

/**
 * Add-ons add field types with the `formglut.fieldTypes` filter and palette groups with
 * `formglut.fieldCategories` (see EXTENDING.md).
 */

// Configure message duration and placement
message.config({
  duration: 3,
  maxCount: 3,
  top: 24,
  placement: 'top',
});

let uid = 0;
function genId() { uid += 1; return 'f' + Date.now() + '_' + uid; }

/* ── CSS Parser Helper ──────────────────────────────────────────────── */

/**
 * Parse CSS string into style object
 * Handles CSS properties like "color: red; font-size: 14px;"
 */
/* ── Field tree helpers (column containers hold nested fields) ─────── */
const CONTAINER_GAPS = { none: 0, small: 8, medium: 16, large: 24 };
const PREVIEW_ICONS = { hidden: <FontAwesomeIcon icon={faEyeSlash} />, hash: <FontAwesomeIcon icon={faHashtag} />, code: <FontAwesomeIcon icon={faCode} /> };

// Apply fn(list, idx) to whichever list (top level or a column) holds `id`. Returns the new tree, or null if not found.
function updateParentList(list, id, fn) {
  const idx = list.findIndex(f => f.id === id);
  if (idx !== -1) return fn(list, idx);
  let found = false;
  const next = list.map(f => {
    if (found || !isContainerField(f)) return f;
    const columns = f.columns.map(col => {
      if (found) return col;
      const r = updateParentList(col.fields || [], id, fn);
      if (!r) return col;
      found = true;
      return { ...col, fields: r };
    });
    return found ? { ...f, columns } : f;
  });
  return found ? next : null;
}

function findFieldInTree(list, id) {
  for (const f of list) {
    if (f.id === id) return f;
    if (isContainerField(f)) {
      for (const col of f.columns) {
        const r = findFieldInTree(col.fields || [], id);
        if (r) return r;
      }
    }
  }
  return null;
}

// Returns { containerId, colIdx, index } describing where `id` lives.
function locateField(list, id, ctx = { containerId: null, colIdx: 0 }) {
  const idx = list.findIndex(f => f.id === id);
  if (idx !== -1) return { ...ctx, index: idx };
  for (const f of list) {
    if (!isContainerField(f)) continue;
    for (let ci = 0; ci < f.columns.length; ci++) {
      const r = locateField(f.columns[ci].fields || [], id, { containerId: f.id, colIdx: ci });
      if (r) return r;
    }
  }
  return null;
}

// Insert `field` at target { containerId, colIdx, index }; containerId null = top level.
function insertIntoTree(list, target, field) {
  const splice = (l) => { const n = [...l]; n.splice(Math.min(target.index ?? n.length, n.length), 0, field); return n; };
  if (!target.containerId) return splice(list);
  return updateParentList(list, target.containerId, (l, i) => l.map((f, j) => j !== i ? f : {
    ...f,
    columns: f.columns.map((col, ci) => ci === target.colIdx ? { ...col, fields: splice(col.fields || []) } : col),
  })) || list;
}

function cloneWithNewIds(field) {
  const copy = JSON.parse(JSON.stringify(field));
  (function reId(f) {
    f.id = genId();
    if (isContainerField(f)) f.columns.forEach(col => (col.fields || []).forEach(reId));
  })(copy);
  return copy;
}

/* ── Add Fields Tab ────────────────────────────────────────────────── */

function AddFieldsTab({ onAddField: addFieldFn, insertTarget, onCancelTarget }) {
  const [searchQuery, setSearchQuery] = React.useState('');
  const [proEnabled, setProEnabled] = React.useState(false);

  // Check if FormGlut Pro is enabled
  React.useEffect(() => {
    if (typeof window.formglut_admin !== 'undefined' && window.formglut_admin.pro_enabled) {
      setProEnabled(true);
    }
  }, []);

  function handleDragStart(e, fieldType) {
    e.dataTransfer.setData('fgFieldType', fieldType);
    e.dataTransfer.effectAllowed = 'copy';
  }

  function handleComingSoonClick(e) {
    e.preventDefault();
    e.stopPropagation();
    message.info(__('This field is not implemented yet', 'formglut'));
  }

  // Palette groups in display order; add-ons add theirs with formglut.fieldCategories.
  const categoryLabels = React.useMemo(() => applyFilters('formglut.fieldCategories', {
    general: __('General Fields', 'formglut'),
    advanced: __('Advanced Fields', 'formglut'),
    layout: __('Container Layouts', 'formglut'),
    payment: __('Payment Fields', 'formglut'),
    security: __('Security Fields', 'formglut'),
    upload: __('Upload Fields', 'formglut'),
    survey: __('Survey & Quiz', 'formglut'),
    wordpress: __('WordPress', 'formglut'),
  }), []);

  // Group fields by category and filter by search
  const groupedFields = React.useMemo(() => {
    const query = searchQuery.toLowerCase().trim();
    const groups = {};

    // Get all fields (free + pro from Pro plugin if active)
    const allFields = getAllFieldTypes();

    Object.entries(allFields).forEach(([key, cfg]) => {
      // Filter by search query
      if (query && !cfg.label.toLowerCase().includes(query)) {
        return;
      }

      const category = cfg.category || 'general';
      const isPro = cfg.pro || false;

      // Skip pro fields if pro is not enabled
      if (isPro && !proEnabled) {
        return;
      }

      if (!groups[category]) {
        groups[category] = [];
      }

      groups[category].push({
        key,
        label: cfg.label,
        icon: cfg.icon,
        pro: isPro,
        enabled: true,
        coming_soon: cfg.coming_soon || false,
      });
    });

    // Category order: the key order of the formglut.fieldCategories labels.
    const categoryOrder = Object.keys(categoryLabels);
    const orderedGroups = {};
    categoryOrder.forEach(cat => {
      if (groups[cat]) {
        orderedGroups[cat] = groups[cat];
      }
    });
    // Add any remaining categories not in the order list
    Object.keys(groups).forEach(cat => {
      if (!orderedGroups[cat]) {
        orderedGroups[cat] = groups[cat];
      }
    });

    return orderedGroups;
  }, [searchQuery, proEnabled, categoryLabels]);

  return (
    <div style={{ padding: '0 4px' }}>
      {insertTarget && (
        <div className="fg-insert-target-banner">
          <span>{insertTarget.afterId ? <>{__( 'Adding after', 'formglut' )} <strong>{insertTarget.afterLabel}</strong></> : <>{__( 'Adding to column', 'formglut' )} {insertTarget.colIdx + 1}</>}</span>
          <button type="button" onClick={onCancelTarget}>{__( 'Cancel', 'formglut' )}</button>
        </div>
      )}
      {/* Search Input */}
      <Input
        placeholder={__('Search fields...', 'formglut')}
        value={searchQuery}
        onChange={(e) => setSearchQuery(e.target.value)}
        allowClear
        prefix={<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ color: '#94a3b8' }}><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>}
        style={{ marginBottom: 16 }}
      />

      {/* Field Accordion */}
      <Collapse
        defaultActiveKey={['general']}
        bordered={false}
        size="small"
        style={{ background: 'transparent' }}
        items={Object.entries(groupedFields).map(([category, fields]) => ({
          key: category,
          label: <span style={{ fontWeight: 600, fontSize: 13 }}>{categoryLabels[category] || category}</span>,
          children: (
            <div className="fg-field-grid">
              {fields.map(ft => (
                <div
                  className={'fg-field-btn' + (ft.coming_soon ? ' fg-field-coming-soon' : '')}
                  key={ft.key}
                  draggable={!ft.coming_soon}
                  data-field-type={ft.key}
                  onDragStart={!ft.coming_soon ? (e) => handleDragStart(e, ft.key) : undefined}
                  onClick={!ft.coming_soon ? () => addFieldFn(ft.key) : handleComingSoonClick}
                >
                  <span className="fg-field-btn-icon">{ft.icon}</span>
                  <span className="fg-field-btn-label">{ft.label}</span>
                  {ft.coming_soon && <span className="fg-pro-badge fg-coming-soon-badge"><FontAwesomeIcon icon={faClock} /></span>}
                  
                </div>
              ))}
            </div>
          ),
        }))}
      />
    </div>
  );
}

/* ── Container Options ─────────────────────────────────────────────── */
function ContainerOptions({ field, onUpdate, allFields = [] }) {
  const up = (u) => onUpdate(field.id, u);
  const setWidth = (ci, w) => up({ columns: field.columns.map((c, i) => i === ci ? { ...c, width: Math.max(1, Number(w) || 1) } : c) });
  const equalize = () => {
    const n = field.columns.length;
    const w = Math.floor((100 / n) * 100) / 100;
    up({ columns: field.columns.map((c, i) => ({ ...c, width: i === n - 1 ? Math.round((100 - w * (n - 1)) * 100) / 100 : w })) });
  };
  const total = Math.round(field.columns.reduce((a, c) => a + (Number(c.width) || 0), 0) * 100) / 100;
  return (
    <div>
      <div className="fg-prop-section"><div className="fg-prop-section-title">{__( 'Columns', 'formglut' )}</div>
        {field.columns.map((col, ci) => (
          <div className="fg-prop-field" key={ci} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span className="fg-prop-label" style={{ marginBottom: 0, width: 80 }}>{__( 'Column', 'formglut' )} {ci + 1}</span>
            <InputNumber min={1} max={100} value={col.width} onChange={(v) => setWidth(ci, v)} addonAfter="%" style={{ flex: 1 }} />
          </div>
        ))}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: 12, color: total === 100 ? '#94a3b8' : '#f59e0b' }}>
          <span>{__( 'Total', 'formglut' )}: {total}%</span>
          <Button size="small" onClick={equalize}>{__( 'Equal widths', 'formglut' )}</Button>
        </div>
      </div>
      <div className="fg-prop-section"><div className="fg-prop-section-title">{__( 'Layout', 'formglut' )}</div>
        <div className="fg-prop-field"><div className="fg-prop-label">{__( 'Column Gap', 'formglut' )}</div>
          <Select value={field.gap || 'medium'} onChange={(v) => up({ gap: v })} style={{ width: '100%' }} options={[
            { value: 'none', label: __( 'None', 'formglut' ) },
            { value: 'small', label: __( 'Small (8px)', 'formglut' ) },
            { value: 'medium', label: __( 'Medium (16px)', 'formglut' ) },
            { value: 'large', label: __( 'Large (24px)', 'formglut' ) },
          ]} />
        </div>
        <div className="fg-prop-field" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span className="fg-prop-label" style={{ marginBottom: 0 }}>{__( 'Stack on mobile', 'formglut' )}</span>
          <Switch size="small" checked={field.responsive_stack !== false} onChange={(v) => up({ responsive_stack: v })} />
        </div>
        <div className="fg-prop-field"><div className="fg-prop-label">{__( 'Container CSS Class', 'formglut' )}</div>
          <Input value={field.container_class || ''} onChange={(e) => up({ container_class: e.target.value })} />
        </div>
        <div className="fg-prop-field" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <span className="fg-prop-label" style={{ marginBottom: 0 }}>{__( 'Hide these columns', 'formglut' )}</span>
          <Switch size="small" checked={!!field.hidden} onChange={(v) => up({ hidden: v })} />
        </div>
      </div>
      <div className="fg-prop-section"><div className="fg-prop-section-title">{__( 'Conditional Logic', 'formglut' )}</div>
        <ConditionalLogicOptions field={field} allFields={flattenFields(allFields).filter((f) => !flattenFields([field]).some((c) => c.id === f.id))} onUpdate={onUpdate} />
      </div>
    </div>
  );
}

/* ── Field Options Tab ─────────────────────────────────────────────── */

// "Check Pro Fields" link under the canvas toolbar; off for the first release.
// "Check Pro Fields" button in the editor footer; hidden once FormGlut Pro is active.
const SHOW_PRO_FIELDS_LINK = !(typeof window !== 'undefined' && window.formglut_admin && window.formglut_admin.pro_enabled);


/* ── Default submit button: settings (Field Options) and styling (Style Options) ── */

function SubmitButtonOptions({ submitBtn, onSubBtnUpdate, part }) {
    const updateSub = (key, val) => { const u = {}; u[key] = val; onSubBtnUpdate(u); };

    // Helper to render label with tooltip
    const renderLabel = (label, tooltip) => (
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
        <span className="fg-prop-label" style={{ marginBottom: 0 }}>{label}</span>
        {tooltip && (
          <Tooltip title={tooltip}>
            <FontAwesomeIcon icon={faCircleInfo} style={{ fontSize: 13, color: '#94a3b8', cursor: 'help', flexShrink: 0, marginTop: -1 }} />
          </Tooltip>
        )}
      </div>
    );

    if (part === 'style') {
      return (
      <div>
        <div className="fg-prop-section"><div className="fg-prop-section-title">{__( 'Button Styling', 'formglut' )}</div>
          <div className="fg-prop-field">{renderLabel(__( 'Background Color', 'formglut' ), __( 'The background color of the submit button.', 'formglut' ))}<div style={{ display: 'flex', gap: 8 }}><input type="color" value={submitBg(submitBtn.bg_color) || window.formglut_admin?.accent || '#e94560'} onChange={(e) => updateSub('bg_color', e.target.value)} style={{ width: 36, height: 36, border: '1px solid #e2e8f0', borderRadius: 6, cursor: 'pointer', padding: 2 }} /><Input value={submitBg(submitBtn.bg_color)} placeholder={__( 'Accent color', 'formglut' )} allowClear onChange={(e) => updateSub('bg_color', e.target.value)} style={{ flex: 1 }} /></div></div>
          <div className="fg-prop-field">{renderLabel(__( 'Text Color', 'formglut' ), __( 'The color of the text on the submit button.', 'formglut' ))}<div style={{ display: 'flex', gap: 8 }}><input type="color" value={submitBtn.text_color} onChange={(e) => updateSub('text_color', e.target.value)} style={{ width: 36, height: 36, border: '1px solid #e2e8f0', borderRadius: 6, cursor: 'pointer', padding: 2 }} /><Input value={submitBtn.text_color} onChange={(e) => updateSub('text_color', e.target.value)} style={{ flex: 1 }} /></div></div>
          <div className="fg-prop-field">{renderLabel(__( 'Border Radius (px)', 'formglut' ), __( 'Round the corners of the button. Higher values create more rounded corners.', 'formglut' ))}<Input type="number" value={submitBtn.border_radius} min={0} placeholder={String(DEFAULT_SUBMIT_BTN.border_radius)} onChange={(e) => updateSub('border_radius', e.target.value === '' ? undefined : Math.max(0, parseInt(e.target.value, 10) || 0))} /></div>
          <div className="fg-prop-field">{renderLabel(__( 'Font Size (px)', 'formglut' ), __( 'The size of the text on the button in pixels.', 'formglut' ))}<Input type="number" value={submitBtn.font_size} min={0} placeholder={String(DEFAULT_SUBMIT_BTN.font_size)} onChange={(e) => updateSub('font_size', e.target.value === '' ? undefined : Math.max(0, parseInt(e.target.value, 10) || 0))} /></div>
          <div className="fg-prop-field">{renderLabel(__( 'Font Weight', 'formglut' ), __( 'The thickness of the text. Bold makes the text more prominent.', 'formglut' ))}<Select value={submitBtn.font_weight} onChange={(v) => updateSub('font_weight', v)} style={{ width: '100%' }} options={[{ value: 400, label: __( 'Normal (400)', 'formglut' ) }, { value: 500, label: __( 'Medium (500)', 'formglut' ) }, { value: 600, label: __( 'Semi Bold (600)', 'formglut' ) }, { value: 700, label: __( 'Bold (700)', 'formglut' ) }]} /></div>
          <div className="fg-prop-field">{renderLabel(__( 'Height (px)', 'formglut' ), __( 'The height of the button in pixels.', 'formglut' ))}<Input type="number" value={submitBtn.height} min={0} placeholder={String(DEFAULT_SUBMIT_BTN.height)} onChange={(e) => updateSub('height', e.target.value === '' ? undefined : Math.max(0, parseInt(e.target.value, 10) || 0))} /></div>
        </div>
      </div>
      );
    }
    return (
      <div>
        <div className="fg-prop-section"><div className="fg-prop-section-title">{__( 'Button Settings', 'formglut' )}</div>
          <div className="fg-prop-field">{renderLabel(__( 'Button Text', 'formglut' ), __( 'The text displayed on the submit button.', 'formglut' ))}<Input value={submitBtn.text} onChange={(e) => updateSub('text', e.target.value)} /></div>
          <div className="fg-prop-field">{renderLabel(__( 'Button Text While Sending', 'formglut' ), __( 'Shown on the submit button while the form is being sent.', 'formglut' ))}<Input value={submitBtn.loading_text || ''} placeholder={__( 'Empty keeps the button text', 'formglut' )} onChange={(e) => updateSub('loading_text', e.target.value)} /></div>
          <div className="fg-prop-field">{renderLabel(__( 'Button Size', 'formglut' ), __( 'The preset size of the button. Small is compact, Large is more prominent.', 'formglut' ))}<Select value={submitBtn.size} onChange={(v) => updateSub('size', v)} style={{ width: '100%' }} options={[{ value: 'small', label: __( 'Small', 'formglut' ) }, { value: 'medium', label: __( 'Medium', 'formglut' ) }, { value: 'large', label: __( 'Large', 'formglut' ) }]} /></div>
          <div className="fg-prop-field">{renderLabel(__( 'Button Alignment', 'formglut' ), __( 'How the button is positioned within the form. Full Width stretches to fill the container.', 'formglut' ))}<Select value={submitBtn.alignment} onChange={(v) => updateSub('alignment', v)} style={{ width: '100%' }} options={[{ value: 'left', label: __( 'Left', 'formglut' ) }, { value: 'center', label: __( 'Center', 'formglut' ) }, { value: 'right', label: __( 'Right', 'formglut' ) }, { value: 'full', label: __( 'Full Width', 'formglut' ) }]} /></div>
        </div>
      </div>
    );
}

function FieldOptionsTab({ field, onUpdate, submitBtn, onSubBtnUpdate, selectedSubmit, allFields = [] }) {
  // Submit button options
  if (selectedSubmit) return <SubmitButtonOptions submitBtn={submitBtn} onSubBtnUpdate={onSubBtnUpdate} part="settings" />;

  if (isContainerField(field)) return <ContainerOptions field={field} onUpdate={onUpdate} allFields={allFields} />;

  // Use dynamic field options renderer
  return <DynamicFieldOptions field={field} onUpdate={onUpdate} allFields={allFields} />;
}

/* ── Style Options Tab ─────────────────────────────────────────────── */

function StyleOptionsTab({ field, onUpdate, submitBtn, onSubBtnUpdate, selectedSubmit }) {
  if (selectedSubmit) return <SubmitButtonOptions submitBtn={submitBtn} onSubBtnUpdate={onSubBtnUpdate} part="style" />;
  if (isContainerField(field)) {
    return (
      <div className="fg-prop-no-selection">
        <div className="fg-prop-no-selection-icon"><FontAwesomeIcon icon={faPalette} /></div>
        <div className="fg-prop-no-selection-text">{__( 'Containers have no style options.', 'formglut' )}<br/>{__( 'Use Field Options to set column widths and gap.', 'formglut' )}</div>
      </div>
    );
  }
  if (!field) {
    return (
      <div className="fg-prop-no-selection">
        <div className="fg-prop-no-selection-icon"><FontAwesomeIcon icon={faPalette} /></div>
        <div className="fg-prop-no-selection-text">{__( 'Select a field', 'formglut' )}<br/>{__( 'to edit its style', 'formglut' )}</div>
      </div>
    );
  }

  const up = (key, val) => { const u = {}; u[key] = val; onUpdate(field.id, u); };
  const styleGroups = getStyleGroups(field.type);
  const has = (group) => styleGroups.includes(group);

  // Helper to render label with tooltip
  const renderLabel = (label, tooltip) => (
    <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
      <span className="fg-prop-label" style={{ marginBottom: 0 }}>{label}</span>
      {tooltip && (
        <Tooltip title={tooltip}>
          <FontAwesomeIcon icon={faCircleInfo} style={{ fontSize: 13, color: '#94a3b8', cursor: 'help', flexShrink: 0, marginTop: -1 }} />
        </Tooltip>
      )}
    </div>
  );

  const colorSwatchStyle = { width: 36, height: 36, border: '1px solid #e2e8f0', borderRadius: 6, cursor: 'pointer', padding: 2 };
  const renderStyleControl = (c, i) => {
    // Controls that only apply with another setting (e.g. label width for left / right labels).
    if (c.showWhen && !c.showWhen.values.includes(field[c.showWhen.key] || '')) return null;
    if (c.boxOnly && NO_BOX_TYPES.includes(field.type)) return null;
    const label = renderLabel(__( c.label, 'formglut' ), c.tip && __( c.tip, 'formglut' ));
    if (c.type === 'select') {
      const value = field[c.key] || c.default;
      return (
        <React.Fragment key={c.key}>
          <div className="fg-prop-field">{label}
            <Select value={value} style={{ width: '100%' }}
              onChange={(v) => onUpdate(field.id, { [c.key]: v, ...(c.customKey && v !== 'custom' ? { [c.customKey]: '' } : {}) })}
              options={c.options.map(o => ({ value: o.value, label: __( o.label, 'formglut' ) }))} />
          </div>
          {c.customKey && field[c.key] === 'custom' && (
            <div className="fg-prop-field">{renderLabel(__( c.customLabel, 'formglut' ), __( c.customTip, 'formglut' ))}
              <Input type="number" value={field[c.customKey] || ''} placeholder={__( c.customPlaceholder, 'formglut' )} onChange={(e) => up(c.customKey, e.target.value)} addonAfter="px" />
            </div>
          )}
        </React.Fragment>
      );
    }
    if (c.type === 'quad') {
      return (
        <div className="fg-prop-field" key={c.keys[0]}>{label}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 6 }}>
            {c.keys.map((k, n) => (
              <div key={k}>
                <div style={{ fontSize: 11, color: '#94a3b8', marginBottom: 2 }}>{__( c.sides[n], 'formglut' )}</div>
                <Input type="number" size="small" min={0} value={field[k] ?? c.defaults[n]} onChange={(e) => up(k, e.target.value === '' ? undefined : Math.max(0, parseInt(e.target.value, 10) || 0))} />
              </div>
            ))}
          </div>
        </div>
      );
    }
    if (c.type === 'number') {
      return <div className="fg-prop-field" key={c.key}>{label}<Input type="number" min={0} value={field[c.key] ?? c.default} onChange={(e) => up(c.key, e.target.value === '' ? undefined : Math.max(0, parseInt(e.target.value, 10) || 0))} /></div>;
    }
    if (c.type === 'color') {
      const value = field[c.key] || c.default;
      return (
        <div className="fg-prop-field" key={c.key}>{label}
          <div style={{ display: 'flex', gap: 8 }}>
            <input type="color" value={value} onChange={(e) => up(c.key, e.target.value)} style={colorSwatchStyle} />
            <Input value={value} onChange={(e) => up(c.key, e.target.value)} style={{ flex: 1 }} />
            {field[c.key] && <Button onClick={() => up(c.key, undefined)} title={__( 'Back to the default colour', 'formglut' )}>{__( 'Reset', 'formglut' )}</Button>}
          </div>
        </div>
      );
    }
    return <div className="fg-prop-field" key={c.key || i}>{label}<Input value={field[c.key] || ''} placeholder={c.placeholder ? __( c.placeholder, 'formglut' ) : undefined} onChange={(e) => up(c.key, e.target.value)} /></div>;
  };

  return (
    <div>
      {/* Type badge */}
      <div style={{ marginBottom: 12, padding: '6px 10px', background: '#f8fafc', borderRadius: 6, fontSize: 12, color: '#64748b', display: 'flex', alignItems: 'center', gap: 6 }}>
        {getAllFieldTypes()[field.type]?.icon}<span style={{ fontWeight: 600 }}>{getAllFieldTypes()[field.type]?.label || field.type}</span>
      </div>

      {STYLE_BLOCKS.filter(block => has(block.group)).map(block => (
        <div className="fg-prop-section" key={block.group}>
          <div className="fg-prop-section-title">{__( block.title, 'formglut' )}</div>
          {block.controls.map((c, i) => renderStyleControl(c, i))}
        </div>
      ))}


      {/* Field-specific style options (moved from Field Options) */}
      <DynamicFieldOptions field={field} onUpdate={onUpdate} styleOnly />


    </div>
  );
}

/* ── Helpers ──────────────────────────────────────────────────────── */

function getFormIdFromUrl() {
  const params = new URLSearchParams(window.location.search);
  return params.get('form_id') ? parseInt(params.get('form_id'), 10) : null;
}


/** Three-dot menu beside the Shortcode button: put the form on a new or an existing page or post. */
function AddToContent({ formId }) {
  const [open, setOpen] = useState(false);
  const [mode, setMode] = useState('new');
  const [type, setType] = useState('page');
  const [title, setTitle] = useState('');
  const [postId, setPostId] = useState(null);
  const [options, setOptions] = useState([]);
  const [busy, setBusy] = useState(false);
  const timer = useRef(null);

  const load = useCallback((q) => {
    api.searchContent(q).then((res) => setOptions((res.data || res || []).map((p) => ({ value: p.id, label: `${p.title} (${p.type})` })))).catch(() => {});
  }, []);
  useEffect(() => { if (open && mode === 'existing' && !options.length) load(''); }, [open, mode]); // eslint-disable-line react-hooks/exhaustive-deps

  const submit = () => {
    setBusy(true);
    api.addFormToContent({ form_id: formId, mode, type, title, post_id: postId }).then((res) => {
      const d = res.data || res;
      message.success(mode === 'new' ? __( 'Draft created with the shortcode.', 'formglut' ) : __( 'Shortcode added.', 'formglut' ));
      setOpen(false);
      setTitle(''); setPostId(null);
      if (d.edit_url) window.open(d.edit_url, '_blank');
    }).catch((e) => message.error(e.message || __( 'Could not add the form.', 'formglut' ))).finally(() => setBusy(false));
  };

  const ghost = { color: '#fff', background: 'rgba(255,255,255,0.1)', borderColor: 'rgba(255,255,255,0.15)', borderRadius: 8 };
  return (
    <>
      <Dropdown trigger={['click']} disabled={!formId} menu={{ items: [{ key: 'add', label: __( 'Add to page or post', 'formglut' ) }], onClick: () => setOpen(true) }}>
        <Button aria-label={__( 'More shortcode options', 'formglut' )} icon={<FontAwesomeIcon icon={faEllipsisVertical} />} style={ghost} disabled={!formId} />
      </Dropdown>
      <Modal title={__( 'Add form to a page or post', 'formglut' )} open={open} onCancel={() => setOpen(false)} onOk={submit} confirmLoading={busy}
        okText={mode === 'new' ? __( 'Create', 'formglut' ) : __( 'Add shortcode', 'formglut' )} okButtonProps={{ disabled: mode === 'existing' && !postId }}>
        <Radio.Group value={mode} onChange={(e) => setMode(e.target.value)} style={{ marginBottom: 16 }}>
          <Radio.Button value="new">{__( 'Create new', 'formglut' )}</Radio.Button>
          <Radio.Button value="existing">{__( 'Use existing', 'formglut' )}</Radio.Button>
        </Radio.Group>
        {mode === 'new' ? (
          <div style={{ display: 'grid', gap: 12 }}>
            <Radio.Group value={type} onChange={(e) => setType(e.target.value)}>
              <Radio value="page">{__( 'Page', 'formglut' )}</Radio>
              <Radio value="post">{__( 'Post', 'formglut' )}</Radio>
            </Radio.Group>
            <Input value={title} onChange={(e) => setTitle(e.target.value)} placeholder={type === 'page' ? __( 'Page name', 'formglut' ) : __( 'Post name', 'formglut' )} />
            <span style={{ color: '#64748b', fontSize: 12 }}>{__( 'It is created as a draft with the form shortcode inside.', 'formglut' )}</span>
          </div>
        ) : (
          <div style={{ display: 'grid', gap: 12 }}>
            <Select showSearch filterOption={false} value={postId} onChange={setPostId} options={options} placeholder={__( 'Search pages and posts…', 'formglut' )}
              onSearch={(q) => { clearTimeout(timer.current); timer.current = setTimeout(() => load(q), 300); }} style={{ width: '100%' }} />
            <span style={{ color: '#64748b', fontSize: 12 }}>{__( 'The shortcode is added at the end of its content.', 'formglut' )}</span>
          </div>
        )}
      </Modal>
    </>
  );
}

// Copy text to clipboard with fallback for non-HTTPS contexts
function copyToClipboard(text) {
  // Try modern Clipboard API first
  if (navigator.clipboard && navigator.clipboard.writeText) {
    return navigator.clipboard.writeText(text).catch(() => {
      // Fallback if clipboard API fails
      return fallbackCopy(text);
    });
  }
  // Fallback for older browsers or non-secure contexts
  return fallbackCopy(text);
}

function fallbackCopy(text) {
  const textArea = document.createElement('textarea');
  textArea.value = text;
  textArea.style.position = 'fixed';
  textArea.style.left = '-999999px';
  textArea.style.top = '-999999px';
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();
  try {
    const successful = document.execCommand('copy');
    document.body.removeChild(textArea);
    return successful ? Promise.resolve() : Promise.reject(new Error('Copy command failed'));
  } catch (err) {
    document.body.removeChild(textArea);
    return Promise.reject(err);
  }
}

/** The old built-in pink means "no color set": the button follows the accent color (Global Settings › Appearance). */
const submitBg = (c) => (String(c || '').toLowerCase() === '#e94560' ? '' : (c || ''));

const DEFAULT_SUBMIT_BTN = {
  text: __( 'Submit Form', 'formglut' ), size: 'large', alignment: 'full',
  bg_color: '', text_color: '#ffffff', // Empty bg_color: the form accent color.
  border_radius: 10, font_size: 15, font_weight: 600, height: 48,
};

/** Canvas width and alignment: Form Settings › Layout (same as build_form_html()), limited by the device view. */
function canvasWrapperStyle(style, deviceWidth) {
  const st = {};
  const width = /^\d{1,4}(\.\d+)?(px|%|rem|em|vw)$/.test(style.form_width || '') ? style.form_width : '';
  if (width) st.maxWidth = width;
  if (style.form_align === 'center') { st.marginLeft = 'auto'; st.marginRight = 'auto'; }
  else if (style.form_align === 'right') { st.marginLeft = 'auto'; st.marginRight = 0; }
  else if (width) { st.marginLeft = 0; st.marginRight = 'auto'; }
  if (deviceWidth !== '100%') st.maxWidth = width ? `min(${width}, ${deviceWidth})` : deviceWidth;
  return st;
}

/* ── Main Editor ──────────────────────────────────────────────────── */

export default function FormEditor() {
  const [fields, setFields] = useState([]);
  const [selectedId, setSelectedId] = useState(null);
  const [activeTab, setActiveTab] = useState('addFields');
  const dragIdRef = useRef(null);
  const [submitBtn, setSubmitBtn] = useState({ ...DEFAULT_SUBMIT_BTN });
  const [selectedSubmit, setSelectedSubmit] = useState(false);
  const [dropTarget, setDropTarget] = useState(null);
  const [insertTarget, setInsertTarget] = useState(null);
  // Form Settings that change how the form looks (title, width, alignment, class, custom CSS).
  const [formSettings, setFormSettings] = useState({});

  const [formTitle, setFormTitle] = useState(__( 'Untitled Form', 'formglut' ));
  const [formId, setFormId] = useState(getFormIdFromUrl());
  const [deviceWidth, setDeviceWidth] = useState('100%');
  const [isDirty, setIsDirty] = useState(false);
  const [saving, setSaving] = useState(false);
  const [loading, setLoading] = useState(!!formId);

  const [history, setHistory] = useState([]);
  const [historyIdx, setHistoryIdx] = useState(-1);
  const initialLoadDone = useRef(false);

  /* ── History ─────────────────────────────────────────────────────── */

  const pushHistory = useCallback((newFields, newSubmitBtn) => {
    setHistory(prev => {
      const trimmed = prev.slice(0, historyIdx + 1);
      trimmed.push({ fields: newFields, submitBtn: { ...(newSubmitBtn || submitBtn) } });
      if (trimmed.length > 50) trimmed.shift();
      setHistoryIdx(trimmed.length - 1);
      return trimmed;
    });
  }, [historyIdx, submitBtn]);

  function undo() {
    if (historyIdx <= 0) return;
    const prev = history[historyIdx - 1];
    setHistoryIdx(historyIdx - 1);
    setFields(prev.fields);
    setSubmitBtn(prev.submitBtn);
    setIsDirty(true);
  }

  function redo() {
    if (historyIdx >= history.length - 1) return;
    const next = history[historyIdx + 1];
    setHistoryIdx(historyIdx + 1);
    setFields(next.fields);
    setSubmitBtn(next.submitBtn);
    setIsDirty(true);
  }

  /* ── Load ─────────────────────────────────────────────────────────── */

  useEffect(() => {
    if (!formId) { setLoading(false); return; }
    api.getForm(formId)
      .then(data => {
        const form = data.form;
        if (form.title) setFormTitle(form.title);
        if (form.settings && typeof form.settings === 'object') setFormSettings(form.settings);
        if (Array.isArray(form.fields)) setFields(form.fields);
        if (form.submit_btn && typeof form.submit_btn === 'object') {
          // Empty values fall back to the defaults, as on the live form (FormGlut_Form::submit_defaults()).
          setSubmitBtn({ ...DEFAULT_SUBMIT_BTN, ...Object.fromEntries(Object.entries(form.submit_btn).filter(([, v]) => v !== '' && v !== null)) });
        }
        setLoading(false);
      })
      .catch(err => { message.error(err.message || __( 'Failed to load form.', 'formglut' )); setLoading(false); });
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (!initialLoadDone.current && !loading) {
      setHistory([{ fields, submitBtn }]);
      setHistoryIdx(0);
      initialLoadDone.current = true;
    }
  }, [loading]); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    const h = (e) => { if (isDirty) { e.preventDefault(); e.returnValue = ''; } };
    window.addEventListener('beforeunload', h);
    return () => window.removeEventListener('beforeunload', h);
  }, [isDirty]);

  useEffect(() => {
    function onKey(e) {
      const mod = e.ctrlKey || e.metaKey;
      if (!mod) return;
      if (e.key === 'z' && !e.shiftKey) { e.preventDefault(); undo(); }
      else if ((e.key === 'z' && e.shiftKey) || e.key === 'y') { e.preventDefault(); redo(); }
      else if (e.key === 's') { e.preventDefault(); handleSave(); }
    }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  });

  /* ── Field ops ───────────────────────────────────────────────────── */
  function commit(next) { setFields(next); setIsDirty(true); pushHistory(next); }

  function addField(type) {
    const f = createField(type);
    if (!f) return;
    f.id = genId();
    const after = insertTarget && insertTarget.afterId ? locateField(fields, insertTarget.afterId) : null;
    if (after) {
      commit(insertIntoTree(fields, { containerId: after.containerId, colIdx: after.colIdx, index: after.index + 1 }, f));
    } else if (insertTarget && !insertTarget.afterId && !isContainerField(f) && findFieldInTree(fields, insertTarget.containerId)) {
      commit(insertIntoTree(fields, { ...insertTarget, index: Infinity }, f));
    } else {
      commit([...fields, f]);
    }
    setInsertTarget(null);
  }
  function removeField(id) {
    const next = updateParentList(fields, id, (l, i) => l.filter((_, j) => j !== i));
    if (!next) return;
    if (selectedId === id || (selectedId && !findFieldInTree(next, selectedId))) { setSelectedId(null); setActiveTab('addFields'); }
    if (insertTarget && !findFieldInTree(next, insertTarget.afterId || insertTarget.containerId)) setInsertTarget(null);
    commit(next);
  }
  function duplicateField(id) {
    const next = updateParentList(fields, id, (l, i) => {
      const copy = cloneWithNewIds(l[i]);
      if (!isContainerField(copy)) copy.label = (l[i].label || '') + ' (copy)';
      const n = [...l]; n.splice(i + 1, 0, copy); return n;
    });
    if (!next) return;
    commit(next);
    message.success(__( 'Field duplicated', 'formglut' ));
  }
  function moveField(id, dir) {
    const next = updateParentList(fields, id, (l, i) => {
      const ni = i + dir;
      if (ni < 0 || ni >= l.length) return l;
      const n = [...l]; [n[i], n[ni]] = [n[ni], n[i]]; return n;
    });
    if (next) commit(next);
  }
  function updateFieldProp(id, updates) {
    const next = updateParentList(fields, id, (l, i) => l.map((f, j) => j === i ? Object.assign({}, f, updates) : f));
    if (next) commit(next);
  }
  function selectField(id) { setSelectedId(id); setSelectedSubmit(false); setActiveTab('fieldOptions'); }
  function selectSubmitBtn() { setSelectedId(null); setSelectedSubmit(true); setActiveTab('fieldOptions'); }
  function targetColumn(containerId, colIdx) { setInsertTarget({ containerId, colIdx }); setActiveTab('addFields'); }

  /* ── Drag & drop ─────────────────────────────────────────────────── */
  const sameTarget = (a, b) => !!a && !!b && (a.containerId || null) === (b.containerId || null) && (a.colIdx || 0) === (b.colIdx || 0);

  function performDrop(e, target) {
    const type = e.dataTransfer.getData('fgFieldType');
    const dragId = dragIdRef.current;
    dragIdRef.current = null; setDropTarget(null);
    if (!target) target = { containerId: null, colIdx: 0, index: fields.length };

    if (type && getAllFieldTypes()[type]) {
      const f = createField(type); if (!f) return;
      f.id = genId();
      if (target.containerId && isContainerField(f)) { message.warning(__( 'Containers cannot be placed inside another container.', 'formglut' )); return; }
      commit(insertIntoTree(fields, target, f));
      return;
    }
    if (!dragId) return;
    const moving = findFieldInTree(fields, dragId);
    if (!moving) return;
    if (target.containerId && isContainerField(moving)) { message.warning(__( 'Containers cannot be placed inside another container.', 'formglut' )); return; }
    const from = locateField(fields, dragId);
    const without = updateParentList(fields, dragId, (l, i) => l.filter((_, j) => j !== i));
    let index = target.index;
    if (sameTarget(from, target) && from.index < index) index -= 1;
    commit(insertIntoTree(without, { ...target, index }, moving));
  }

  function handleCanvasDragOver(e) { e.preventDefault(); e.dataTransfer.dropEffect = dragIdRef.current ? 'move' : 'copy'; }
  function handleCanvasDrop(e) { e.preventDefault(); performDrop(e, dropTarget); }
  function handleCanvasDragLeave(e) { if (!e.currentTarget.contains(e.relatedTarget)) setDropTarget(null); }
  function handleEmptyDragOver(e) { e.preventDefault(); e.currentTarget.classList.add('drag-over'); setDropTarget(null); }
  function handleEmptyDragLeave(e) { e.currentTarget.classList.remove('drag-over'); }
  function handleEmptyDrop(e) {
    e.preventDefault(); e.stopPropagation(); e.currentTarget.classList.remove('drag-over');
    performDrop(e, null);
  }
  function handleFieldDragStart(e, id) { e.stopPropagation(); dragIdRef.current = id; e.dataTransfer.setData('fgReorder', 'true'); e.dataTransfer.effectAllowed = 'move'; }
  function handleFieldDragOver(e, ctx, idx) {
    e.preventDefault(); e.stopPropagation();
    const rect = e.currentTarget.getBoundingClientRect();
    const t = { ...ctx, index: e.clientY < rect.top + rect.height / 2 ? idx : idx + 1 };
    if (!dropTarget || !sameTarget(dropTarget, t) || dropTarget.index !== t.index) setDropTarget(t);
  }
  function handleColumnDragOver(e, ctx, len) {
    e.preventDefault(); e.stopPropagation();
    if (!dropTarget || !sameTarget(dropTarget, ctx) || dropTarget.index !== len) setDropTarget({ ...ctx, index: len });
  }
  function handleFieldDragEnd() { dragIdRef.current = null; setDropTarget(null); }

  /* ── Canvas rendering ────────────────────────────────────────────── */
  const dropIndicator = <div className="fg-drop-indicator visible"><span>{__( 'Drop here', 'formglut' )}</span></div>;
  const showIndicatorAt = (ctx, idx) => !!dropTarget && sameTarget(dropTarget, ctx) && dropTarget.index === idx;

  function renderFieldList(list, ctx) {
    return (
      <>
        {list.map((f, idx) => (
          <React.Fragment key={f.id}>
            {showIndicatorAt(ctx, idx) && dropIndicator}
            {renderFieldNode(f, idx, list.length, ctx)}
          </React.Fragment>
        ))}
        {showIndicatorAt(ctx, list.length) && dropIndicator}
      </>
    );
  }

  function renderFieldNode(f, idx, count, ctx) {
    const container = isContainerField(f);
    return (
      <div
        className={'fg-form-field' + (container ? ' fg-container-field' : '') + (container && f.container_class ? ' ' + f.container_class : '') + (selectedId === f.id ? ' selected' : '')}
        onClick={(e) => { e.stopPropagation(); selectField(f.id); }}
        draggable onDragStart={(e) => handleFieldDragStart(e, f.id)}
        onDragOver={(e) => handleFieldDragOver(e, ctx, idx)} onDragEnd={handleFieldDragEnd}
      >
        <div className="fg-field-toolbar">
          <Tooltip title={__( 'Move up', 'formglut' )} mouseEnterDelay={0.4}><button onClick={(e) => { e.stopPropagation(); moveField(f.id, -1); }} disabled={idx === 0} style={{ opacity: idx === 0 ? 0.3 : 1 }}><FontAwesomeIcon icon={faArrowUp} /></button></Tooltip>
          <Tooltip title={__( 'Move down', 'formglut' )} mouseEnterDelay={0.4}><button onClick={(e) => { e.stopPropagation(); moveField(f.id, 1); }} disabled={idx === count - 1} style={{ opacity: idx === count - 1 ? 0.3 : 1 }}><FontAwesomeIcon icon={faArrowDown} /></button></Tooltip>
          <div className="toolbar-sep"></div>
          <Tooltip title={__( 'Settings', 'formglut' )} mouseEnterDelay={0.4}><button onClick={(e) => { e.stopPropagation(); selectField(f.id); }}><FontAwesomeIcon icon={faGear} /></button></Tooltip>
          {!container && <Tooltip title={__( 'Style', 'formglut' )} mouseEnterDelay={0.4}><button onClick={(e) => { e.stopPropagation(); setSelectedId(f.id); setActiveTab('styleOptions'); }}><FontAwesomeIcon icon={faPalette} /></button></Tooltip>}
          <div className="toolbar-sep"></div>
          <Tooltip title={__( 'Duplicate', 'formglut' )} mouseEnterDelay={0.4}><button onClick={(e) => { e.stopPropagation(); duplicateField(f.id); }}><FontAwesomeIcon icon={faCopy} /></button></Tooltip>
          <Tooltip title={__( 'Delete', 'formglut' )} mouseEnterDelay={0.4}><button className="danger" onClick={(e) => { e.stopPropagation(); removeField(f.id); }}><FontAwesomeIcon icon={faTrash} /></button></Tooltip>
        </div>
        {container ? (
          <div className={'formglut-columns fg-columns' + (f.responsive_stack === false ? '' : ' formglut-columns-stack') + (f.hidden ? ' fg-dimmed' : '')} style={{ gap: (CONTAINER_GAPS[f.gap || 'medium'] ?? 16) + 'px' }}>
            {f.columns.map((col, ci) => {
              const colCtx = { containerId: f.id, colIdx: ci };
              const colFields = col.fields || [];
              const targeted = insertTarget && insertTarget.containerId === f.id && insertTarget.colIdx === ci;
              return (
                <div
                  key={ci}
                  className={'formglut-column fg-column' + (colFields.length ? '' : ' empty') + (targeted ? ' targeted' : '')}
                  style={{ flex: `${Number(col.width) || 1} 1 0%` }}
                  onDragOver={(e) => handleColumnDragOver(e, colCtx, colFields.length)}
                >
                  {renderFieldList(colFields, colCtx)}
                  <div className="fg-column-add" onClick={(e) => { e.stopPropagation(); targetColumn(f.id, ci); }}>
                    <FontAwesomeIcon icon={faPlus} />
                    {!colFields.length && <span>{targeted ? __( 'Pick a field on the left', 'formglut' ) : __( 'Add or drop a field', 'formglut' )}</span>}
                  </div>
                </div>
              );
            })}
          </div>
        ) : (
          <FieldPreview field={f} icons={PREVIEW_ICONS} />
        )}
        {!ctx.containerId && (
          <div className="fg-add-between">
            <div className="fg-add-between-btn" onClick={(e) => { e.stopPropagation(); setInsertTarget({ afterId: f.id, afterLabel: f.label || f.type }); setActiveTab('addFields'); }}><FontAwesomeIcon icon={faPlus} /></div>
          </div>
        )}
      </div>
    );
  }

  /* ── Save ────────────────────────────────────────────────────────── */

  async function handleSave() {
    if (saving) return;
    const title = formTitle.trim();
    if (!title) { message.warning(__( 'Please enter a form title.', 'formglut' )); return; }
    setSaving(true);
    try {
      // Status is not sent: new forms get the Default form status (Global Settings), and saving
      // keeps a form's current status (changed from All Forms).
      const payload = { title, fields, submit_btn: submitBtn };
      if (formId) {
        payload.id = formId;
        await api.updateForm(payload);
        message.success(__( 'Form saved.', 'formglut' ));
      } else {
        const result = await api.createForm(payload);
        setFormId(result.form_id);
        const url = new URL(window.location.href);
        url.searchParams.set('form_id', result.form_id);
        window.history.replaceState({}, '', url.toString());
        message.success(__( 'Form created.', 'formglut' ));
      }
      setIsDirty(false);
    } catch (err) { message.error(err.message || __( 'Failed to save form.', 'formglut' )); } finally { setSaving(false); }
  }

  const selectedField = selectedId ? findFieldInTree(fields, selectedId) : null;
  const updateSubmitBtn = (u) => { const next = { ...submitBtn, ...u }; setSubmitBtn(next); setIsDirty(true); pushHistory(fields, next); };
  const allInputFields = flattenFields(fields);

  if (loading) {
    return (<div style={{ height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#f8fafc' }}><Spin size="large" tip={__( 'Loading form...', 'formglut' )} /></div>);
  }

  return (
    <div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
      <EditorHeader formId={formId} title={formTitle} onTitleChange={(v) => { setFormTitle(v); setIsDirty(true); }} active="editor">
          <Tooltip title={__( 'Undo', 'formglut' )}><Button icon={<FontAwesomeIcon icon={faRotateLeft} />} size="small" type="text" style={{ color: 'rgba(255,255,255,0.7)' }} onClick={undo} disabled={historyIdx <= 0} /></Tooltip>
          <Tooltip title={__( 'Redo', 'formglut' )}><Button icon={<FontAwesomeIcon icon={faRotateRight} />} size="small" type="text" style={{ color: 'rgba(255,255,255,0.7)' }} onClick={redo} disabled={historyIdx >= history.length - 1} /></Tooltip>
          <Button icon={<FontAwesomeIcon icon={faEye} />} style={{ color: '#fff', background: 'rgba(255,255,255,0.1)', borderColor: 'rgba(255,255,255,0.15)', borderRadius: 8 }} onClick={() => { if (formId) { window.open(_pg.preview + '&form_id=' + formId, '_blank'); } else { message.warning(__( 'Save the form first to preview.', 'formglut' )); } }}>{__( 'Preview', 'formglut' )}</Button>
          <Tooltip title={formId ? `[formglut id="${formId}"]` : __( 'Save the form first to get shortcode.', 'formglut' )}>
            <Button icon={<FontAwesomeIcon icon={faCode} />} style={{ color: '#fff', background: 'rgba(255,255,255,0.1)', borderColor: 'rgba(255,255,255,0.15)', borderRadius: 8 }} disabled={!formId} onClick={() => { const shortcode = `[formglut id="${formId}"]`; copyToClipboard(shortcode).then(() => message.success(__( 'Shortcode copied!', 'formglut' ))).catch(() => message.error(__( 'Failed to copy shortcode.', 'formglut' ))); }}>
              {__( 'Shortcode', 'formglut' )}
            </Button>
          </Tooltip>
          <AddToContent formId={formId} />
          <Button icon={<FontAwesomeIcon icon={faFloppyDisk} />} type="primary" loading={saving} onClick={handleSave} style={{ background: 'var(--fg-accent)', borderColor: 'var(--fg-accent)', borderRadius: 8, fontWeight: 600 }}>
            {isDirty ? __( 'Save Form *', 'formglut' ) : __( 'Save Form', 'formglut' )}
          </Button>
              </EditorHeader>

      <div className="fg-editor-body">
        <div className="fg-sidebar">
          <Tabs activeKey={activeTab} onChange={setActiveTab} centered items={[
            { key: 'addFields', label: __( 'Add Fields', 'formglut' ), children: <AddFieldsTab onAddField={addField} insertTarget={insertTarget} onCancelTarget={() => setInsertTarget(null)} /> },
            { key: 'fieldOptions', label: __( 'Field Options', 'formglut' ), children: <FieldOptionsTab field={selectedField} onUpdate={updateFieldProp} submitBtn={submitBtn} onSubBtnUpdate={updateSubmitBtn} selectedSubmit={selectedSubmit} allFields={allInputFields} /> },
            { key: 'styleOptions', label: __( 'Style Options', 'formglut' ), children: <StyleOptionsTab field={selectedField} onUpdate={updateFieldProp} submitBtn={submitBtn} onSubBtnUpdate={updateSubmitBtn} selectedSubmit={selectedSubmit} /> },
          ]} />
        </div>

        <div className="fg-canvas-area">
          <div className="fg-canvas-toolbar">
            <div className="fg-device-switcher">
              <button className={"fg-device-btn" + (deviceWidth === '100%' ? ' active' : '')} onClick={() => setDeviceWidth('100%')} title="Desktop">
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
              </button>
              <button className={"fg-device-btn" + (deviceWidth === '640px' ? ' active' : '')} onClick={() => setDeviceWidth('640px')} title="Tablet">
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="12" y1="18" x2="12" y2="18.01"/></svg>
              </button>
              <button className={"fg-device-btn" + (deviceWidth === '480px' ? ' active' : '')} onClick={() => setDeviceWidth('480px')} title="Mobile">
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="5" y="2" width="14" height="20" rx="2"/><line x1="12" y1="18" x2="12" y2="18.01"/></svg>
              </button>
            </div>
            <div className="fg-undo-hint" style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
              <span>{fields.length} {fields.length !== 1 ? __( 'fields', 'formglut' ) : __( 'field', 'formglut' )}{isDirty ? ' — ' + __( 'unsaved', 'formglut' ) : ''}</span>
              {SHOW_PRO_FIELDS_LINK && (
              <button
                  type="button"
                  className="fg-pro-fields-btn"
                  onClick={() => window.open((_pg.pro_features || 'https://formglut.com/pro') + '#fields', '_blank')}
                >
                  <span className="fg-pro-fields-star">
                    <svg width="10" height="10" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/></svg>
                  </span>
                  <span>{__('Check Pro Fields', 'formglut')}</span>
                  <svg className="fg-pro-fields-arrow" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
                </button>
              )}
            </div>
          </div>
          <div className="fg-canvas">
            <div
              className={'formglut-form-wrapper fg-canvas-form' + (formSettings.general?.form_class ? ' ' + formSettings.general.form_class : '')}
              id={'formglut-form-' + (formId || 0)}
              style={canvasWrapperStyle(formSettings.style || {}, deviceWidth)}
              onClick={() => { setSelectedId(null); setSelectedSubmit(false); setInsertTarget(null); }} onDragOver={handleCanvasDragOver} onDrop={handleCanvasDrop} onDragLeave={handleCanvasDragLeave}
            >
              {formSettings.style?.custom_css && <style>{String(formSettings.style.custom_css).split('{form}').join('#formglut-form-' + (formId || 0))}</style>}
              <div className="formglut-form">
                {formSettings.general?.show_title && <h3 className="formglut-form-title">{formTitle}</h3>}
                {fields.length === 0 ? (
                  <div className="fg-empty-state" onDragOver={handleEmptyDragOver} onDragLeave={handleEmptyDragLeave} onDrop={handleEmptyDrop}>
                    <span className="fg-empty-state-icon"><FontAwesomeIcon icon={faPlus} /></span>
                    <div className="fg-empty-state-title">{__( 'Start building your form', 'formglut' )}</div>
                    <div className="fg-empty-state-desc">{__( 'Drag a field from the left panel and drop it here, or pick one to get started.', 'formglut' )}</div>
                    <span className="fg-empty-drag"><FontAwesomeIcon icon={faArrowsUpDownLeftRight} /></span>
                    <div className="fg-empty-hint"><span className="fg-empty-hint-dot" />{__( 'Drop fields anywhere in this area', 'formglut' )}</div>
                  </div>
                ) : (
                  <>
                    {renderFieldList(fields, { containerId: null, colIdx: 0 })}
                    {!allInputFields.some(x => x.type === 'custom_submit_button' && !x.hidden) && (() => {
                      const bs = submitButtonStyles(submitBtn);
                      return (
                        <div className={'fg-submit-field' + (selectedSubmit ? ' selected' : '')} onClick={(e) => { e.stopPropagation(); selectSubmitBtn(); }}>
                          <div className="formglut-form-actions" style={bs.actions}>
                            <button type="button" className="formglut-submit-btn" style={bs.button} tabIndex={-1}><span className="formglut-btn-text">{submitBtn.text || __( 'Submit', 'formglut' )}</span><span className="formglut-btn-spinner" style={{ display: 'none' }}>&nbsp;&hellip;</span></button>
                          </div>
                        </div>
                      );
                    })()}
                  </>
                )}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
