<?php
/**
 * lab_formulario_builder.php
 * Editor de formularios dedicado — se abre en ventana nueva.
 * ?id=X  → editar formulario X
 * (sin id) → nuevo formulario
 */
require_once 'config/config.php';
if (!defined('APP_ROOT')) { define('APP_ROOT', __DIR__); }
if (!isUserLoggedIn()) { echo '<script>window.close();</script>'; exit; }
if (isEnfermero())     { echo '<script>window.close();</script>'; exit; }
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');

$formId = isset($_GET['id']) ? (int)$_GET['id'] : 0;
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Editor de Formulario — Lab</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        *, *::before, *::after { box-sizing: border-box; }

        html, body {
            height: 100%; margin: 0; padding: 0;
            background: #f0f2f5;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
            font-size: 13.5px;
        }

        /* ── TOPBAR ─────────────────────────────────────────────── */
        #topbar {
            height: 56px; background: #1565c0; color: #fff;
            display: flex; align-items: center; gap: 12px;
            padding: 0 16px; position: fixed; top: 0; left: 0; right: 0; z-index: 200;
            box-shadow: 0 2px 8px rgba(0,0,0,.25);
        }
        #topbar .brand { font-size: 16px; font-weight: 700; white-space: nowrap; }
        #topbar .brand i { opacity: .8; margin-right: 6px; }
        #topbar #tb-nombre {
            flex: 1; min-width: 0;
            background: rgba(255,255,255,.15); border: 1px solid rgba(255,255,255,.3);
            color: #fff; border-radius: 6px; padding: 6px 12px; font-size: 14px;
            font-weight: 600;
        }
        #topbar #tb-nombre::placeholder { color: rgba(255,255,255,.5); }
        #topbar #tb-nombre.is-invalid { border-color: #ff6b6b; background: rgba(255,107,107,.2); }
        #topbar .top-meta { display: flex; gap: 8px; align-items: center; }
        #topbar .top-meta select { border-radius: 6px; padding: 4px 8px; font-size: 12px; border: none; }
        #topbar .checks { display: flex; gap: 12px; }
        #topbar .checks label { color: rgba(255,255,255,.9); font-size: 12px; cursor: pointer; }
        #topbar .checks input { cursor: pointer; }
        #topbar .btn-save {
            background: #fff; color: #1565c0; font-weight: 700;
            border: none; border-radius: 6px; padding: 7px 18px; white-space: nowrap;
            cursor: pointer; transition: background .15s;
        }
        #topbar .btn-save:hover { background: #e3f2fd; }
        #topbar .btn-save:disabled { opacity: .6; cursor: default; }
        #topbar .btn-close-win {
            background: rgba(255,255,255,.15); border: none; color: #fff;
            border-radius: 6px; padding: 7px 12px; cursor: pointer;
        }
        #topbar .btn-close-win:hover { background: rgba(255,255,255,.3); }

        /* ── LAYOUT PRINCIPAL ───────────────────────────────────── */
        #workspace {
            position: fixed; top: 56px; bottom: 0; left: 0; right: 0;
            display: flex;
        }

        /* ── PANEL IZQUIERDO — PALETA ───────────────────────────── */
        #panel-palette {
            width: 210px; min-width: 210px;
            background: #fff; border-right: 1px solid #dee2e6;
            display: flex; flex-direction: column; overflow: hidden;
        }
        #panel-palette .pane-hdr {
            padding: 10px 12px; font-size: 10px; font-weight: 700;
            text-transform: uppercase; color: #6c757d; letter-spacing: .5px;
            border-bottom: 1px solid #f0f0f0; background: #f8f9fa; flex-shrink: 0;
        }
        #panel-palette .pane-scroll { flex: 1; overflow-y: auto; padding: 10px; }

        .palette-group-title {
            font-size: 10px; font-weight: 700; text-transform: uppercase;
            color: #adb5bd; letter-spacing: .5px; margin: 8px 0 4px;
        }
        .palette-item {
            display: flex; align-items: center; gap: 8px;
            padding: 7px 10px; border-radius: 7px; cursor: grab;
            border: 1px solid #dee2e6; margin-bottom: 4px;
            font-size: 12px; font-weight: 500; background: #fff;
            transition: all .12s; user-select: none;
        }
        .palette-item:hover { background: #e8f0fe; border-color: #90caf9; color: #1565c0; }
        .palette-item i { width: 14px; text-align: center; }
        .palette-item.linked { border-color: #b2dfdb; color: #00796b; }
        .palette-item.linked:hover { background: #e0f2f1; }

        /* ── PANEL CENTRAL — CANVAS ─────────────────────────────── */
        #panel-canvas {
            flex: 1; display: flex; flex-direction: column;
            min-width: 0; overflow: hidden; background: #f0f2f5;
        }
        #canvas-scroll { flex: 1; overflow-y: auto; padding: 20px; }

        /* Secciones canvas */
        .cv-card {
            background: #fff; border-radius: 10px; border: 1px solid #dee2e6;
            padding: 16px 18px; margin-bottom: 16px;
        }
        .cv-card-title {
            font-size: 10px; font-weight: 700; text-transform: uppercase;
            color: #6c757d; letter-spacing: .5px; margin-bottom: 12px;
            border-bottom: 2px solid #e9ecef; padding-bottom: 6px;
        }
        .cv-card-title i { margin-right: 4px; }

        /* Canvas drop zone */
        #drop-zone {
            min-height: 280px; border: 2px dashed #b3c6f7;
            border-radius: 10px; padding: 10px;
            background: #f8faff; transition: all .15s;
        }
        #drop-zone.drag-over { border-color: #1565c0; background: #e8f0fe; }

        /* Field items */
        .field-item {
            display: flex; align-items: center; gap: 8px;
            background: #fff; border: 1px solid #dee2e6; border-radius: 8px;
            padding: 9px 12px; margin-bottom: 7px; cursor: default;
            transition: box-shadow .12s; position: relative;
        }
        .field-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,.09); }
        .field-item.dragging { opacity: .45; }
        .field-item .fi-handle { cursor: grab; color: #adb5bd; font-size: 13px; }
        .field-item .fi-handle:active { cursor: grabbing; }
        .field-item .fi-icon { color: #1565c0; font-size: 13px; width: 16px; text-align: center; }
        .field-item .fi-label { flex: 1; font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .field-item .fi-badges { display: flex; gap: 4px; flex-shrink: 0; }
        .field-item .fi-badge { font-size: 10px; padding: 1px 5px; border-radius: 4px; }
        .field-item .fi-actions { display: flex; gap: 4px; flex-shrink: 0; }
        .field-item .fi-btn { background: none; border: none; padding: 3px 5px;
                              border-radius: 4px; cursor: pointer; color: #6c757d; font-size: 12px; }
        .field-item .fi-btn:hover { background: #f0f0f0; }
        .field-item .fi-btn.danger:hover { background: #fde8e8; color: #dc3545; }

        #drop-hint { text-align: center; color: #9bb3d4; padding: 40px 0; font-size: 13px; }
        #drop-hint i { font-size: 28px; display: block; margin-bottom: 8px; opacity: .5; }

        /* Doc design toggle */
        .doc-section-toggle {
            cursor: pointer; user-select: none;
            display: flex; align-items: center; gap: 6px;
            color: #1565c0; font-size: 11px; font-weight: 700;
            text-transform: uppercase; letter-spacing: .5px;
        }
        .doc-section-toggle:hover { color: #0d47a1; }

        /* ── PANEL DERECHO — PREVIEW ────────────────────────────── */
        #panel-preview {
            width: 320px; min-width: 320px;
            background: #f8f9fa; border-left: 1px solid #dee2e6;
            display: flex; flex-direction: column; overflow: hidden;
        }
        #panel-preview .pane-hdr {
            padding: 10px 14px; font-size: 10px; font-weight: 700;
            text-transform: uppercase; color: #6c757d; letter-spacing: .5px;
            border-bottom: 1px solid #dee2e6; background: #f0f2f5; flex-shrink: 0;
            display: flex; align-items: center; justify-content: space-between;
        }
        #preview-scroll { flex: 1; overflow-y: auto; padding: 12px; }
        #preview-doc {
            background: #fff; border-radius: 8px; border: 1px solid #dee2e6;
            padding: 16px; min-height: 100%;
        }
        .preview-field { margin-bottom: 12px; }
        .preview-field label { display: block; font-size: 11px; font-weight: 600;
                               margin-bottom: 3px; color: #444; }
        .preview-field input, .preview-field select,
        .preview-field textarea { width: 100%; font-size: 11px; border: 1px solid #dee2e6;
                                   border-radius: 4px; padding: 4px 6px; background: #fafafa; }
        .preview-sep { border: none; border-top: 2px solid #1565c0;
                       margin: 14px 0 6px; opacity: .25; }
        .preview-sep-label { font-size: 10px; font-weight: 700; text-transform: uppercase;
                             color: #6c757d; letter-spacing: .5px; margin-bottom: 8px; }

        /* ── MODAL campo ─────────────────────────────────────────── */
        .modal-backdrop.show { opacity: .45; }

        /* ── STATUSBAR ───────────────────────────────────────────── */
        #statusbar {
            height: 26px; background: #1565c0; color: rgba(255,255,255,.7);
            font-size: 11px; display: flex; align-items: center; gap: 16px;
            padding: 0 14px; position: fixed; bottom: 0; left: 0; right: 0; z-index: 200;
        }
        #statusbar span { display: flex; align-items: center; gap: 4px; }

        /* ── Toast ───────────────────────────────────────────────── */
        #toast-msg {
            position: fixed; bottom: 36px; left: 50%; transform: translateX(-50%);
            background: #1b5e20; color: #fff; border-radius: 20px;
            padding: 8px 20px; font-size: 13px; font-weight: 600;
            z-index: 9999; display: none; box-shadow: 0 3px 12px rgba(0,0,0,.3);
        }

        /* ── Scrollbars ──────────────────────────────────────────── */
        ::-webkit-scrollbar { width: 6px; height: 6px; }
        ::-webkit-scrollbar-track { background: transparent; }
        ::-webkit-scrollbar-thumb { background: #c1c9d4; border-radius: 3px; }
        ::-webkit-scrollbar-thumb:hover { background: #8fa0b5; }

        /* ── Drop indicators (touch drag) ─────────────────────── */
        .field-item.touch-dragging { opacity: .3; }
        .field-item.drop-above::before {
            content: ''; position: absolute; top: -4px; left: 0; right: 0;
            height: 3px; background: #1565c0; border-radius: 2px; pointer-events: none;
        }
        .field-item.drop-below::after {
            content: ''; position: absolute; bottom: -4px; left: 0; right: 0;
            height: 3px; background: #1565c0; border-radius: 2px; pointer-events: none;
        }
        #drag-ghost {
            position: fixed; pointer-events: none; z-index: 9999;
            background: #fff; border: 1.5px solid #1565c0; border-radius: 8px;
            box-shadow: 0 8px 28px rgba(21,101,192,.25);
            padding: 9px 12px; display: flex; align-items: center; gap: 8px;
            font-size: 12.5px; font-weight: 600; color: #1565c0;
            opacity: .92; transition: none;
        }

        /* ── Palette tap hint ──────────────────────────────────── */
        .palette-item { touch-action: none; }
        @media (pointer: coarse) {
            .palette-item::after {
                content: '+'; margin-left: auto; font-size: 15px;
                font-weight: 700; color: #1565c0; opacity: .5;
            }
            .field-item .fi-handle {
                font-size: 18px; padding: 4px 6px;
                color: #90a4ae;
            }
            .field-item .fi-btn { padding: 6px 8px; font-size: 14px; }
        }

        @media (max-width: 900px) {
            #panel-palette { width: 170px; min-width: 170px; }
            #panel-preview { width: 260px; min-width: 260px; }
        }
        @media (max-width: 680px) {
            #panel-preview { display: none; }
            #panel-palette { width: 140px; min-width: 140px; }
        }

        /* ── Pantalla de éxito ─────────────────────────────── */
        #success-screen {
            position: fixed; inset: 0; z-index: 1000;
            background: linear-gradient(135deg, #1565c0 0%, #0d47a1 100%);
            display: none; flex-direction: column;
            align-items: center; justify-content: center;
            color: #fff; text-align: center;
        }
        #success-screen.show { display: flex; }
        #success-screen .success-icon {
            font-size: 72px; margin-bottom: 16px; line-height: 1;
            animation: pop .4s cubic-bezier(.175,.885,.32,1.275);
        }
        @keyframes pop {
            from { transform: scale(0); opacity: 0; }
            to   { transform: scale(1); opacity: 1; }
        }
        #success-screen h2 { font-size: 28px; font-weight: 700; margin: 0 0 8px; }
        #success-screen p  { font-size: 16px; opacity: .8; margin: 0 0 32px; }
        #success-screen .success-actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }
        #success-screen .btn-white {
            background: #fff; color: #1565c0; border: none;
            border-radius: 8px; padding: 12px 28px; font-size: 15px;
            font-weight: 700; cursor: pointer; transition: transform .1s, box-shadow .1s;
        }
        #success-screen .btn-white:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,.25); }
        #success-screen .btn-outline {
            background: transparent; color: #fff;
            border: 2px solid rgba(255,255,255,.6);
            border-radius: 8px; padding: 11px 28px; font-size: 15px;
            font-weight: 600; cursor: pointer; transition: background .15s;
        }
        #success-screen .btn-outline:hover { background: rgba(255,255,255,.15); }
    </style>
</head>
<body>

<!-- ── TOPBAR ──────────────────────────────────────────────────────── -->
<div id="topbar">
    <div class="brand"><i class="fas fa-magic"></i>Builder</div>
    <input type="text" id="tb-nombre" placeholder="Nombre del formulario *" autocomplete="off">
    <div class="top-meta">
        <select id="tb-categoria" title="Categoría">
            <option value="consentimiento">Consentimiento</option>
            <option value="historia_clinica">Historia clínica</option>
            <option value="autorizacion">Autorización</option>
            <option value="encuesta">Encuesta</option>
            <option value="otro" selected>Otro</option>
        </select>
        <div class="checks">
            <label><input type="checkbox" id="tb-firma" checked> Firma</label>
            <label><input type="checkbox" id="tb-firma-req"> Req.</label>
            <label><input type="checkbox" id="tb-firma-canvas" checked> ✍️ Dibujar</label>
            <label><input type="checkbox" id="tb-firma-foto" checked> 📷 Foto</label>
        </div>
    </div>
    <button class="btn-save" id="btn-save" onclick="guardar()">
        <i class="fas fa-save me-1"></i>Guardar
    </button>
    <button class="btn-close-win" title="Cerrar editor" onclick="cerrar()">
        <i class="fas fa-times"></i>
    </button>
</div>

<!-- ── WORKSPACE ───────────────────────────────────────────────────── -->
<div id="workspace">

    <!-- ── PALETA ─────────────────────────────────────────────────── -->
    <div id="panel-palette">
        <div class="pane-hdr"><i class="fas fa-th-large me-1"></i>Tipos de campo</div>
        <div class="pane-scroll" id="palette-scroll">
            <div class="palette-group-title">Campos básicos</div>
            <div id="palette"></div>
            <div class="palette-group-title" style="margin-top:12px">Vinculados al paciente</div>
            <div id="palette-linked"></div>
            <div class="palette-group-title" style="margin-top:12px">Calculados</div>
            <div id="palette-calc"></div>
        </div>
    </div>

    <!-- ── CANVAS ─────────────────────────────────────────────────── -->
    <div id="panel-canvas">
        <div id="canvas-scroll">

            <!-- Info del formulario -->
            <div class="cv-card">
                <div class="cv-card-title"><i class="fas fa-info-circle"></i>Información del formulario</div>
                <div class="mb-2">
                    <label class="form-label small mb-1 fw-semibold">Descripción breve</label>
                    <textarea class="form-control form-control-sm" id="tb-descripcion"
                              rows="2" placeholder="Describe el propósito del formulario (opcional)"></textarea>
                </div>
            </div>

            <!-- Drop zone -->
            <div class="cv-card" style="padding:0;overflow:hidden">
                <div style="padding:12px 16px 0">
                    <div class="cv-card-title" style="margin-bottom:8px">
                        <i class="fas fa-layer-group"></i>Campos del formulario
                        <span id="campos-count" class="ms-2 text-muted fw-normal" style="font-size:11px;text-transform:none"></span>
                    </div>
                </div>
                <div id="drop-zone" style="margin:0 12px 12px"
                     ondragover="onDragOver(event)" ondrop="onDrop(event)"
                     ondragleave="onDragLeave(event)">
                    <div id="drop-hint">
                        <i class="fas fa-mouse-pointer"></i>
                        Arrastra campos desde el panel izquierdo
                    </div>
                </div>
            </div>

            <!-- Diseño del documento -->
            <div class="cv-card">
                <div class="d-flex align-items-center justify-content-between mb-0" style="cursor:pointer"
                     onclick="toggleDocSection()">
                    <div class="doc-section-toggle">
                        <i class="fas fa-paint-brush"></i>Diseño del documento
                        <i class="fas fa-chevron-down ms-1" id="doc-chevron" style="transition:.2s"></i>
                    </div>
                    <div class="form-check form-switch mb-0" onclick="event.stopPropagation()">
                        <input class="form-check-input" type="checkbox" id="tb-usar-global"
                               onchange="toggleDocGlobal(this.checked)" checked>
                        <label class="form-check-label small text-muted" for="tb-usar-global"
                               style="font-size:11px">Config global</label>
                    </div>
                </div>
                <div id="doc-section-body" class="mt-3">
                    <div id="doc-global-hint" class="alert alert-light py-2 mb-0" style="font-size:12px">
                        <i class="fas fa-info-circle me-1 text-primary"></i>
                        Se usará el logo y encabezado configurados globalmente.
                        <a href="lab_configuracion.php" target="_blank">Editar config global</a>
                    </div>
                    <div id="doc-override-fields" style="display:none">
                        <div class="row g-2">
                            <div class="col-8">
                                <label class="form-label small mb-1">Encabezado (nombre empresa)</label>
                                <input type="text" class="form-control form-control-sm" id="tb-doc-encabezado"
                                       placeholder="Ej: Laboratorio Clínico Ximena">
                            </div>
                            <div class="col-4">
                                <label class="form-label small mb-1">Color</label>
                                <input type="color" class="form-control form-control-sm form-control-color w-100"
                                       id="tb-doc-color" value="#1565c0" title="Color del encabezado"
                                       oninput="renderPreview()">
                            </div>
                            <div class="col-12">
                                <label class="form-label small mb-1">Subtítulo</label>
                                <input type="text" class="form-control form-control-sm" id="tb-doc-subtitulo"
                                       placeholder="Ej: Análisis Clínicos Especializados">
                            </div>
                            <div class="col-12">
                                <label class="form-label small mb-1">Logo del formulario</label>
                                <input type="file" class="form-control form-control-sm" id="tb-logo-file"
                                       accept="image/*" onchange="cargarLogo(this)">
                                <div id="tb-logo-preview" class="mt-2" style="display:none">
                                    <div class="d-flex align-items-center gap-2">
                                        <img id="tb-logo-img" src="" style="max-height:44px;max-width:100px;border:1px solid #dee2e6;border-radius:5px;padding:2px">
                                        <button type="button" class="btn btn-link btn-sm text-danger p-0"
                                                onclick="quitarLogo()"><i class="fas fa-trash"></i> Quitar</button>
                                    </div>
                                </div>
                                <input type="hidden" id="tb-logo-base64">
                            </div>
                            <div class="col-12">
                                <label class="form-label small mb-1">Pie de página</label>
                                <input type="text" class="form-control form-control-sm" id="tb-doc-pie"
                                       placeholder="Ej: Documento de uso confidencial">
                            </div>
                        </div>
                    </div>
                </div>
            </div>

        </div><!-- /canvas-scroll -->
    </div>

    <!-- ── PREVIEW ────────────────────────────────────────────────── -->
    <div id="panel-preview">
        <div class="pane-hdr">
            <span><i class="fas fa-eye me-1"></i>Vista previa del cliente</span>
            <button class="btn btn-xs btn-outline-secondary" style="font-size:10px;padding:2px 7px"
                    onclick="renderPreview()">
                <i class="fas fa-sync-alt me-1"></i>Actualizar
            </button>
        </div>
        <div id="preview-scroll">
            <div id="preview-doc">
                <p class="text-muted text-center small mt-3">El formulario aparecerá aquí…</p>
            </div>
        </div>
    </div>

</div><!-- /workspace -->

<!-- ── STATUSBAR ───────────────────────────────────────────────────── -->
<div id="statusbar">
    <span><i class="fas fa-wpforms"></i><span id="sb-form-id"><?= $formId ? "Form #$formId" : 'Nuevo formulario' ?></span></span>
    <span><i class="fas fa-layer-group"></i><span id="sb-campos">0 campos</span></span>
    <span id="sb-status" style="margin-left:auto"><i class="fas fa-circle" style="color:#69f0ae;font-size:8px"></i> Listo</span>
</div>

<!-- ── MODAL CONFIGURAR CAMPO ──────────────────────────────────────── -->
<div class="modal fade" id="modalCampo" tabindex="-1">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header py-2 bg-light">
                <h6 class="modal-title mb-0"><i class="fas fa-cog me-1 text-primary"></i>Configurar campo</h6>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body" id="campo-editor-body"></div>
            <div class="modal-footer py-2 bg-light">
                <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
                <button type="button" class="btn btn-primary btn-sm" id="campo-save-btn">
                    <i class="fas fa-check me-1"></i>Aplicar
                </button>
            </div>
        </div>
    </div>
</div>

<!-- ── PANTALLA DE ÉXITO ──────────────────────────────────────────── -->
<div id="success-screen">
    <div class="success-icon">✅</div>
    <h2 id="success-title">¡Formulario guardado!</h2>
    <p id="success-sub">Los cambios quedaron guardados correctamente.</p>
    <div class="success-actions">
        <button class="btn-white" onclick="irAFormularios()">
            <i class="fas fa-arrow-left me-2"></i>Ir a Formularios
        </button>
        <button class="btn-outline" onclick="seguirEditando()">
            <i class="fas fa-edit me-2"></i>Seguir editando
        </button>
    </div>
</div>

<div id="toast-msg"></div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
// ════════════════════════════════════════════════════════════════════
// CONSTANTES
// ════════════════════════════════════════════════════════════════════
const FORM_ID = <?= $formId ?>;

const TIPOS_CAMPO = [
    { tipo:'texto',       label:'Texto corto',       icon:'fa-font'         },
    { tipo:'textarea',    label:'Texto largo',        icon:'fa-align-left'   },
    { tipo:'numero',      label:'Número',             icon:'fa-hashtag'      },
    { tipo:'fecha',       label:'Fecha',              icon:'fa-calendar'     },
    { tipo:'hora',        label:'Hora',               icon:'fa-clock'        },
    { tipo:'select',      label:'Lista desplegable',  icon:'fa-list'         },
    { tipo:'radio',       label:'Selección única',    icon:'fa-dot-circle'   },
    { tipo:'checkbox',    label:'Múltiple opción',    icon:'fa-check-square' },
    { tipo:'firma',             label:'Firma del paciente',   icon:'fa-signature' },
    { tipo:'firma_profesional', label:'Firma del profesional', icon:'fa-user-md'   },
    { tipo:'separador',   label:'Separador / Título', icon:'fa-minus'        },
    { tipo:'parrafo',       label:'Párrafo de texto',      icon:'fa-paragraph'    },
    { tipo:'parrafo_inline', label:'Párrafo con campos',    icon:'fa-align-left'   },
    { tipo:'lista_marcable', label:'Lista marcable',        icon:'fa-list-ol'      },
];
const TIPOS_CALC = [
    { tipo:'fecha_hoy', label:'Fecha actual',        icon:'fa-calendar-day'  },
    { tipo:'edad',      label:'Edad del paciente',   icon:'fa-user-clock'    },
];
const TIPOS_LINKED = [
    { key:'nombre_completo',  label:'Nombre completo',   icon:'fa-user'           },
    { key:'numero_documento', label:'N.º documento',     icon:'fa-id-card'        },
    { key:'tipo_documento',   label:'Tipo documento',    icon:'fa-id-badge'       },
    { key:'fecha_nacimiento', label:'Fecha nacimiento',  icon:'fa-birthday-cake'  },
    { key:'telefono',         label:'Teléfono',          icon:'fa-phone'          },
    { key:'email',            label:'Email',             icon:'fa-envelope'       },
    { key:'eps',              label:'EPS / Aseguradora', icon:'fa-hospital'       },
    { key:'direccion',        label:'Dirección',         icon:'fa-map-marker-alt' },
];

// ════════════════════════════════════════════════════════════════════
// ESTADO
// ════════════════════════════════════════════════════════════════════
let _campos    = [];
let _dragSrc   = null; // índice del item siendo reordenado
let _dragTipo  = null; // { tipo, linked } desde la paleta
let _globalCfg = {};
let _bsCampo   = null;
let _saved     = false;
let _docOpen   = false;
let _campoIdx  = null;

// ════════════════════════════════════════════════════════════════════
// DOM HELPERS
// ════════════════════════════════════════════════════════════════════
const $ = id => document.getElementById(id);
const esc = s => String(s||'').replace(/[<>&"']/g,
    c => ({'<':'&lt;','>':'&gt;','&':'&amp;','"':'&quot;',"'":'&#39;'}[c]));
const uid = () => '_' + Math.random().toString(36).slice(2,9);

function showToast(msg, color='#1b5e20') {
    const t = $('toast-msg');
    t.textContent = msg;
    t.style.background = color;
    t.style.display = 'block';
    clearTimeout(t._tid);
    t._tid = setTimeout(() => t.style.display = 'none', 2800);
}
function sbStatus(msg, ok=true) {
    $('sb-status').innerHTML = `<i class="fas fa-circle" style="color:${ok?'#69f0ae':'#ff8a65'};font-size:8px"></i> ${msg}`;
}

// ════════════════════════════════════════════════════════════════════
// RENDER PALETA
// ════════════════════════════════════════════════════════════════════
function renderPalette() {
    $('palette').innerHTML = TIPOS_CAMPO.map(t => `
        <div class="palette-item" draggable="true"
             data-tipo="${t.tipo}"
             ondragstart="palDragStart(event,'${t.tipo}')"
             onclick="agregarCampo({tipo:'${t.tipo}',linked:null})">
            <i class="fas ${t.icon}"></i>${t.label}
        </div>`).join('');

    $('palette-linked').innerHTML = TIPOS_LINKED.map(t => `
        <div class="palette-item linked" draggable="true"
             data-tipo="linked" data-linked="${t.key}"
             ondragstart="palDragStart(event,'linked','${t.key}')"
             onclick="agregarCampo({tipo:'linked',linked:'${t.key}'})">
            <i class="fas ${t.icon}"></i>${t.label}
        </div>`).join('');

    $('palette-calc').innerHTML = TIPOS_CALC.map(t => `
        <div class="palette-item" draggable="true"
             data-tipo="${t.tipo}"
             ondragstart="palDragStart(event,'${t.tipo}')"
             onclick="agregarCampo({tipo:'${t.tipo}',linked:null})"
             style="color:#856404">
            <i class="fas ${t.icon}"></i>${t.label}
        </div>`).join('');
}

// ════════════════════════════════════════════════════════════════════
// DRAG & DROP — PALETA ➜ CANVAS
// ════════════════════════════════════════════════════════════════════
function palDragStart(e, tipo, linked = null) {
    _dragTipo = { tipo, linked };
    _dragSrc  = null;
    e.dataTransfer.effectAllowed = 'copy';
}
function onDragOver(e) {
    e.preventDefault();
    $('drop-zone').classList.add('drag-over');
}
function onDragLeave(e) {
    $('drop-zone').classList.remove('drag-over');
}
function onDrop(e) {
    e.preventDefault();
    $('drop-zone').classList.remove('drag-over');
    if (_dragTipo) { agregarCampo(_dragTipo); _dragTipo = null; }
}

// ════════════════════════════════════════════════════════════════════
// AGREGAR CAMPO
// ════════════════════════════════════════════════════════════════════
function agregarCampo({ tipo, linked }) {
    const id = uid();
    let campo;
    if (tipo === 'linked') {
        campo = { id, tipo:'linked', linked_key:linked,
                  label: TIPOS_LINKED.find(t=>t.key===linked)?.label || linked,
                  required:false };
    } else if (tipo === 'separador') {
        campo = { id, tipo:'separador', label:'Nueva sección' };
    } else if (['select','radio','checkbox'].includes(tipo)) {
        campo = { id, tipo, label:'Campo sin título', options:['Opción 1','Opción 2'], required:false };
    } else if (tipo === 'firma') {
        campo = { id, tipo:'firma', label:'Firma del paciente', modos: ['canvas','foto'] };
    } else if (tipo === 'firma_profesional') {
        campo = { id, tipo:'firma_profesional', label:'Firma del profesional', modos: ['canvas'] };
    } else if (tipo === 'parrafo') {
        campo = { id, tipo:'parrafo', contenido:'Escribe aquí el texto del párrafo...', flujoLibre:false };
    } else if (tipo === 'parrafo_inline') {
        campo = { id, tipo:'parrafo_inline', contenido:'Yo, {nombre_completo}, con N.º de identificación {numero_documento}, declaro que…' };
    } else if (tipo === 'lista_marcable') {
        campo = { id, tipo:'lista_marcable', label:'Marque con X la prueba solicitada', items:['Opción 1','Opción 2'], required:false };
    } else if (tipo === 'fecha_hoy') {
        campo = { id, tipo:'fecha_hoy', label:'Fecha', required:false };
    } else if (tipo === 'edad') {
        campo = { id, tipo:'edad', label:'Edad', required:false };
    } else {
        campo = { id, tipo, label:'Campo sin título', placeholder:'', required:false };
    }
    _campos.push(campo);
    renderCanvas();
    renderPreview();
}

// ════════════════════════════════════════════════════════════════════
// RENDER CANVAS
// ════════════════════════════════════════════════════════════════════
const TIPO_ICON = {
    texto:'fa-font', textarea:'fa-align-left', numero:'fa-hashtag',
    fecha:'fa-calendar', hora:'fa-clock', select:'fa-list', radio:'fa-dot-circle',
    checkbox:'fa-check-square', firma:'fa-signature', firma_profesional:'fa-user-md', separador:'fa-minus', linked:'fa-link',
    parrafo:'fa-paragraph', parrafo_inline:'fa-align-left', lista_marcable:'fa-list-ol',
    fecha_hoy:'fa-calendar-day', edad:'fa-user-clock'
};

function renderCanvas() {
    const zone = $('drop-zone');
    $('drop-hint').style.display = _campos.length ? 'none' : '';
    zone.querySelectorAll('.field-item').forEach(el => el.remove());

    $('campos-count').textContent = _campos.length
        ? `(${_campos.length} campo${_campos.length!==1?'s':''})` : '';
    $('sb-campos').textContent = `${_campos.length} campo${_campos.length!==1?'s':''}`;

    _campos.forEach((c, idx) => {
        const div = document.createElement('div');
        div.className = 'field-item';
        div.dataset.idx = idx;
        div.setAttribute('draggable', 'true');

        const reqBadge = c.required
            ? '<span class="badge bg-danger fi-badge">req</span>' : '';
        const linkedBadge = c.tipo === 'linked'
            ? '<span class="badge bg-teal fi-badge" style="background:#009688;color:#fff">vinculado</span>' : '';

        div.innerHTML = `
            <span class="fi-handle"><i class="fas fa-grip-vertical"></i></span>
            <i class="fas ${TIPO_ICON[c.tipo]||'fa-question'} fi-icon"></i>
            <span class="fi-label" title="${esc(c.label)}">${esc(c.label)}</span>
            <div class="fi-badges">${reqBadge}${linkedBadge}</div>
            <div class="fi-actions">
                <button class="fi-btn" title="Configurar" onclick="abrirEditorCampo(${idx})">
                    <i class="fas fa-cog"></i>
                </button>
                <button class="fi-btn danger" title="Eliminar" onclick="eliminarCampo(${idx})">
                    <i class="fas fa-trash"></i>
                </button>
            </div>`;

        // Reordenar — HTML5 drag (mouse desktop)
        div.setAttribute('draggable', 'true');
        div.addEventListener('dragstart', e => {
            if (e.target.closest('.fi-btn')) { e.preventDefault(); return; }
            _dragSrc = idx; _dragTipo = null;
            e.dataTransfer.effectAllowed = 'move';
            div.classList.add('dragging');
        });
        div.addEventListener('dragend', () => {
            div.classList.remove('dragging');
            $('drop-zone').querySelectorAll('.field-item').forEach(fi =>
                fi.classList.remove('drop-above','drop-below'));
        });
        div.addEventListener('dragover', e => {
            e.preventDefault(); e.dataTransfer.dropEffect = 'move';
            $('drop-zone').querySelectorAll('.field-item').forEach(fi =>
                fi.classList.remove('drop-above','drop-below'));
            const r = div.getBoundingClientRect();
            div.classList.add(e.clientY < r.top + r.height / 2 ? 'drop-above' : 'drop-below');
        });
        div.addEventListener('drop', e => {
            e.stopPropagation();
            $('drop-zone').querySelectorAll('.field-item').forEach(fi =>
                fi.classList.remove('drop-above','drop-below'));
            if (_dragSrc !== null && _dragSrc !== idx) {
                const r = div.getBoundingClientRect();
                const before = e.clientY < r.top + r.height / 2;
                const [moved] = _campos.splice(_dragSrc, 1);
                const dest = _dragSrc < idx ? (before ? idx - 1 : idx) : (before ? idx : idx + 1);
                _campos.splice(dest, 0, moved);
                _dragSrc = null;
                renderCanvas(); renderPreview();
            }
        });
        // Reordenar — Pointer Events (touch / tablet)
        initPointerDrag(div, idx);

        zone.appendChild(div);
    });
}

// ════════════════════════════════════════════════════════════════════
// POINTER DRAG (touch + tablet)
// ════════════════════════════════════════════════════════════════════
let _pDrag = null;

function initPointerDrag(div, idx) {
    const handle = div.querySelector('.fi-handle');
    if (!handle) return;

    handle.addEventListener('pointerdown', e => {
        // Solo si es touch o el botón primario del mouse (pero el mouse usa HTML5)
        if (e.pointerType === 'mouse') return;
        e.preventDefault();
        e.stopPropagation();

        _dragSrc = idx; _dragTipo = null;
        const rect = div.getBoundingClientRect();

        // Crear ghost
        const ghost = document.createElement('div');
        ghost.id = 'drag-ghost';
        ghost.innerHTML = div.querySelector('.fi-icon').outerHTML +
            '<span>' + (div.querySelector('.fi-label')?.textContent || '') + '</span>';
        ghost.style.top  = rect.top  + 'px';
        ghost.style.left = rect.left + 'px';
        ghost.style.width = rect.width + 'px';
        document.body.appendChild(ghost);

        div.classList.add('touch-dragging');
        handle.setPointerCapture(e.pointerId);

        _pDrag = { idx, div, ghost, offsetY: e.clientY - rect.top };
    });

    handle.addEventListener('pointermove', e => {
        if (!_pDrag || _pDrag.idx !== idx) return;
        e.preventDefault();
        const { ghost } = _pDrag;
        ghost.style.top = (e.clientY - _pDrag.offsetY) + 'px';

        // Indicador de posición
        $('drop-zone').querySelectorAll('.field-item').forEach(fi =>
            fi.classList.remove('drop-above','drop-below'));
        ghost.style.display = 'none';
        const el = document.elementFromPoint(e.clientX, e.clientY);
        ghost.style.display = '';
        const target = el?.closest('.field-item');
        if (target && target !== _pDrag.div) {
            const r = target.getBoundingClientRect();
            target.classList.add(e.clientY < r.top + r.height / 2 ? 'drop-above' : 'drop-below');
        }
    });

    const endDrag = e => {
        if (!_pDrag || _pDrag.idx !== idx) return;
        const { div: origDiv, ghost } = _pDrag;

        ghost.style.display = 'none';
        const el = document.elementFromPoint(e.clientX, e.clientY);
        ghost.remove();
        origDiv.classList.remove('touch-dragging');
        $('drop-zone').querySelectorAll('.field-item').forEach(fi =>
            fi.classList.remove('drop-above','drop-below'));

        const target = el?.closest('.field-item');
        if (target && target !== origDiv) {
            const targetIdx = parseInt(target.dataset.idx);
            const r = target.getBoundingClientRect();
            const before = e.clientY < r.top + r.height / 2;
            if (!isNaN(targetIdx) && targetIdx !== idx) {
                const [moved] = _campos.splice(idx, 1);
                const dest = idx < targetIdx
                    ? (before ? targetIdx - 1 : targetIdx)
                    : (before ? targetIdx : targetIdx + 1);
                _campos.splice(dest, 0, moved);
                renderCanvas(); renderPreview();
            }
        }
        _pDrag = null; _dragSrc = null;
    };

    handle.addEventListener('pointerup',     endDrag);
    handle.addEventListener('pointercancel', e => {
        if (!_pDrag || _pDrag.idx !== idx) return;
        _pDrag.ghost.remove();
        _pDrag.div.classList.remove('touch-dragging');
        $('drop-zone').querySelectorAll('.field-item').forEach(fi =>
            fi.classList.remove('drop-above','drop-below'));
        _pDrag = null; _dragSrc = null;
    });
}

function eliminarCampo(idx) {
    _campos.splice(idx, 1);
    renderCanvas();
    renderPreview();
}

// ════════════════════════════════════════════════════════════════════
// RENDER PREVIEW
// ════════════════════════════════════════════════════════════════════
function renderPreview() {
    const pv = $('preview-doc');
    const titulo = $('tb-nombre').value || 'Vista previa';
    const desc   = $('tb-descripcion').value;

    let html = `<h6 style="font-size:13px;font-weight:700;margin:0 0 2px">${esc(titulo)}</h6>`;
    if (desc) html += `<p style="font-size:11px;color:#888;margin:0 0 10px">${esc(desc)}</p>`;
    if (titulo || desc) html += '<hr style="margin:8px 0">';

    if (!_campos.length) {
        html += '<p style="font-size:11px;color:#aaa;text-align:center;margin-top:24px">Agrega campos desde el panel izquierdo</p>';
    } else {
        html += _campos.map(c => renderCampoPreview(c)).join('');
    }

    if ($('tb-firma').checked) {
        const _showCanvas = $('tb-firma-canvas').checked;
        const _showFoto   = $('tb-firma-foto').checked;
        html += `<div class="preview-field" style="margin-top:14px"><label>Firma del paciente</label>`;
        if (_showCanvas) html += `<div style="border:1px solid #dee2e6;border-radius:5px;background:#f5f5f5;height:50px;display:flex;align-items:center;justify-content:center;font-size:11px;color:#aaa;margin-bottom:6px">✍️ Área de dibujo</div>`;
        if (_showFoto)   html += `<div style="border:2px dashed #adb5bd;border-radius:5px;background:#f5f5f5;height:40px;display:flex;align-items:center;justify-content:center;font-size:11px;color:#aaa">📷 Foto de firma</div>`;
        html += `</div>`;
    }
    pv.innerHTML = html;
}

function renderCampoPreview(c) {
    if (c.tipo === 'separador') {
        const condBadge = c.condicion
            ? (()=>{ const vs=(c.condicion.valores||[c.condicion.valor]).join(', '); return `<span title="Visible si: ${esc(vs)}" style="font-size:9px;background:#fff3cd;color:#856404;border-radius:4px;padding:1px 5px;margin-left:6px;vertical-align:middle"><i class="fas fa-eye-slash"></i> si: ${esc(vs)}</span>`; })()
            : '';
        return `<hr class="preview-sep"><div class="preview-sep-label">${esc(c.label)}${condBadge}</div>`;
    }
    const req = c.required ? '<span style="color:#dc3545"> *</span>' : '';
    const lbl = `<label>${esc(c.label)}${req}</label>`;

    if (c.tipo === 'linked') return `<div class="preview-field">${lbl}
        <input type="text" placeholder="Auto-llenado (${esc(c.linked_key)})" disabled></div>`;
    if (c.tipo === 'textarea') return `<div class="preview-field">${lbl}
        <textarea rows="2" disabled placeholder="${esc(c.placeholder||'')}"></textarea></div>`;
    if (c.tipo === 'select') {
        const opts = (c.options||[]).map(o=>`<option>${esc(o)}</option>`).join('');
        return `<div class="preview-field">${lbl}
            <select disabled><option>— seleccionar —</option>${opts}</select></div>`;
    }
    if (c.tipo === 'radio') {
        const opts = (c.options||[]).map(o=>
            `<div style="font-size:11px;margin:2px 0"><input type="radio" disabled> ${esc(o)}</div>`
        ).join('');
        return `<div class="preview-field">${lbl}${opts}</div>`;
    }
    if (c.tipo === 'checkbox') {
        const opts = (c.options||[]).map(o=>
            `<div style="font-size:11px;margin:2px 0"><input type="checkbox" disabled> ${esc(o)}</div>`
        ).join('');
        return `<div class="preview-field">${lbl}${opts}</div>`;
    }
    if (c.tipo === 'firma') {
        return `<div class="preview-field">${lbl}
            <div style="border:1px solid #1565c0;border-radius:5px;height:50px;display:flex;align-items:center;justify-content:center;font-size:11px;color:#1565c0;background:#e8f0fe">✍️ Firma del paciente</div></div>`;
    }
    if (c.tipo === 'firma_profesional') {
        return `<div class="preview-field">${lbl}
            <div style="border:1px solid #198754;border-radius:5px;height:50px;display:flex;align-items:center;justify-content:center;font-size:11px;color:#198754;background:#f0fff4">✍️ Firma del profesional</div></div>`;
    }
    if (c.tipo === 'parrafo') {
        const ws = c.flujoLibre ? 'normal' : 'pre-wrap';
        return `<div class="preview-field" style="font-size:11px;line-height:1.75;color:#222;text-align:justify;white-space:${ws};border-top:1px solid #eee;padding-top:6px">${esc(c.contenido||'')}</div>`;
    }
    if (c.tipo === 'parrafo_inline') {
        const renderLine = line => line.split(/(\{[a-z_]+\})/g).map((p, i) => {
            if (i % 2 === 1) {
                const key = p.slice(1,-1);
                return `<span style="display:inline-block;min-width:80px;border-bottom:1px dashed #888;color:#0055aa;font-size:10px;font-style:italic;vertical-align:baseline;padding:0 2px">${esc(key)}</span>`;
            }
            return esc(p);
        }).join('');
        const html2 = (c.contenido||'').split('\n').map(renderLine).join('<br>');
        return `<div class="preview-field" style="font-size:11px;line-height:2;color:#222;text-align:justify;border-top:1px solid #eee;padding-top:6px">${html2}</div>`;
    }
    if (c.tipo === 'lista_marcable') {
        const items = (c.items||[]).map((it,i) =>
            `<div style="font-size:11px;margin:2px 0"><input type="checkbox" disabled> ${i+1}. ${esc(it)}</div>`
        ).join('');
        return `<div class="preview-field">${lbl}${items}</div>`;
    }
    if (c.tipo === 'fecha_hoy') {
        const hoy = new Date();
        const val = hoy.getFullYear()+'-'+String(hoy.getMonth()+1).padStart(2,'0')+'-'+String(hoy.getDate()).padStart(2,'0');
        return `<div class="preview-field">${lbl}
            <input type="date" value="${val}" disabled style="background:#fff9e6;border-color:#ffc107">
            <small style="color:#856404;font-size:9px"><i class="fas fa-calendar-day"></i> Fecha actual — editable</small>
        </div>`;
    }
    if (c.tipo === 'edad') {
        return `<div class="preview-field">${lbl}
            <input type="number" placeholder="Ej: 34" disabled style="background:#fff9e6;border-color:#ffc107">
            <small style="color:#856404;font-size:9px"><i class="fas fa-user-clock"></i> Edad calculada del paciente — editable</small>
        </div>`;
    }
    const t = c.tipo==='numero'?'number':c.tipo==='fecha'?'date':c.tipo==='hora'?'time':'text';
    return `<div class="preview-field">${lbl}
        <input type="${t}" disabled placeholder="${esc(c.placeholder||'')}"></div>`;
}

// ════════════════════════════════════════════════════════════════════
// EDITOR DE CAMPO (modal)
// ════════════════════════════════════════════════════════════════════
function abrirEditorCampo(idx) {
    _campoIdx = idx;
    const c   = _campos[idx];
    let html  = `<div class="mb-3">
        <label class="form-label small fw-semibold">Etiqueta del campo</label>
        <input type="text" class="form-control" id="ce-label" value="${esc(c.label)}">
    </div>`;

    if (c.tipo === 'separador') {
        // Campos con opciones que pueden controlar visibilidad
        const camposOpciones = _campos.filter(f =>
            ['checkbox','radio','select'].includes(f.tipo) && f.id !== c.id && (f.options||[]).length
        );
        const condCampoId  = c.condicion?.campo_id || '';
        // soporta tanto valor (string) como valores (array)
        const condValores  = c.condicion?.valores || (c.condicion?.valor ? [c.condicion.valor] : []);
        const campoCtrl    = camposOpciones.find(f => f.id === condCampoId);
        const optsCtrl     = campoCtrl ? (campoCtrl.options||[]) : [];

        const optsCampos = camposOpciones.map(f =>
            `<option value="${esc(f.id)}" ${f.id===condCampoId?'selected':''}>${esc(f.label)}</option>`
        ).join('');
        const optsValores = optsCtrl.map(o =>
            `<option value="${esc(o)}" ${condValores.includes(o)?'selected':''}>${esc(o)}</option>`
        ).join('');

        html += `<hr class="my-2">
        <div class="mb-2">
            <label class="form-label small fw-semibold"><i class="fas fa-eye-slash me-1 text-warning"></i>Visibilidad condicional</label>
            <div class="form-text mb-2">Se muestra si alguno de los valores seleccionados está marcado en el campo elegido. Ctrl+clic para selección múltiple.</div>
            <select class="form-select form-select-sm mb-2" id="ce-cond-campo" onchange="actualizarOpcionesCondicion(this.value)">
                <option value="">— Siempre visible —</option>
                ${optsCampos}
            </select>
            <select class="form-select form-select-sm" id="ce-cond-valor" multiple size="5"
                    style="${condCampoId?'':'opacity:.4;pointer-events:none'}"
                    ${condCampoId?'':'disabled'}>
                ${optsValores}
            </select>
            <div class="form-text">Ctrl+clic para marcar varios valores.</div>
        </div>`;
    } else if (c.tipo === 'linked') {
        html += `<div class="alert alert-info small py-2 mb-0">
            <i class="fas fa-info-circle me-1"></i>Campo vinculado al paciente. Se llenará automáticamente al enviar.
        </div>`;
    } else if (['texto','textarea','numero'].includes(c.tipo)) {
        html += `<div class="mb-3">
            <label class="form-label small">Placeholder</label>
            <input type="text" class="form-control form-control-sm" id="ce-placeholder" value="${esc(c.placeholder||'')}">
        </div>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" id="ce-required" ${c.required?'checked':''}>
            <label class="form-check-label small" for="ce-required">Campo obligatorio</label>
        </div>`;
    } else if (['select','radio','checkbox'].includes(c.tipo)) {
        const opts = (c.options||[]).join('\n');
        html += `<div class="mb-3">
            <label class="form-label small">Opciones <small class="text-muted">(una por línea)</small></label>
            <textarea class="form-control form-control-sm" id="ce-options" rows="6"
                      placeholder="Opción 1\nOpción 2">${esc(opts)}</textarea>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" id="ce-required" ${c.required?'checked':''}>
            <label class="form-check-label small" for="ce-required">Campo obligatorio</label>
        </div>`;
    } else if (['fecha','hora'].includes(c.tipo)) {
        html += `<div class="form-check">
            <input class="form-check-input" type="checkbox" id="ce-required" ${c.required?'checked':''}>
            <label class="form-check-label small" for="ce-required">Campo obligatorio</label>
        </div>`;
    } else if (c.tipo === 'parrafo') {
        // Sobreescribir el label genérico: no aplica para párrafo
        html = `<div class="alert alert-warning small py-2 mb-3"><i class="fas fa-paragraph me-1"></i>Párrafo de texto estático</div>` +
               `<div class="mb-2">
                   <label class="form-label small fw-semibold">Contenido del párrafo</label>
                   <textarea class="form-control form-control-sm" id="ce-contenido" rows="8"
                             placeholder="Escribe el texto legal o informativo…">${esc(c.contenido||'')}</textarea>
                   <div class="form-text">El paciente solo puede leer este texto, no lo edita.</div>
               </div>
               <div class="form-check mt-1">
                   <input class="form-check-input" type="checkbox" id="ce-flujo-libre" ${c.flujoLibre?'checked':''}>
                   <label class="form-check-label small" for="ce-flujo-libre">Texto continuo (ignorar saltos de línea) — ideal para consentimientos</label>
               </div>`;
    } else if (c.tipo === 'parrafo_inline') {
        const keys = ['nombre_completo','numero_documento','tipo_documento','fecha_nacimiento','telefono','email','eps','direccion'];
        const chips = keys.map(k => `<span class="badge bg-secondary me-1 mb-1" style="cursor:pointer;font-size:10px" onclick="_insertarKey('${k}')">{${k}}</span>`).join('');
        html = `<div class="alert alert-info small py-2 mb-3"><i class="fas fa-align-left me-1"></i>Párrafo con campos inline — usa <code>{clave}</code> para insertar datos del paciente en el texto</div>` +
               `<div class="mb-1"><label class="form-label small fw-semibold">Claves disponibles (clic para insertar)</label><div class="mb-2">${chips}</div></div>` +
               `<div class="mb-2">
                   <label class="form-label small fw-semibold">Texto del párrafo</label>
                   <textarea class="form-control form-control-sm" id="ce-contenido" rows="8"
                             placeholder="Yo, {nombre_completo}, con N.º {numero_documento}, declaro que…">${esc(c.contenido||'')}</textarea>
                   <div class="form-text">El paciente ve los campos prellenados con sus datos, inline dentro del texto.</div>
               </div>`;
    } else if (c.tipo === 'lista_marcable') {
        const items = (c.items||[]).join('\n');
        html += `<div class="mb-3">
            <label class="form-label small">Ítems <small class="text-muted">(uno por línea)</small></label>
            <textarea class="form-control form-control-sm" id="ce-items" rows="6"
                      placeholder="Secreción Uretral\nTest de glucosa 50gr">${esc(items)}</textarea>
        </div>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" id="ce-required" ${c.required?'checked':''}>
            <label class="form-check-label small" for="ce-required">Requiere al menos una selección</label>
        </div>`;
    } else if (c.tipo === 'fecha_hoy' || c.tipo === 'edad') {
        html += `<div class="alert alert-warning py-2 small mb-2">
            <i class="fas fa-calculator me-1"></i>
            ${c.tipo === 'fecha_hoy'
                ? 'Se pre-llenará con la fecha actual al abrir el formulario.'
                : 'Se pre-llenará con la edad calculada a partir de la fecha de nacimiento del paciente.'}
            El paciente puede editarlo.
        </div>
        <div class="form-check">
            <input class="form-check-input" type="checkbox" id="ce-required" ${c.required?'checked':''}>
            <label class="form-check-label small" for="ce-required">Campo obligatorio</label>
        </div>`;
    } else if (c.tipo === 'firma' || c.tipo === 'firma_profesional') {
        if (c.tipo === 'firma_profesional') {
            const cm = c.modos || ['canvas'];
            html += `<div class="mb-2">
                <label class="form-label small fw-semibold">Modos de firma disponibles</label>
                <div class="d-flex gap-4">
                    <div class="form-check">
                        <input type="checkbox" class="form-check-input" id="ce-modo-canvas" ${cm.includes('canvas')?'checked':''}>
                        <label class="form-check-label small" for="ce-modo-canvas">✍️ Dibujar (canvas)</label>
                    </div>
                    <div class="form-check">
                        <input type="checkbox" class="form-check-input" id="ce-modo-foto" ${cm.includes('foto')?'checked':''}>
                        <label class="form-check-label small" for="ce-modo-foto">📷 Foto</label>
                    </div>
                </div>
            </div>`;
        } else {
            html += `<div class="alert alert-info py-2 small mb-2">
                <i class="fas fa-info-circle me-1"></i>
                Los modos del paciente (<strong>✍️ Dibujar / 📷 Foto</strong>) se configuran
                desde el panel superior <strong>↑</strong> (sección <em>Firma del paciente</em>).
            </div>`;
        }
    }

    $('campo-editor-body').innerHTML = html;
    $('campo-save-btn').onclick = aplicarCampo;

    if (!_bsCampo) _bsCampo = new bootstrap.Modal('#modalCampo');
    _bsCampo.show();

    // Foco al label
    setTimeout(() => document.getElementById('ce-label')?.select(), 200);
}

function actualizarOpcionesCondicion(campoId) {
    const selValor = document.getElementById('ce-cond-valor');
    if (!selValor) return;
    if (!campoId) {
        selValor.innerHTML = '';
        selValor.disabled = true;
        selValor.style.opacity = '.4';
        selValor.style.pointerEvents = 'none';
        return;
    }
    const campo = _campos.find(f => f.id === campoId);
    const opts  = campo?.options || [];
    selValor.innerHTML = opts.map(o => `<option value="${esc(o)}">${esc(o)}</option>`).join('');
    selValor.disabled = false;
    selValor.style.opacity = '';
    selValor.style.pointerEvents = '';
}

function _insertarKey(key) {
    const ta = document.getElementById('ce-contenido');
    if (!ta) return;
    const s = ta.selectionStart, e = ta.selectionEnd;
    const v = ta.value;
    ta.value = v.slice(0, s) + '{' + key + '}' + v.slice(e);
    ta.selectionStart = ta.selectionEnd = s + key.length + 2;
    ta.focus();
}

function aplicarCampo() {
    const c = _campos[_campoIdx];
    const labelEl = document.getElementById('ce-label');
    if (labelEl) c.label = labelEl.value.trim() || c.label;

    const ph = document.getElementById('ce-placeholder');
    if (ph) c.placeholder = ph.value;

    const req = document.getElementById('ce-required');
    if (req) c.required = req.checked;

    const opts = document.getElementById('ce-options');
    if (opts) c.options = opts.value.split('\n').map(s=>s.trim()).filter(Boolean);

    const contenido = document.getElementById('ce-contenido');
    if (contenido) c.contenido = contenido.value;

    const flujoLibre = document.getElementById('ce-flujo-libre');
    if (flujoLibre !== null) c.flujoLibre = flujoLibre.checked;

    const items = document.getElementById('ce-items');
    if (items) c.items = items.value.split('\n').map(s=>s.trim()).filter(Boolean);

    const modoCanvas = document.getElementById('ce-modo-canvas');
    const modoFoto   = document.getElementById('ce-modo-foto');
    if (modoCanvas !== null || modoFoto !== null) {
        const mc = [];
        if (modoCanvas?.checked) mc.push('canvas');
        if (modoFoto?.checked)   mc.push('foto');
        if (mc.length) c.modos = mc;
    }

    // Condición de visibilidad (solo separadores)
    const condCampo = document.getElementById('ce-cond-campo');
    const condValor = document.getElementById('ce-cond-valor');
    if (condCampo !== null) {
        const selVals = condValor
            ? [...condValor.selectedOptions].map(o => o.value).filter(Boolean)
            : [];
        if (condCampo.value && selVals.length) {
            // ponytail: valores[] siempre, forma unificada
            c.condicion = { campo_id: condCampo.value, valores: selVals };
        } else {
            delete c.condicion;
        }
    }

    _bsCampo.hide();
    renderCanvas();
    renderPreview();
}

// ════════════════════════════════════════════════════════════════════
// DISEÑO DEL DOCUMENTO
// ════════════════════════════════════════════════════════════════════
function toggleDocSection() {
    _docOpen = !_docOpen;
    $('doc-section-body').style.display = _docOpen ? '' : 'none';
    $('doc-chevron').style.transform = _docOpen ? 'rotate(180deg)' : '';
}

function toggleDocGlobal(usarGlobal) {
    $('doc-override-fields').style.display = usarGlobal ? 'none' : '';
    $('doc-global-hint').style.display     = usarGlobal ? ''     : 'none';
}

function cargarLogo(input) {
    const file = input.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = e => {
        const b64 = e.target.result;
        $('tb-logo-base64').value = b64;
        $('tb-logo-img').src = b64;
        $('tb-logo-preview').style.display = '';
    };
    reader.readAsDataURL(file);
}

function quitarLogo() {
    $('tb-logo-base64').value = '';
    $('tb-logo-img').src = '';
    $('tb-logo-preview').style.display = 'none';
    $('tb-logo-file').value = '';
}

// ════════════════════════════════════════════════════════════════════
// CARGAR FORMULARIO EXISTENTE
// ════════════════════════════════════════════════════════════════════
async function cargarFormulario(id) {
    sbStatus('Cargando formulario…', true);
    const r = await fetch(`api/lab/get_formularios.php?id=${id}`);
    const d = await r.json();
    const f = d.formulario;
    if (!f) { sbStatus('Error al cargar', false); return; }

    $('tb-nombre').value      = f.nombre;
    $('tb-descripcion').value = f.descripcion || '';
    $('tb-categoria').value   = f.categoria;
    $('tb-firma').checked        = !!f.permite_firma;
    $('tb-firma-req').checked    = !!f.requiere_firma;
    _campos = f.esquema_decoded || [];
    // Leer modos: primero columna dedicada, luego campo tipo:'firma' en esquema, nunca defaultear a foto
    const _firmaCampo = _campos.find(c => c.tipo === 'firma');
    const _fModosStr  = f.firma_modos || '';   // columna DB: 'canvas', 'foto', 'canvas,foto' o ''
    const _fModos     = _fModosStr
        ? _fModosStr.split(',').map(m => m.trim()).filter(Boolean)
        : (_firmaCampo?.modos ?? ['canvas','foto']);
    $('tb-firma-canvas').checked = _fModos.includes('canvas');
    $('tb-firma-foto').checked   = _fModos.includes('foto');

    // Campos doc
    const tieneOverride = !!(f.doc_encabezado || f.doc_logo_base64 || f.doc_color);
    $('tb-usar-global').checked = !tieneOverride;
    toggleDocGlobal(!tieneOverride);
    $('tb-doc-encabezado').value  = f.doc_encabezado  || '';
    $('tb-doc-subtitulo').value   = f.doc_subtitulo   || '';
    $('tb-doc-color').value       = f.doc_color       || _globalCfg.doc_color || '#1565c0';
    $('tb-doc-pie').value         = f.doc_pie_pagina  || '';
    $('tb-logo-base64').value     = f.doc_logo_base64 || '';
    if (f.doc_logo_base64) {
        $('tb-logo-img').src = f.doc_logo_base64;
        $('tb-logo-preview').style.display = '';
    }

    document.title = `Editar: ${f.nombre} — Builder Lab`;
    $('sb-form-id').textContent = `Form #${id}: ${f.nombre}`;

    renderCanvas();
    renderPreview();
    sbStatus('Listo', true);
}

// ════════════════════════════════════════════════════════════════════
// GUARDAR
// ════════════════════════════════════════════════════════════════════
async function guardar() {
    const nombre = $('tb-nombre').value.trim();
    if (!nombre) {
        $('tb-nombre').classList.add('is-invalid');
        $('tb-nombre').focus();
        showToast('⚠️ Ingresa el nombre del formulario', '#e65100');
        return;
    }
    if (!_campos.length) {
        showToast('⚠️ Agrega al menos un campo', '#e65100');
        return;
    }
    $('tb-nombre').classList.remove('is-invalid');

    const usarGlobal = $('tb-usar-global').checked;
    // Sincronizar modos ANTES de serializar el esquema
    const _modos = []; if($('tb-firma-canvas').checked)_modos.push('canvas'); if($('tb-firma-foto').checked)_modos.push('foto');
    const datos = {
        nombre,
        descripcion:     $('tb-descripcion').value.trim() || null,
        categoria:       $('tb-categoria').value,
        esquema:         JSON.stringify(_campos),
        permite_firma:   $('tb-firma').checked     ? 1 : 0,
        requiere_firma:  $('tb-firma-req').checked ? 1 : 0,
        firma_modos:     _modos.length ? _modos.join(',') : 'canvas',
        doc_encabezado:  usarGlobal ? null : ($('tb-doc-encabezado').value.trim() || null),
        doc_subtitulo:   usarGlobal ? null : ($('tb-doc-subtitulo').value.trim()  || null),
        doc_color:       usarGlobal ? null : ($('tb-doc-color').value || null),
        doc_logo_base64: usarGlobal ? null : ($('tb-logo-base64').value || null),
        doc_pie_pagina:  usarGlobal ? null : ($('tb-doc-pie').value.trim() || null),
    };
    if (FORM_ID) datos.id = FORM_ID;

    const btn = $('btn-save');
    btn.disabled = true;
    btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1" style="width:.75em;height:.75em"></span>Guardando…';
    sbStatus('Guardando…', true);

    try {
        const r = await fetch('api/lab/save_formulario.php', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(datos),
        });
        const d = await r.json();
        if (d.success) {
            _saved = true;
            sbStatus('Guardado ✓', true);

            // Notificar ventana padre para refrescar lista
            if (window.opener && !window.opener.closed) {
                window.opener.postMessage('builder:saved', '*');
            }

            // Actualizar ID si era formulario nuevo
            const savedId = d.id || FORM_ID;
            if (!FORM_ID && d.id) {
                history.replaceState({}, '', `?id=${d.id}`);
                $('sb-form-id').textContent = `Form #${d.id}: ${nombre}`;
            }

            // Mostrar pantalla de éxito
            $('success-title').textContent = '¡Formulario guardado!';
            $('success-sub').textContent   = `"${nombre}" fue guardado correctamente.`;
            $('success-screen').classList.add('show');

            // Si la ventana tiene opener, intentar cerrar automáticamente
            if (window.opener && !window.opener.closed) {
                setTimeout(() => {
                    try { window.close(); } catch(e) {}
                }, 1600);
            }
        } else {
            showToast('❌ ' + (d.error || 'Error al guardar'), '#c62828');
            sbStatus('Error al guardar', false);
        }
    } catch(e) {
        showToast('❌ Error de red', '#c62828');
        sbStatus('Error de red', false);
    } finally {
        btn.disabled = false;
        btn.innerHTML = '<i class="fas fa-save me-1"></i>Guardar';
    }
}

// ════════════════════════════════════════════════════════════════════
// PANTALLA DE ÉXITO
// ════════════════════════════════════════════════════════════════════
function irAFormularios() {
    if (window.opener && !window.opener.closed) {
        window.close();
    } else {
        window.location.href = 'lab_formularios.php';
    }
}

function seguirEditando() {
    $('success-screen').classList.remove('show');
    _saved = false; // permitir volver a guardar después de editar
}

// ════════════════════════════════════════════════════════════════════
// CERRAR
// ════════════════════════════════════════════════════════════════════
function cerrar() {
    if (_saved || !_campos.length) { window.close(); return; }
    if (confirm('¿Cerrar sin guardar los cambios?')) window.close();
}

// Ctrl+S para guardar
document.addEventListener('keydown', e => {
    if ((e.ctrlKey || e.metaKey) && e.key === 's') {
        e.preventDefault();
        guardar();
    }
});

// Prevenir cierre accidental si hay cambios
window.addEventListener('beforeunload', e => {
    if (!_saved && _campos.length) {
        e.preventDefault();
        e.returnValue = '';
    }
});

// ════════════════════════════════════════════════════════════════════
// INIT
// ════════════════════════════════════════════════════════════════════
// Ocultar doc-section-body por defecto
$('doc-section-body').style.display = 'none';

document.addEventListener('DOMContentLoaded', async () => {
    // Preview auto-update al cambiar nombre/descripción
    $('tb-nombre').addEventListener('input', renderPreview);
    $('tb-descripcion').addEventListener('input', renderPreview);
    $('tb-firma').addEventListener('change', renderPreview);
    $('tb-firma-canvas').addEventListener('change', renderPreview);
    $('tb-firma-foto').addEventListener('change', renderPreview);

    // Cargar config global
    try {
        const r = await fetch('api/lab/get_config.php');
        const d = await r.json();
        if (d.success) {
            _globalCfg = d.config || {};
            $('tb-doc-color').value = _globalCfg.doc_color || '#1565c0';
        }
    } catch(e) {}

    renderPalette();

    if (FORM_ID) {
        await cargarFormulario(FORM_ID);
    } else {
        renderCanvas();
        renderPreview();
    }
});
</script>
<script src="assets/js/lab-sidebar.js"></script>
</body>
</html>
