<?php
/**
 * Forms — create / edit a form.
 *
 * Uses a textarea DSL for the field list (parsed by FormsAPI). The
 * full drag-drop builder is a follow-up session. Webhook URLs are
 * one-per-line in another textarea — save replaces the list.
 */
require_once dirname(__DIR__, 3) . '/config.php';
require_once dirname(__DIR__) . '/FormsAPI.php';
require_once __DIR__ . '/_editor_ui.php';   // reusable record-editor UI kit

Auth::require();
Auth::requirePerm('forms.manage');
FormsAPI::ensureSchema();

$tid = current_tenant_id();

// ── Live preview: render the public form from the builder's current JSON
// (no save). The editor's "Preview" button POSTs fields_json_data here. ──
if (($_GET['preview'] ?? '') === '1' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    $arr = json_decode((string)($_POST['fields_json_data'] ?? ''), true);
    $pf  = is_array($arr) ? FormsAPI::normalizeFields($arr)['fields'] : [];
    $title = trim((string)($_POST['title'] ?? '')) ?: 'Form preview';
    $desc  = trim((string)($_POST['description'] ?? ''));
    $pvSet = FormsAPI::formSettings((string)($_POST['settings_json'] ?? ''));
    $cssUrl = plugin_url('forms', 'assets/css/public.css') . '?v=' . FormsAPI::ASSET_VERSION;
    $jsUrl  = plugin_url('forms', 'assets/js/forms-logic.js') . '?v=' . FormsAPI::ASSET_VERSION;
    header('Content-Type: text/html; charset=utf-8');
    echo '<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">';
    echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
    echo '<title>Preview · ' . e($title) . '</title>';
    slate_ui_emit_css();
    echo '<link rel="stylesheet" href="' . e($cssUrl) . '">';
    echo '</head><body class="forms-public">';
    echo '<div style="position:sticky;top:0;z-index:9;background:#111827;color:#fff;font:600 12px/1 -apple-system,sans-serif;padding:9px 14px;text-align:center;letter-spacing:.02em;">PREVIEW — changes here are not saved</div>';
    $pvMulti = false;
    foreach ($pf as $pff) { if (($pff['type'] ?? '') === 'step') { $pvMulti = true; break; } }
    echo '<main class="forms-public-shell"><article ' . FormsAPI::publicCardAttrs($pvSet) . '>';
    if ($pvMulti) {
        echo '<div class="forms-public-kicker">' . e($title) . '</div>';
    } else {
        echo '<header class="forms-public-header"><h1>' . e($title) . '</h1>';
        if ($desc !== '') echo '<p class="forms-public-desc">' . nl2br(e($desc)) . '</p>';
        echo '</header>';
    }
    echo '<form onsubmit="return false;" data-animate="' . ($pvSet['animate'] ? '1' : '0') . '" data-validate="' . ($pvSet['validate'] ? '1' : '0') . '">';
    if (!$pf) {
        echo '<p style="color:#64748B;">No fields yet — add some in the builder.</p>';
    } else {
        echo FormsAPI::renderFormBody($pf, [], [], 'Submit', ['rail' => $pvSet['rail']]);
    }
    echo '</form></article></main>';
    echo '<script src="' . e($jsUrl) . '" defer></script>';
    echo '</body></html>';
    exit;
}

$id   = (int)($_GET['id'] ?? 0);
$form = null;
$webhookUrlsText = '';

if ($id > 0) {
    $form = Database::row(
        "SELECT * FROM forms_definitions WHERE id = ? AND tenant_id = ?",
        [$id, $tid]
    );
    if (!$form) {
        http_response_code(404);
        require SLATE_ROOT . '/admin/partials/header.php';
        echo '<div class="card"><h1>Form not found</h1></div>';
        require SLATE_ROOT . '/admin/partials/footer.php';
        exit;
    }
    $hooks = Database::rows(
        "SELECT url FROM forms_webhooks WHERE form_id = ? AND tenant_id = ? AND is_active = 1 ORDER BY id",
        [$id, $tid]
    );
    $webhookUrlsText = implode("\n", array_column($hooks, 'url'));
}

$isNew = !$form;

// Defaults / form state
$state = [
    'title'             => $form['title']             ?? '',
    'slug'              => $form['slug']              ?? '',
    'description'       => $form['description']       ?? '',
    'fields_dsl'        => $form ? FormsAPI::fieldsToDsl(json_decode($form['fields_json'] ?? '[]', true) ?: []) : "text|full_name|Your name|required\nemail|email|Email|required\ntextarea|message|Message|required",
    'fields_json'       => $form['fields_json'] ?? '',
    'submit_label'      => $form['submit_label']      ?? 'Submit',
    'success_message'   => $form['success_message']   ?? 'Thanks — we got your submission. We\'ll be in touch.',
    'redirect_url'      => $form['redirect_url']      ?? '',
    'notify_email'      => $form['notify_email']      ?? '',
    'confirm_submitter' => (int)($form['confirm_submitter'] ?? 0),
    'confirm_subject'   => $form['confirm_subject']   ?? '',
    'confirm_body'      => $form['confirm_body']      ?? '',
    'submission_limit'  => $form['submission_limit']  ?? '',
    'status'            => $form['status']            ?? 'draft',
    'webhook_urls'      => $webhookUrlsText,
];

// Per-form appearance settings (density / animations / validation / rail).
$fset = FormsAPI::formSettings($form['settings_json'] ?? null);

$flash      = null;
$fieldErrors = [];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!csrf_verify()) {
        $flash = ['type' => 'error', 'msg' => 'Security check failed.'];
    } else {
        // Soak up posted state
        foreach (array_keys($state) as $k) {
            if (array_key_exists($k, $_POST)) {
                $state[$k] = is_string($_POST[$k]) ? $_POST[$k] : $state[$k];
            }
        }
        $state['confirm_submitter'] = !empty($_POST['confirm_submitter']) ? 1 : 0;

        // Appearance settings
        $fset['density']  = (($_POST['fs_density'] ?? '') === 'compact') ? 'compact' : 'comfortable';
        $fset['animate']  = !empty($_POST['fs_animate']);
        $fset['validate'] = !empty($_POST['fs_validate']);
        $fset['rail']     = !empty($_POST['fs_rail']);
        if (!empty($_POST['fs_accent_on'])) {
            $fset['accent']       = FormsAPI::sanitizeHex((string)($_POST['fs_accent'] ?? ''));
            $fset['accent_hover'] = FormsAPI::sanitizeHex((string)($_POST['fs_accent_hover'] ?? ''));
        } else {
            $fset['accent'] = '';
            $fset['accent_hover'] = '';
        }
        $fset['field_style'] = (($_POST['fs_field_style'] ?? '') === 'filled') ? 'filled' : 'outline';
        $fset['shape']       = in_array(($_POST['fs_shape'] ?? 'rounded'), ['rounded', 'pill', 'square'], true) ? $_POST['fs_shape'] : 'rounded';
        $fset['labels']      = !empty($_POST['fs_hide_labels']) ? 'hide' : 'show';
        $fset['pdf_attach']  = !empty($_POST['fs_pdf_attach']);

        // Validate
        $title = trim($state['title']);
        if ($title === '') {
            $fieldErrors['title'] = 'Title is required.';
        }
        if ($state['notify_email'] !== '' && !filter_var($state['notify_email'], FILTER_VALIDATE_EMAIL)) {
            $fieldErrors['notify_email'] = 'Notify email is not a valid email address.';
        }
        if ($state['redirect_url'] !== '' && !filter_var($state['redirect_url'], FILTER_VALIDATE_URL)) {
            $fieldErrors['redirect_url'] = 'Redirect URL is not valid.';
        }

        // Prefer the visual builder's JSON (carries advanced field metadata —
        // conditions, formulas, steps); fall back to the DSL textarea.
        $jsonRaw = (string)($_POST['fields_json_data'] ?? '');
        $jsonArr = $jsonRaw !== '' ? json_decode($jsonRaw, true) : null;
        if (is_array($jsonArr) && $jsonArr) {
            $parsed = FormsAPI::normalizeFields($jsonArr);
        } else {
            $parsed = FormsAPI::parseFieldDsl($state['fields_dsl']);
        }
        if (!empty($parsed['errors'])) {
            $fieldErrors['fields_dsl'] = implode(' ', $parsed['errors']);
        }
        if (empty($parsed['fields'])) {
            $fieldErrors['fields_dsl'] = ($fieldErrors['fields_dsl'] ?? '') . ' At least one field is required.';
        }
        // Canonical JSON for the builder to re-read on re-render (keeps advanced props).
        $state['fields_json'] = json_encode($parsed['fields'], JSON_UNESCAPED_UNICODE);

        // Parse webhook URLs
        $hookUrls = [];
        foreach (preg_split('/\r\n|\n|\r/', $state['webhook_urls']) as $line) {
            $u = trim($line);
            if ($u === '') continue;
            if (!filter_var($u, FILTER_VALIDATE_URL)) {
                $fieldErrors['webhook_urls'] = 'One or more webhook URLs are invalid.';
                continue;
            }
            $hookUrls[] = $u;
        }

        if (empty($fieldErrors)) {
            $slug = trim($state['slug']);
            if ($slug === '') {
                $slug = FormsAPI::slugify($title, $isNew ? null : $id);
            } else {
                // Normalise + de-dup
                $slug = FormsAPI::slugify($slug, $isNew ? null : $id);
            }

            $row = [
                'tenant_id'         => $tid,
                'slug'              => $slug,
                'title'             => $title,
                'description'       => $state['description'] !== '' ? $state['description'] : null,
                'fields_json'       => json_encode($parsed['fields'], JSON_UNESCAPED_UNICODE),
                'submit_label'      => $state['submit_label'] !== '' ? $state['submit_label'] : 'Submit',
                'success_message'   => $state['success_message'] !== '' ? $state['success_message'] : null,
                'redirect_url'      => $state['redirect_url'] !== '' ? $state['redirect_url'] : null,
                'notify_email'      => $state['notify_email'] !== '' ? $state['notify_email'] : null,
                'confirm_submitter' => (int)$state['confirm_submitter'],
                'confirm_subject'   => $state['confirm_subject'] !== '' ? $state['confirm_subject'] : null,
                'confirm_body'      => $state['confirm_body'] !== '' ? $state['confirm_body'] : null,
                'submission_limit'  => $state['submission_limit'] !== '' && is_numeric($state['submission_limit'])
                                        ? (int)$state['submission_limit'] : null,
                'status'            => in_array($state['status'], ['draft','published','archived'], true)
                                        ? $state['status'] : 'draft',
                'settings_json'     => json_encode($fset, JSON_UNESCAPED_UNICODE),
            ];

            if ($isNew) {
                $id = Database::insert('forms_definitions', $row);
                AuditLog::record('forms.created', (string)$id, ['slug' => $slug]);
                $flash = ['type' => 'success', 'msg' => 'Form created.'];
                $isNew = false;
            } else {
                Database::update('forms_definitions', $row, 'id = ? AND tenant_id = ?', [$id, $tid]);
                AuditLog::record('forms.updated', (string)$id);
                $flash = ['type' => 'success', 'msg' => 'Form saved.'];
            }

            // Sync webhooks: simple replace strategy.
            Database::delete('forms_webhooks', 'form_id = ? AND tenant_id = ?', [$id, $tid]);
            foreach ($hookUrls as $u) {
                Database::insert('forms_webhooks', [
                    'tenant_id' => $tid,
                    'form_id'   => $id,
                    'url'       => $u,
                    'is_active' => 1,
                ]);
            }

            // Re-read the saved state so the form reflects what's stored
            $form = Database::row("SELECT * FROM forms_definitions WHERE id = ?", [$id]);
            $state['slug']        = $form['slug'];
            $state['fields_dsl']  = FormsAPI::fieldsToDsl($parsed['fields']);
            $state['webhook_urls'] = implode("\n", $hookUrls);
        } else {
            $flash = ['type' => 'error', 'msg' => 'Please fix the highlighted fields.'];
        }
    }
}

$pageTitle  = $isNew ? __('forms_new', 'New form') : ($state['title'] !== '' ? $state['title'] : __('forms_edit', 'Edit form'));
$currentNav = 'forms';

// Hero stats + live status pill mapping.
$subCount   = (!$isNew && $id) ? (int) Database::value(
    "SELECT COUNT(*) FROM forms_submissions WHERE tenant_id = ? AND form_id = ?", [$tid, $id]) : 0;
$fieldCount = count(FormsAPI::parseFieldDsl($state['fields_dsl'])['fields'] ?? []);
$statusMap  = [
    'published' => ['tone' => 'on',   'text' => 'Published'],
    'draft'     => ['tone' => 'warn', 'text' => 'Draft'],
    'archived'  => ['tone' => 'off',  'text' => 'Archived'],
];
$curStatus  = $statusMap[$state['status']] ?? $statusMap['draft'];

require SLATE_ROOT . '/admin/partials/header.php';

$publicUrl = ($state['slug'] !== '' && !$isNew) ? SLATE_URL . '/forms/' . $state['slug'] : null;
?>

<?php slate_breadcrumbs([
    ['label' => __('dashboard', 'Dashboard'), 'href' => SLATE_URL . '/admin/'],
    ['label' => __('forms', 'Forms'), 'href' => plugin_url('forms', 'admin/index.php')],
    ['label' => $isNew ? 'New form' : $state['title']],
]); ?>

<?php if ($flash): ?>
    <div class="alert alert-<?= e($flash['type']) ?>" role="status"><?= e($flash['msg']) ?></div>
<?php endif; ?>

<?php forms_editor_css(); ?>

<?php forms_edit_open(['title_fallback' => 'New form']); ?>

<form method="post">
    <?= csrf_field() ?>

    <?php forms_edit_backlink([
        'back_href'  => plugin_url('forms', 'admin/index.php'),
        'back_label' => 'All forms',
    ]); ?>

    <?php forms_edit_hero([
        'icon'        => 'box',
        'title'       => $isNew ? 'New form' : ($state['title'] !== '' ? $state['title'] : 'Untitled form'),
        'ref'         => $isNew ? null : (int)$id,
        'status_text' => $curStatus['text'],
        'status_tone' => $curStatus['tone'],
        'status_map'  => $statusMap,
        'stats'       => $isNew ? [] : [
            ['Submissions', number_format($subCount)],
            ['Fields',      number_format($fieldCount)],
            ['Created',     !empty($form['created_at']) ? '<small>' . e(date('j M Y', strtotime($form['created_at']))) . '</small>' : '—'],
        ],
    ]); ?>

    <?php forms_edit_tabs([
        ['id' => 'general',    'label' => 'General',      'icon' => 'box'],
        ['id' => 'fields',     'label' => 'Fields',       'icon' => 'list'],
        ['id' => 'appearance', 'label' => 'Appearance',   'icon' => 'star'],
        ['id' => 'after',      'label' => 'After submit', 'icon' => 'check'],
        ['id' => 'notify',     'label' => 'Notifications','icon' => 'mail'],
        ['id' => 'webhooks',   'label' => 'Webhooks',     'icon' => 'link'],
    ]); ?>

            <div class="pv-panel" data-panel="general">
            <?php forms_edit_card_open(['icon' => 'box', 'eyebrow' => 'General', 'title' => 'Form details']); ?>

                <div class="field">
                    <label class="field-label" for="title">Title <span class="field-required">*</span></label>
                    <input type="text" id="title" name="title" required maxlength="200"
                           value="<?= e($state['title']) ?>">
                    <?php if (!empty($fieldErrors['title'])): ?>
                        <div class="field-error"><?= e($fieldErrors['title']) ?></div>
                    <?php endif; ?>
                </div>

                <div class="field-row field-row-2">
                    <div class="field">
                        <label class="field-label" for="slug">URL slug</label>
                        <input type="text" id="slug" name="slug" maxlength="80"
                               value="<?= e($state['slug']) ?>"
                               placeholder="<?= e($isNew ? 'auto-generated from title' : '') ?>">
                        <div class="field-hint">Lowercase letters / digits / hyphens. Leave blank to auto-generate.</div>
                    </div>
                    <div class="field">
                        <label class="field-label" for="status">Status</label>
                        <select id="status" name="status">
                            <option value="draft"     <?= $state['status'] === 'draft'     ? 'selected' : '' ?>>Draft (not public)</option>
                            <option value="published" <?= $state['status'] === 'published' ? 'selected' : '' ?>>Published (live)</option>
                            <option value="archived"  <?= $state['status'] === 'archived'  ? 'selected' : '' ?>>Archived</option>
                        </select>
                    </div>
                </div>

                <div class="field" style="margin-bottom:0;">
                    <label class="field-label" for="description">Description</label>
                    <textarea id="description" name="description" maxlength="1000"><?= e($state['description']) ?></textarea>
                    <div class="field-hint">Shown above the form on the public page.</div>
                </div>

            <?php forms_edit_card_close(); ?>

            <?php if (!$isNew && $state['status'] === 'published' && $publicUrl): ?>
                <?php forms_edit_card_open(['icon' => 'link', 'eyebrow' => 'Live', 'title' => 'Share & embed']); ?>
                    <div class="field">
                        <label class="field-label">Public URL</label>
                        <p style="margin:0;"><a href="<?= e($publicUrl) ?>" target="_blank"><?= e($publicUrl) ?></a></p>
                    </div>
                    <div class="field" style="margin-bottom:0;">
                        <label class="field-label">Embed snippet</label>
                        <pre class="snippet" style="white-space:pre-wrap;">&lt;iframe src=&quot;<?= e($publicUrl) ?>?embed=1&quot;
  style=&quot;width:100%;border:0;min-height:520px&quot;&gt;
&lt;/iframe&gt;</pre>
                    </div>
                <?php forms_edit_card_close(); ?>
            <?php endif; ?>
            </div>

            <div class="pv-panel" data-panel="fields" hidden>
            <?php forms_edit_card_open([
                'icon'       => 'list',
                'eyebrow'    => 'Fields',
                'title'      => 'Form fields',
                'aside_html' => '<button type="button" class="btn btn-sm btn-primary" id="fb-preview">Preview</button> <button type="button" class="btn btn-sm" id="fb-toggle">Advanced (DSL)</button>',
            ]); ?>
            <div id="fb-card">
                <input type="hidden" name="fields_json_data" id="fields_json_data" value="<?= e($state['fields_json']) ?>">

                <div class="fb-palette" id="fb-palette">
                    <span class="fb-palette-label">Add a field</span>
                    <button type="button" class="fb-add" data-type="text">Text</button>
                    <button type="button" class="fb-add" data-type="textarea">Paragraph</button>
                    <button type="button" class="fb-add" data-type="email">Email</button>
                    <button type="button" class="fb-add" data-type="tel">Phone</button>
                    <button type="button" class="fb-add" data-type="number">Number</button>
                    <button type="button" class="fb-add" data-type="date">Date</button>
                    <button type="button" class="fb-add" data-type="url">URL</button>
                    <button type="button" class="fb-add" data-type="select">Dropdown</button>
                    <button type="button" class="fb-add" data-type="radio">Choice</button>
                    <button type="button" class="fb-add" data-type="checkbox">Checkbox</button>
                    <button type="button" class="fb-add" data-type="time">Time</button>
                    <button type="button" class="fb-add" data-type="range">Slider</button>
                    <button type="button" class="fb-add" data-type="rating">Rating</button>
                    <button type="button" class="fb-add" data-type="calc">Calculated</button>
                    <button type="button" class="fb-add" data-type="file">File</button>
                    <button type="button" class="fb-add" data-type="signature">Signature</button>
                    <button type="button" class="fb-add" data-type="heading">Heading</button>
                    <button type="button" class="fb-add" data-type="step">Step break</button>
                    <button type="button" class="fb-add" data-type="hidden">Hidden</button>
                </div>

                <div class="fb-list" id="fb-list"></div>
                <div class="fb-empty" id="fb-empty">No fields yet — click a type above to add one. Drag the ⠿ handle to reorder.</div>

                <!-- Always-posted source of truth; the builder writes here. Power
                     users can edit it directly via the Advanced toggle. -->
                <div class="field" id="fb-advanced" hidden>
                    <label class="field-label" for="fields_dsl">Field DSL — <code>type|name|label|required|placeholder|options</code></label>
                    <textarea id="fields_dsl" name="fields_dsl" rows="14"
                              style="font-family:var(--font-mono); font-size:12.5px; min-height:240px;"
                              spellcheck="false"><?= e($state['fields_dsl']) ?></textarea>
                    <div class="field-hint">
                        Supported types: text, email, tel, url, number, date, time, textarea, select, radio,
                        checkbox, range, rating, file, signature, heading, hidden.
                        Options column = comma-separated choices (<code>select</code>/<code>radio</code>),
                        <code>min,max,step</code> (range) or max-stars (rating). Switch back to the visual builder to sync.
                    </div>
                    <ul class="kv-list" style="margin-top:12px;border-top:1px solid var(--border);padding-top:12px;">
                        <li class="kv-row"><span class="kv-label kv-mono">type</span><span class="kv-value">text · email · tel · url · number · date · time · textarea · select · radio · checkbox · range · rating · calc · file · signature · heading · step · hidden</span></li>
                        <li class="kv-row"><span class="kv-label kv-mono">advanced</span><span class="kv-value">conditional visibility, calculated formulas and step breaks are set in the <strong>visual builder</strong> (not the DSL)</span></li>
                        <li class="kv-row"><span class="kv-label kv-mono">name</span><span class="kv-value">lowercase, letters/digits/underscores</span></li>
                        <li class="kv-row"><span class="kv-label kv-mono">label</span><span class="kv-value">shown next to the input</span></li>
                        <li class="kv-row"><span class="kv-label kv-mono">required</span><span class="kv-value">literal word <code>required</code></span></li>
                        <li class="kv-row"><span class="kv-label kv-mono">placeholder</span><span class="kv-value">optional hint</span></li>
                        <li class="kv-row"><span class="kv-label kv-mono">options</span><span class="kv-value">for select/radio, comma-separated</span></li>
                    </ul>
                </div>
                <?php if (!empty($fieldErrors['fields_dsl'])): ?>
                    <div class="field-error" style="margin-top:8px;"><?= e($fieldErrors['fields_dsl']) ?></div>
                <?php endif; ?>
            </div>
            <?php forms_edit_card_close(); ?>
            </div>

            <div class="pv-panel" data-panel="appearance" hidden>
            <?php forms_edit_card_open(['icon' => 'star', 'eyebrow' => 'Appearance', 'title' => 'Look & feel']); ?>
                <div class="field">
                    <label class="field-label" for="fs_density">Density</label>
                    <select id="fs_density" name="fs_density">
                        <option value="comfortable" <?= $fset['density'] === 'comfortable' ? 'selected' : '' ?>>Comfortable (roomy)</option>
                        <option value="compact"     <?= $fset['density'] === 'compact'     ? 'selected' : '' ?>>Compact (tighter)</option>
                    </select>
                    <div class="field-hint">Compact tightens spacing, padding and type sizes on the public form.</div>
                </div>
                <div class="field" style="margin-bottom:8px;">
                    <label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;">
                        <input type="checkbox" name="fs_animate" value="1" <?= $fset['animate'] ? 'checked' : '' ?>>
                        <span>Step animations <span class="text-muted text-xs">— directional slide + staggered field entrance</span></span>
                    </label>
                </div>
                <div class="field" style="margin-bottom:8px;">
                    <label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;">
                        <input type="checkbox" name="fs_validate" value="1" <?= $fset['validate'] ? 'checked' : '' ?>>
                        <span>Inline validation <span class="text-muted text-xs">— live green-check / red state as visitors type</span></span>
                    </label>
                </div>
                <div class="field" style="margin-bottom:0;">
                    <label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;">
                        <input type="checkbox" name="fs_rail" value="1" <?= $fset['rail'] ? 'checked' : '' ?>>
                        <span>Numbered step rail <span class="text-muted text-xs">— ①②③ progress dots on multi-step forms</span></span>
                    </label>
                </div>
            <?php forms_edit_card_close(); ?>

            <?php
                $accOn = $fset['accent'] !== '';
                $accVal = $fset['accent'] ?: '#2563EB';
                $accHov = $fset['accent_hover'] ?: ($fset['accent'] ? FormsAPI::darkenHex($fset['accent'], 0.12) : '#1D4ED8');
            ?>
            <?php forms_edit_card_open(['icon' => 'tag', 'eyebrow' => 'Style', 'title' => 'Colors & components']); ?>
                <div class="field" style="margin-bottom:10px;">
                    <label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;">
                        <input type="checkbox" id="fs_accent_on" name="fs_accent_on" value="1" <?= $accOn ? 'checked' : '' ?>>
                        <span>Custom brand colors <span class="text-muted text-xs">— override the theme accent</span></span>
                    </label>
                </div>
                <div class="field-row field-row-2" id="fs_accent_row" style="<?= $accOn ? '' : 'opacity:.45;pointer-events:none;' ?>">
                    <div class="field">
                        <label class="field-label" for="fs_accent">Primary color</label>
                        <input type="color" id="fs_accent" name="fs_accent" value="<?= e($accVal) ?>" style="width:100%;height:40px;padding:3px;cursor:pointer;">
                    </div>
                    <div class="field">
                        <label class="field-label" for="fs_accent_hover">Hover / darker</label>
                        <input type="color" id="fs_accent_hover" name="fs_accent_hover" value="<?= e($accHov) ?>" style="width:100%;height:40px;padding:3px;cursor:pointer;">
                    </div>
                </div>
                <div class="field-row field-row-2">
                    <div class="field">
                        <label class="field-label" for="fs_field_style">Field style</label>
                        <select id="fs_field_style" name="fs_field_style">
                            <option value="outline" <?= $fset['field_style'] === 'outline' ? 'selected' : '' ?>>Outlined (white)</option>
                            <option value="filled"  <?= $fset['field_style'] === 'filled'  ? 'selected' : '' ?>>Filled (soft grey)</option>
                        </select>
                    </div>
                    <div class="field">
                        <label class="field-label" for="fs_shape">Corners</label>
                        <select id="fs_shape" name="fs_shape">
                            <option value="rounded" <?= $fset['shape'] === 'rounded' ? 'selected' : '' ?>>Rounded</option>
                            <option value="pill"    <?= $fset['shape'] === 'pill'    ? 'selected' : '' ?>>Pill buttons</option>
                            <option value="square"  <?= $fset['shape'] === 'square'  ? 'selected' : '' ?>>Square</option>
                        </select>
                    </div>
                </div>
                <div class="field" style="margin-bottom:0;">
                    <label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;">
                        <input type="checkbox" name="fs_hide_labels" value="1" <?= $fset['labels'] === 'hide' ? 'checked' : '' ?>>
                        <span>Hide field labels <span class="text-muted text-xs">— rely on placeholders (kept for screen readers)</span></span>
                    </label>
                </div>
                <script>
                (function(){
                    var on = document.getElementById('fs_accent_on'), row = document.getElementById('fs_accent_row');
                    if (on && row) on.addEventListener('change', function(){ row.style.opacity = on.checked ? '' : '.45'; row.style.pointerEvents = on.checked ? '' : 'none'; });
                })();
                </script>
            <?php forms_edit_card_close(); ?>
            </div>

            <div class="pv-panel" data-panel="after" hidden>
            <?php forms_edit_card_open(['icon' => 'check', 'eyebrow' => 'After submit', 'title' => 'Confirmation & redirect']); ?>

                <div class="field-row field-row-2">
                    <div class="field">
                        <label class="field-label" for="submit_label">Submit button label</label>
                        <input type="text" id="submit_label" name="submit_label" maxlength="80"
                               value="<?= e($state['submit_label']) ?>">
                    </div>
                    <div class="field">
                        <label class="field-label" for="submission_limit">Submission limit</label>
                        <input type="number" id="submission_limit" name="submission_limit" min="0"
                               value="<?= e($state['submission_limit']) ?>"
                               placeholder="unlimited">
                        <div class="field-hint">Form closes once this many submissions land.</div>
                    </div>
                </div>

                <div class="field">
                    <label class="field-label" for="success_message">Success message</label>
                    <textarea id="success_message" name="success_message" maxlength="1000"><?= e($state['success_message']) ?></textarea>
                    <div class="field-hint">Shown on the thank-you page after a successful submit (unless redirect URL is set).</div>
                </div>

                <div class="field" style="margin-bottom:0;">
                    <label class="field-label" for="redirect_url">Redirect URL <span class="text-muted text-xs">(optional)</span></label>
                    <input type="url" id="redirect_url" name="redirect_url" maxlength="500"
                           value="<?= e($state['redirect_url']) ?>"
                           placeholder="https://example.com/thanks">
                    <?php if (!empty($fieldErrors['redirect_url'])): ?>
                        <div class="field-error"><?= e($fieldErrors['redirect_url']) ?></div>
                    <?php endif; ?>
                    <div class="field-hint">If set, the submitter is redirected here instead of seeing the success message.</div>
                </div>

            <?php forms_edit_card_close(); ?>
            </div>

            <div class="pv-panel" data-panel="notify" hidden>
            <?php forms_edit_card_open(['icon' => 'mail', 'eyebrow' => 'Notifications', 'title' => 'Email']); ?>

                <div class="field">
                    <label class="field-label" for="notify_email">Notify email</label>
                    <input type="email" id="notify_email" name="notify_email" maxlength="200"
                           value="<?= e($state['notify_email']) ?>"
                           placeholder="you@example.com">
                    <?php if (!empty($fieldErrors['notify_email'])): ?>
                        <div class="field-error"><?= e($fieldErrors['notify_email']) ?></div>
                    <?php endif; ?>
                    <div class="field-hint">Where to send a copy of each submission. Leave blank to skip.</div>
                </div>

                <div class="field">
                    <label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;">
                        <input type="checkbox" name="confirm_submitter" value="1"
                               <?= $state['confirm_submitter'] ? 'checked' : '' ?>>
                        <span>Email the submitter a confirmation (uses the form's <code>email</code> field)</span>
                    </label>
                </div>

                <div class="field-row field-row-2">
                    <div class="field">
                        <label class="field-label" for="confirm_subject">Confirmation subject</label>
                        <input type="text" id="confirm_subject" name="confirm_subject" maxlength="200"
                               value="<?= e($state['confirm_subject']) ?>"
                               placeholder="We got your message">
                    </div>
                </div>

                <div class="field">
                    <label class="field-label" for="confirm_body">Confirmation body (HTML)</label>
                    <textarea id="confirm_body" name="confirm_body" rows="4"><?= e($state['confirm_body']) ?></textarea>
                    <div class="field-hint">Sent to the submitter when the checkbox above is on and the form has an <code>email</code> field.</div>
                </div>

                <div class="field" style="margin-bottom:0;border-top:1px solid var(--line,#e5e7eb);padding-top:16px;">
                    <label style="display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:400;">
                        <input type="checkbox" name="fs_pdf_attach" value="1"
                               <?= !empty($fset['pdf_attach']) ? 'checked' : '' ?>>
                        <span>Attach a branded <strong>PDF</strong> of the submission to the notification &amp; confirmation emails</span>
                    </label>
                    <div class="field-hint">A professional, brand-styled PDF (logo, colours, signature) is generated for each submission and attached to the admin notification and the submitter confirmation. You can also download it from any submission.</div>
                </div>

            <?php forms_edit_card_close(); ?>
            </div>

            <div class="pv-panel" data-panel="webhooks" hidden>
            <?php forms_edit_card_open([
                'icon'       => 'link',
                'eyebrow'    => 'Integrations',
                'title'      => 'Webhooks',
                'aside_html' => '<span class="text-xs text-muted">POST JSON on submit</span>',
            ]); ?>
                <div class="field" style="margin-bottom:0;">
                    <textarea id="webhook_urls" name="webhook_urls" rows="3"
                              style="font-family:var(--font-mono); font-size:12.5px;"
                              placeholder="https://hooks.zapier.com/...&#10;https://internal.example.com/forms"><?= e($state['webhook_urls']) ?></textarea>
                    <?php if (!empty($fieldErrors['webhook_urls'])): ?>
                        <div class="field-error"><?= e($fieldErrors['webhook_urls']) ?></div>
                    <?php endif; ?>
                    <div class="field-hint">One URL per line. Each submission is POSTed as JSON. Save and we'll start firing.</div>
                </div>
            <?php forms_edit_card_close(); ?>
            </div>

    <?php
    // Action-bar left slot: contextual links (fills the bar instead of an empty band).
    $abLeft = '';
    if (!$isNew) {
        $abLeft = '<a href="' . e(plugin_url('forms', 'admin/submissions.php')) . '?form_id=' . (int)$id . '">'
                . forms_edit_icon('mail', 14) . ' Submissions</a>';
        if ($state['status'] === 'published' && $publicUrl) {
            $abLeft .= '<a href="' . e($publicUrl) . '" target="_blank">' . forms_edit_icon('link', 14) . ' View live</a>';
        }
    } else {
        $abLeft = '<span>You can keep editing every tab after the form is created.</span>';
    }
    ?>
    <?php forms_edit_actionbar([
        'left_html'    => $abLeft,
        'buttons_html' =>
            '<button type="submit" class="btn btn-primary">' . ($isNew ? 'Create form' : 'Save changes') . '</button>'
          . '<a href="' . e(plugin_url('forms', 'admin/index.php')) . '" class="btn btn-ghost">Cancel</a>',
    ]); ?>
</form>
<?php forms_edit_close(); ?>
<?php forms_editor_js(); ?>

<style>
.fb-palette{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-bottom:14px;}
.fb-palette-label{font-size:12px;font-weight:600;color:var(--muted);margin-right:4px;}
.fb-add{border:1px solid var(--border);background:var(--card,#fff);border-radius:8px;padding:5px 11px;font-size:12.5px;cursor:pointer;color:var(--text);transition:border-color .12s,color .12s,background .12s;}
.fb-add:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-soft);}
.fb-list{display:flex;flex-direction:column;gap:10px;}
.fb-item{border:1px solid var(--border);border-radius:10px;background:var(--card,#fff);overflow:hidden;}
.fb-item.fb-dragging{opacity:.45;}
.fb-item.fb-over{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent);}
.fb-head{display:flex;align-items:center;gap:10px;padding:9px 12px;background:var(--bg-soft,#FAFAF7);border-bottom:1px solid var(--border);}
.fb-handle{cursor:grab;color:var(--muted);font-size:15px;line-height:1;user-select:none;}
.fb-badge{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--accent);background:var(--accent-soft);padding:2px 8px;border-radius:999px;}
.fb-head-label{flex:1;font-weight:600;font-size:13px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.fb-del{border:0;background:transparent;color:var(--muted);cursor:pointer;font-size:15px;line-height:1;padding:3px 7px;border-radius:6px;}
.fb-del:hover{color:#DC2626;background:#FEF2F2;}
.fb-body{padding:12px;display:grid;grid-template-columns:1fr 1fr;gap:10px;}
.fb-full{grid-column:1/-1;}
.fb-body label{display:block;font-size:11px;font-weight:600;color:var(--muted);margin-bottom:3px;}
.fb-body input[type=text]{width:100%;}
.fb-req{display:flex !important;align-items:center;gap:6px;font-weight:400 !important;color:var(--text) !important;font-size:13px !important;cursor:pointer;margin:0;}
.fb-req input{width:16px;height:16px;accent-color:var(--accent);}
.fb-empty{text-align:center;color:var(--muted);font-size:13px;padding:20px;border:1px dashed var(--border);border-radius:10px;}
.fb-logic{grid-column:1/-1;border-top:1px dashed var(--border);margin-top:4px;padding-top:9px;}
.fb-logic>label{display:block;font-size:11px;font-weight:600;color:var(--muted);margin-bottom:4px;}
.fb-logic-row{display:flex;gap:6px;flex-wrap:wrap;}
.fb-logic-row select,.fb-logic-row input{flex:1;min-width:96px;font-size:12px;}
.fb-formula-keys{grid-column:1/-1;font-size:11px;color:var(--muted);font-family:var(--font-mono);margin-top:-2px;}
.fb-icon-sel>label{display:block;font-size:11px;font-weight:600;color:var(--muted);margin-bottom:3px;}
.fb-icon-sel select{width:100%;font-size:12px;}
.fb-cards-ed{grid-column:1/-1;}
.fb-cards-ed>label{display:block;font-size:11px;font-weight:600;color:var(--muted);margin-bottom:6px;}
.fb-card-row{display:flex;gap:6px;margin-bottom:6px;align-items:center;}
.fb-card-row input{flex:1;min-width:0;font-size:12px;}
.fb-card-row input:first-child{flex:0 0 28%;}
.fb-card-row select{flex:0 0 88px;font-size:11.5px;}
.fb-card-rm{flex:none;border:0;background:transparent;color:var(--muted);cursor:pointer;font-size:13px;padding:4px 6px;border-radius:6px;}
.fb-card-rm:hover{color:#DC2626;background:#FEF2F2;}
.fb-card-add{border:1px dashed var(--border);background:var(--surface-2);color:var(--accent);cursor:pointer;font-size:12px;font-weight:600;padding:7px 12px;border-radius:8px;width:100%;margin-top:2px;}
.fb-card-add:hover{background:var(--accent-soft);border-color:var(--accent);}
</style>
<script>
(function(){
    var TYPES = {text:'Text',textarea:'Paragraph',email:'Email',tel:'Phone',number:'Number',
                 date:'Date',time:'Time',url:'URL',select:'Dropdown',radio:'Choice',checkbox:'Checkbox',
                 range:'Slider',rating:'Rating',calc:'Calculated',file:'File',signature:'Signature',
                 heading:'Heading',step:'Step break',hidden:'Hidden'};
    var hasOptions = function(t){ return t === 'select' || t === 'radio' || t === 'range' || t === 'rating'; };
    // Per-type labels for the config (options) and placeholder inputs.
    var optLabel = function(t){
        if (t === 'range')  return 'Min, Max, Step';
        if (t === 'rating') return 'Max stars (e.g. 5)';
        return 'Options (comma-separated)';
    };
    var phLabel = function(t){
        if (t === 'heading' || t === 'step') return 'Subtitle (optional)';
        if (t === 'hidden')  return 'Value';
        return 'Placeholder';
    };
    var hasPlaceholder = function(t){
        return ['checkbox','file','signature','range','rating','calc'].indexOf(t) === -1;
    };
    var canHalf = function(t){ return ['step','heading','signature','file'].indexOf(t) === -1; };
    var hasRequired = function(t){ return ['heading','hidden','step','calc'].indexOf(t) === -1; };

    var ta       = document.getElementById('fields_dsl');
    var list     = document.getElementById('fb-list');
    var empty    = document.getElementById('fb-empty');
    var palette  = document.getElementById('fb-palette');
    var advanced = document.getElementById('fb-advanced');
    var toggle   = document.getElementById('fb-toggle');
    var jsonEl   = document.getElementById('fields_json_data');
    if (!ta || !list) return;

    function slugify(s){
        return (String(s||'').toLowerCase().replace(/[^a-z0-9]+/g,'_').replace(/^_+|_+$/g,'').slice(0,50)) || 'field';
    }
    function uniqueName(base, exceptIdx){
        base = slugify(base); var n = base, i = 2;
        var taken = function(nm){ return fields.some(function(f,j){ return j !== exceptIdx && (f.name||'') === nm; }); };
        while (taken(n)) { n = base + '_' + i; i++; }
        return n;
    }
    function parse(text){
        var out = [];
        String(text||'').split(/\r\n|\n|\r/).forEach(function(line){
            line = line.trim(); if (!line || line[0] === '#') return;
            var p = line.split('|').map(function(s){ return s.trim(); });
            var type = (p[0]||'').toLowerCase();
            if (!TYPES[type]) return;
            out.push({
                type: type, name: p[1]||'', label: p[2]||'',
                required: (p[3]||'').toLowerCase() === 'required',
                placeholder: p[4]||'',
                options: p[5] ? p[5].split(',').map(function(s){return s.trim();}).filter(Boolean) : [],
                _named: !!(p[1])
            });
        });
        return out;
    }
    function toDsl(){
        return fields.map(function(f){
            var parts = [f.type, f.name || slugify(f.label), f.label || '',
                         f.required ? 'required' : '', f.placeholder || '',
                         hasOptions(f.type) ? optStr(f.options).join(',') : ''];
            while (parts.length > 3 && parts[parts.length-1] === '') parts.pop();
            return parts.join('|');
        }).join('\n');
    }
    function sync(){
        ta.value = toDsl();
        if (jsonEl) jsonEl.value = JSON.stringify(fields);   // canonical (carries advanced props)
        empty.style.display = fields.length ? 'none' : '';
    }
    function fromJson(a){
        return a.map(function(f){
            return {
                type: f.type, name: f.name || '', label: f.label || '',
                required: !!f.required, placeholder: f.placeholder || '',
                options: Array.isArray(f.options) ? f.options : [],
                card: !!f.card, half: !!f.half, icon: f.icon || '',
                show_if: f.show_if || null, formula: f.formula || '', step: f.step || null,
                _named: true
            };
        });
    }

    // Choice-card option helpers.
    var FB_CARD_ICONS = ['','user','users','building','anchor','boat','star','heart','tag','box','card','globe','phone','mail','home','shield','truck','calendar','dollar','briefcase','wrench','check'];
    function optStr(opts){ return (opts||[]).map(function(o){ return (o && typeof o === 'object') ? (o.value||o.label||'') : o; }); }
    function optObj(opts){ return (opts||[]).map(function(o){ return (o && typeof o === 'object') ? o : { value:o, label:o, icon:'', desc:'' }; }); }
    function cardOptionsEditor(f){
        var wrap = document.createElement('div'); wrap.className = 'fb-full fb-cards-ed';
        var lab = document.createElement('label'); lab.textContent = 'Choice cards'; wrap.appendChild(lab);
        var rows = document.createElement('div'); wrap.appendChild(rows);
        var addBtn = document.createElement('button'); addBtn.type='button'; addBtn.className='fb-card-add'; addBtn.textContent='+ Add option';
        wrap.appendChild(addBtn);
        function draw(){
            rows.innerHTML = '';
            f.options.forEach(function(o, i){
                var row = document.createElement('div'); row.className='fb-card-row';
                var lv = document.createElement('input'); lv.type='text'; lv.placeholder='Label'; lv.value=o.label||o.value||'';
                lv.addEventListener('input', function(){ o.label=lv.value; o.value=lv.value; sync(); });
                var ic = document.createElement('select');
                FB_CARD_ICONS.forEach(function(n){ var op=new Option(n||'— icon —', n); if((o.icon||'')===n) op.selected=true; ic.appendChild(op); });
                ic.addEventListener('change', function(){ o.icon=ic.value; sync(); });
                var dv = document.createElement('input'); dv.type='text'; dv.placeholder='Short description'; dv.value=o.desc||'';
                dv.addEventListener('input', function(){ o.desc=dv.value; sync(); });
                var rm = document.createElement('button'); rm.type='button'; rm.className='fb-card-rm'; rm.title='Remove'; rm.textContent='✕';
                rm.addEventListener('click', function(){ f.options.splice(i,1); draw(); sync(); });
                row.appendChild(lv); row.appendChild(ic); row.appendChild(dv); row.appendChild(rm);
                rows.appendChild(row);
            });
        }
        addBtn.addEventListener('click', function(){ f.options.push({value:'Option '+(f.options.length+1), label:'Option '+(f.options.length+1), icon:'', desc:''}); draw(); sync(); });
        draw();
        return wrap;
    }

    function textField(label, val, oninput, full){
        var w = document.createElement('div'); if (full) w.className = 'fb-full';
        var l = document.createElement('label'); l.textContent = label;
        var i = document.createElement('input'); i.type = 'text'; i.value = val || '';
        i.addEventListener('input', function(){ oninput(i.value); });
        w.appendChild(l); w.appendChild(i); return w;
    }
    function card(f, idx){
        var item = document.createElement('div'); item.className = 'fb-item'; item.dataset.idx = idx;

        var head = document.createElement('div'); head.className = 'fb-head'; head.draggable = true;
        var handle = document.createElement('span'); handle.className = 'fb-handle'; handle.textContent = '⠿'; handle.title = 'Drag to reorder';
        var badge = document.createElement('span'); badge.className = 'fb-badge'; badge.textContent = TYPES[f.type] || f.type;
        var hlabel = document.createElement('span'); hlabel.className = 'fb-head-label'; hlabel.textContent = f.label || '(untitled)';
        var del = document.createElement('button'); del.type = 'button'; del.className = 'fb-del'; del.textContent = '✕'; del.title = 'Remove field';
        del.addEventListener('click', function(){ fields.splice(idx,1); render(); });
        head.appendChild(handle); head.appendChild(badge); head.appendChild(hlabel); head.appendChild(del);

        head.addEventListener('dragstart', function(e){ item.classList.add('fb-dragging'); e.dataTransfer.setData('text/plain', String(idx)); e.dataTransfer.effectAllowed = 'move'; });
        head.addEventListener('dragend', function(){ item.classList.remove('fb-dragging'); });
        item.addEventListener('dragover', function(e){ e.preventDefault(); item.classList.add('fb-over'); });
        item.addEventListener('dragleave', function(){ item.classList.remove('fb-over'); });
        item.addEventListener('drop', function(e){
            e.preventDefault(); item.classList.remove('fb-over');
            var from = parseInt(e.dataTransfer.getData('text/plain'), 10);
            if (isNaN(from) || from === idx) return;
            var moved = fields.splice(from, 1)[0];
            fields.splice(idx, 0, moved); render();
        });

        var body = document.createElement('div'); body.className = 'fb-body';
        body.appendChild(textField('Label', f.label, function(v){
            f.label = v; hlabel.textContent = v || '(untitled)';
            if (!f._named) f.name = uniqueName(v, idx);
            sync();
        }));
        body.appendChild(textField('Field key', f.name, function(v){
            f.name = v; f._named = true; sync();
        }));
        if (hasPlaceholder(f.type)) {
            body.appendChild(textField(phLabel(f.type), f.placeholder, function(v){ f.placeholder = v; sync(); }, f.type === 'heading' || f.type === 'hidden'));
        }
        if (['text','email','tel','url','number','date','time'].indexOf(f.type) !== -1) {
            var iw = document.createElement('div'); iw.className = 'fb-full fb-icon-sel';
            var il = document.createElement('label'); il.textContent = 'Field icon';
            var isel = document.createElement('select');
            [['','Auto (by type)'], ['none','No icon']].concat(FB_CARD_ICONS.filter(Boolean).map(function(n){ return [n, n]; })).forEach(function(p){
                var o = new Option(p[1], p[0]); if ((f.icon||'') === p[0]) o.selected = true; isel.appendChild(o);
            });
            isel.addEventListener('change', function(){ f.icon = isel.value; sync(); });
            iw.appendChild(il); iw.appendChild(isel); body.appendChild(iw);
        }
        if (f.type === 'select' || f.type === 'radio') {
            var cardWrap = document.createElement('div'); cardWrap.className = 'fb-full';
            var clab = document.createElement('label'); clab.className = 'fb-req';
            var ccb = document.createElement('input'); ccb.type = 'checkbox'; ccb.checked = !!f.card;
            ccb.addEventListener('change', function(){
                f.card = ccb.checked;
                f.options = f.card ? optObj(f.options) : optStr(f.options);
                render();
            });
            clab.appendChild(ccb); clab.appendChild(document.createTextNode(' Display as choice cards (icon + description)'));
            cardWrap.appendChild(clab); body.appendChild(cardWrap);

            if (f.card) {
                body.appendChild(cardOptionsEditor(f));
            } else {
                body.appendChild(textField('Options (comma-separated)', optStr(f.options).join(', '), function(v){
                    f.options = v.split(',').map(function(s){return s.trim();}).filter(Boolean); sync();
                }, true));
            }
        } else if (hasOptions(f.type)) {
            body.appendChild(textField(optLabel(f.type), (f.options||[]).join(', '), function(v){
                f.options = v.split(',').map(function(s){return s.trim();}).filter(Boolean); sync();
            }, true));
        }
        if (f.type === 'calc') {
            body.appendChild(textField('Formula (e.g. {qty} * {price})', f.formula || '', function(v){ f.formula = v; sync(); }, true));
            var ck = fields.filter(function(of, j){ return j !== idx && of.name && of.type !== 'step' && of.type !== 'heading' && of.type !== 'calc'; })
                           .map(function(of){ return '{' + of.name + '}'; });
            if (ck.length){
                var hk = document.createElement('div'); hk.className = 'fb-full fb-formula-keys';
                hk.textContent = 'Available: ' + ck.join('  ');
                body.appendChild(hk);
            }
        }
        if (hasRequired(f.type)) {
            var reqWrap = document.createElement('div'); reqWrap.className = 'fb-full';
            var rl = document.createElement('label'); rl.className = 'fb-req';
            var cb = document.createElement('input'); cb.type = 'checkbox'; cb.checked = !!f.required;
            cb.addEventListener('change', function(){ f.required = cb.checked; sync(); });
            rl.appendChild(cb); rl.appendChild(document.createTextNode(' Required'));
            reqWrap.appendChild(rl); body.appendChild(reqWrap);
        }
        if (canHalf(f.type) && !f.card) {
            var halfWrap = document.createElement('div'); halfWrap.className = 'fb-full';
            var hl = document.createElement('label'); hl.className = 'fb-req';
            var hcb = document.createElement('input'); hcb.type = 'checkbox'; hcb.checked = !!f.half;
            hcb.addEventListener('change', function(){ f.half = hcb.checked; sync(); });
            hl.appendChild(hcb); hl.appendChild(document.createTextNode(' Half width (two per row)'));
            halfWrap.appendChild(hl); body.appendChild(halfWrap);
        }

        // Conditional visibility — "show this field when [field] [op] [value]".
        if (f.type !== 'step') {
            var others = fields.filter(function(of, j){ return j !== idx && of.name && of.type !== 'step' && of.type !== 'heading'; });
            var logic = document.createElement('div'); logic.className = 'fb-full fb-logic';
            var ll = document.createElement('label'); ll.textContent = 'Visibility'; logic.appendChild(ll);
            var lrow = document.createElement('div'); lrow.className = 'fb-logic-row';

            var selF = document.createElement('select');
            selF.appendChild(new Option('Always show', ''));
            others.forEach(function(of){
                var o = new Option((of.label || of.name), of.name);
                if (f.show_if && f.show_if.field === of.name) o.selected = true;
                selF.appendChild(o);
            });
            var selOp = document.createElement('select');
            [['eq','is'],['ne','is not'],['gt','greater than'],['lt','less than'],['filled','is filled'],['empty','is empty']].forEach(function(p){
                var o = new Option(p[1], p[0]); if (f.show_if && f.show_if.op === p[0]) o.selected = true; selOp.appendChild(o);
            });
            var inpV = document.createElement('input'); inpV.type = 'text'; inpV.placeholder = 'value';
            inpV.value = (f.show_if && f.show_if.value) || '';

            var noVal = function(){ return selOp.value === 'filled' || selOp.value === 'empty'; };
            var paint = function(){ selOp.style.display = selF.value ? '' : 'none'; inpV.style.display = (selF.value && !noVal()) ? '' : 'none'; };
            var syncLogic = function(){
                if (!selF.value) f.show_if = null;
                else f.show_if = { field: selF.value, op: selOp.value, value: noVal() ? '' : inpV.value };
                paint(); sync();
            };
            selF.addEventListener('change', syncLogic);
            selOp.addEventListener('change', syncLogic);
            inpV.addEventListener('input', syncLogic);

            lrow.appendChild(selF); lrow.appendChild(selOp); lrow.appendChild(inpV);
            logic.appendChild(lrow); body.appendChild(logic);
            paint();
        }

        item.appendChild(head); item.appendChild(body);
        return item;
    }
    function render(){
        list.innerHTML = '';
        fields.forEach(function(f, i){ list.appendChild(card(f, i)); });
        sync();
    }

    var fields = (function(){
        if (jsonEl && jsonEl.value) {
            try { var a = JSON.parse(jsonEl.value); if (Array.isArray(a) && a.length) return fromJson(a); } catch (e) {}
        }
        return parse(ta.value);
    })();

    function defaultOptions(t){
        if (t === 'select' || t === 'radio') return ['Option 1','Option 2'];
        if (t === 'range')  return ['0','100','5'];
        if (t === 'rating') return ['5'];
        return [];
    }
    function defaultLabel(t){
        if (t === 'heading') return 'Section title';
        if (t === 'step')    return '';   // unnamed → renders just the "Step i of N" eyebrow
        return TYPES[t];
    }
    Array.prototype.forEach.call(document.querySelectorAll('.fb-add'), function(btn){
        btn.addEventListener('click', function(){
            var t = btn.dataset.type;
            fields.push({ type: t, name: uniqueName(t), label: defaultLabel(t),
                          required: false, placeholder: '',
                          options: defaultOptions(t), _named: false });
            render();
        });
    });

    var showingAdvanced = false;
    toggle.addEventListener('click', function(){
        showingAdvanced = !showingAdvanced;
        if (showingAdvanced) {
            sync(); advanced.hidden = false; list.style.display = 'none';
            palette.style.display = 'none'; empty.style.display = 'none';
            toggle.textContent = 'Visual builder';
        } else {
            fields = parse(ta.value); advanced.hidden = true; list.style.display = '';
            palette.style.display = ''; toggle.textContent = 'Advanced (DSL)'; render();
        }
    });

    var form = ta.closest('form');
    if (form) form.addEventListener('submit', function(){ if (!showingAdvanced) sync(); });

    // Live preview — POST the current builder state to the preview endpoint in a new tab.
    var previewBtn = document.getElementById('fb-preview');
    if (previewBtn) previewBtn.addEventListener('click', function(){
        if (showingAdvanced) { fields = parse(ta.value); } else { sync(); }
        var pf = document.createElement('form');
        pf.method = 'post'; pf.target = '_blank';
        pf.action = window.location.pathname + (window.location.search ? window.location.search + '&' : '?') + 'preview=1';
        var add = function(n, v){ var i = document.createElement('input'); i.type = 'hidden'; i.name = n; i.value = (v == null ? '' : v); pf.appendChild(i); };
        add('fields_json_data', JSON.stringify(fields));
        var t = document.getElementById('title');       add('title', t ? t.value : '');
        var d = document.getElementById('description');  add('description', d ? d.value : '');
        var ds = document.getElementById('fs_density');
        var accOn = !!(document.getElementById('fs_accent_on') || {}).checked;
        add('settings_json', JSON.stringify({
            density: ds ? ds.value : 'comfortable',
            animate:  !!(document.querySelector('[name="fs_animate"]')  || {}).checked,
            validate: !!(document.querySelector('[name="fs_validate"]') || {}).checked,
            rail:     !!(document.querySelector('[name="fs_rail"]')     || {}).checked,
            accent:       accOn ? ((document.getElementById('fs_accent') || {}).value || '') : '',
            accent_hover: accOn ? ((document.getElementById('fs_accent_hover') || {}).value || '') : '',
            field_style:  (document.getElementById('fs_field_style') || {}).value || 'outline',
            shape:        (document.getElementById('fs_shape') || {}).value || 'rounded',
            labels:       (document.querySelector('[name="fs_hide_labels"]') || {}).checked ? 'hide' : 'show'
        }));
        document.body.appendChild(pf); pf.submit(); document.body.removeChild(pf);
    });

    render();
})();
</script>

<?php require SLATE_ROOT . '/admin/partials/footer.php'; ?>
