<?php
session_start();

// ==========================================
//  1. CONFIGURACIÓN
// ==========================================
$CONFIG = [
    'password' => '33comRxX', 
    'root' => "../../../" 
];

// ==========================================
//  2. LOGIN Y CONTROL
// ==========================================
if (isset($_GET['logout'])) {
    session_destroy();
    header("Location: " . basename(__FILE__));
    exit;
}

if (isset($_POST['login_pass'])) {
    if ($_POST['login_pass'] === $CONFIG['password']) {
        $_SESSION['editor_logged_in'] = true;
    } else {
        $error = "Contraseña incorrecta";
    }
}

if (isset($_GET['open']) && isset($_SESSION['editor_logged_in'])) {
    $_SESSION['forced_open_path'] = $_GET['open'];
    header("Location: " . basename(__FILE__)); 
    exit;
}

if (empty($_SESSION['editor_logged_in'])) {
    ?>
    <!DOCTYPE html>
    <html lang="es">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Login - IDE Pro</title>
        <style>
            body { background:#1e1e1e; color:#ccc; font-family:sans-serif; display:flex; height:100vh; justify-content:center; align-items:center; margin:0; }
            form { background:#252526; padding:40px; border-radius:8px; width:300px; text-align:center; border:1px solid #333; box-shadow:0 10px 30px rgba(0,0,0,0.5); }
            input { padding:10px; width:100%; box-sizing:border-box; background:#3c3c3c; color:white; border:1px solid #444; margin-bottom:15px; outline:none; }
            input:focus { border-color:#007acc; }
            button { padding:10px; background:#007acc; color:white; border:none; width:100%; cursor:pointer; font-weight:bold; }
            button:hover { background:#005f9e; }
            .error { color:#ff6b6b; margin-bottom:15px; font-size:14px; background:rgba(255,0,0,0.1); padding:10px; }
        </style>
    </head>
    <body>
        <form method="POST">
            <h3 style="margin-top:0;">IDE V24.8</h3>
            <?php if(isset($error)) echo "<div class='error'>$error</div>"; ?>
            <input type="password" name="login_pass" placeholder="Contraseña" autofocus>
            <button>Entrar</button>
        </form>
    </body>
    </html>
    <?php exit;
}

// ==========================================
//  3. API BACKEND
// ==========================================
if (isset($_GET['action'])) {
    header('Content-Type: application/json');
    $root = $CONFIG['root'];

    function securePath($base, $req) { 
        $path = $base . DIRECTORY_SEPARATOR . $req; 
        $path = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path); 
        $realPath = realpath($base) ? realpath($base) : $base;
        $fullPath = realpath($path) ? realpath($path) : $path;
        if ($fullPath === false || strpos($fullPath, $realPath) !== 0) {
            if (file_exists($path) && strpos($path, $base) !== 0) throw new Exception("Ruta inválida.");
        }
        return $path; 
    }
    
    function rrmdir($dir) { 
        if (is_dir($dir)) { 
            $objects = scandir($dir); 
            foreach ($objects as $object) { 
                if ($object != "." && $object != "..") { 
                    if (is_dir($dir.DIRECTORY_SEPARATOR.$object) && !is_link($dir.DIRECTORY_SEPARATOR.$object)) rrmdir($dir.DIRECTORY_SEPARATOR.$object);
                    else unlink($dir.DIRECTORY_SEPARATOR.$object); 
                } 
            } rmdir($dir); 
        } 
    }

    try {
        $act = $_GET['action'];
        $in = json_decode(file_get_contents('php://input'), true) ?? [];

        if ($act === 'list') {
            $rel = $_GET['path'] ?? '';
            $dir = securePath($root, $rel);
            if (!is_dir($dir)) $dir = $root;
            $files = scandir($dir);
            $out = [];
            foreach($files as $f) {
                if($f=='.' || $f=='..') continue;
                if($f == basename(__FILE__)) continue; 
                $path = ($rel ? $rel.'/' : '') . $f;
                $out[] = ['name'=>$f, 'type'=>is_dir($dir.DIRECTORY_SEPARATOR.$f)?'folder':'file', 'path'=>$path];
            }
            usort($out, fn($a,$b) => ($b['type']==='folder') <=> ($a['type']==='folder'));
            echo json_encode(['items'=>$out]);
        }
        elseif ($act === 'load') {
            $path = securePath($root, $_GET['file']);
            if(!file_exists($path)) throw new Exception("No existe.");
            echo json_encode(['content'=>file_get_contents($path)]);
        }
        elseif ($act === 'save') {
            $path = securePath($root, $in['file']);
            if(file_put_contents($path, $in['content']) !== false) echo json_encode(['status'=>'success']);
            else throw new Exception("Error guardando.");
        }
        elseif ($act === 'save_state') {
            $_SESSION['editor_state'] = $in['state'];
            echo json_encode(['status'=>'success']);
        }
        elseif ($act === 'create') {
            $path = securePath($root, $in['path']);
            if ($in['type'] === 'folder') { if(!is_dir($path) && !mkdir($path)) throw new Exception("Error mkdir"); } 
            else { if(!touch($path)) throw new Exception("Error touch"); }
            echo json_encode(['status'=>'success']);
        }
        elseif ($act === 'rename') {
            if(!rename(securePath($root, $in['old']), securePath($root, $in['new']))) throw new Exception("Error rename");
            echo json_encode(['status'=>'success']);
        }
        elseif ($act === 'delete') {
            $path = securePath($root, $in['path']);
            if(is_dir($path)) rrmdir($path); else unlink($path);
            echo json_encode(['status'=>'success']);
        }
        elseif ($act === 'copy') { 
            $src = securePath($root, $in['src']);
            $destFolder = securePath($root, $in['dest']);
            $finalDest = $destFolder . DIRECTORY_SEPARATOR . basename($src);
            if(file_exists($finalDest)) $finalDest = $destFolder . DIRECTORY_SEPARATOR . 'copy_' . basename($src);
            if (is_dir($src)) throw new Exception("Folder copy not supported.");
            if(!copy($src, $finalDest)) throw new Exception("Error copy.");
            echo json_encode(['status'=>'success']);
        }
    } catch (Exception $e) { http_response_code(400); echo json_encode(['error'=>$e->getMessage()]); }
    exit;
}

$editor_state = isset($_SESSION['editor_state']) ? $_SESSION['editor_state'] : null;
if (isset($_SESSION['forced_open_path'])) {
    $editor_state['forcedOpenPath'] = $_SESSION['forced_open_path'];
    unset($_SESSION['forced_open_path']); 
}
$editor_state_json = json_encode($editor_state);
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IDE Pro - Dual View V24.8</title>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
    
    <style>
        :root { 
            --bg: #1e1e1e; --sidebar: #252526; --border: #333; 
            --accent: #007acc; --text: #cccccc; --text-muted: #858585;
            --folder: #dcb67a; --file: #5caefc;
            --danger: #f48771; --success: #89d185;
            --warning: #f1c40f;
        }
        
        * { box-sizing: border-box; user-select: none; outline: none; }
        ::-webkit-scrollbar { width: 8px; height: 8px; background: var(--bg); }
        ::-webkit-scrollbar-thumb { background: #444; border-radius: 4px; }
        
        body { margin:0; height:100vh; display:flex; background:var(--bg); color:var(--text); font-family:'Inter', sans-serif; overflow:hidden; font-size: 13px; }
        
        #sidebar { width: 250px; background: var(--sidebar); border-right: 1px solid var(--border); display: flex; flex-direction: column; }

        .sidebar-head { height: 35px; padding: 0 10px; font-weight: 600; display: flex; justify-content: space-between; align-items: center; border-bottom:1px solid #000; font-size:11px; text-transform:uppercase; color:var(--text-muted); }
        #file-tree { flex: 1; overflow-y: auto; padding-top: 5px; }
        
        .tree-content { display: flex; align-items: center; padding: 4px 12px; cursor: pointer; color: var(--text); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; border-left: 2px solid transparent; }
        .tree-content:hover { background: #2a2d2e; }
        .tree-content.active { background: #37373d; color: white; border-left: 2px solid var(--accent); }
        .tree-content i { font-size: 16px; margin-right: 8px; color: var(--text-muted); }
        .tree-content.folder > i { color: var(--folder); }
        .tree-content.file > i { color: var(--file); }
        .tree-children { display: none; margin-left: 12px; border-left: 1px solid #333; }
        .expanded > .tree-content > .tree-arrow { transform: rotate(90deg); }
        .tree-arrow { font-size:14px !important; transition:0.2s; }

        #main { flex: 1; display: flex; flex-direction: column; min-width: 0; }
        
        #toolbar { height: 42px; background: var(--bg); display: flex; align-items: center; padding: 0 10px; gap: 5px; border-bottom: 1px solid var(--border); }
        .tool-btn { background: transparent; border: none; color: var(--text-muted); width: 32px; height: 32px; border-radius: 4px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: 0.2s; position:relative; }
        .tool-btn:hover, .tool-btn.active { background: #333; color: var(--text); }
        .tool-sep { width:1px; height:20px; background:var(--border); margin:0 4px; }
        
        .dropdown-menu { display: none; position: absolute; top: 40px; left: 0; z-index: 1000; background: #252526; border: 1px solid #454545; box-shadow: 0 5px 20px rgba(0,0,0,0.5); border-radius: 4px; width: 240px; max-height: 400px; overflow-y: auto; }
        .dropdown-menu.show { display: block; }
        .dd-item { padding: 8px 15px; cursor: pointer; display: flex; align-items: center; gap: 10px; color: #ccc; font-size: 12px; border-bottom: 1px solid #2d2d2d; }
        .dd-item:hover { background: var(--accent); color: white; }
        .dd-item small { margin-left: auto; font-family: monospace; opacity: 0.5; font-size: 10px; }
        .dd-header { padding: 8px 10px; font-size: 10px; color: #858585; font-weight: bold; text-transform: uppercase; background:#1e1e1e; position:sticky; top:0; z-index:2; border-bottom: 1px solid #333; }

        #tab-bar { height: 32px; background: var(--bg); display: flex; overflow-x: auto; align-items: flex-end; }
        .tab { background: #2d2d2d; color: #888; padding: 0 12px; font-size: 12px; cursor: pointer; border-right: 1px solid var(--border); height: 30px; display: flex; align-items: center; gap: 8px; min-width: 100px; max-width: 200px; position:relative; }
        .tab:hover { background: #333; }
        .tab.active { background: var(--bg); color: white; height: 32px; border-top: 2px solid var(--accent); }
        .tab.dirty span::after { content: ' ●'; color: var(--danger); font-size: 14px; line-height: 0; }
        .tab-close { border-radius: 50%; padding: 2px; font-size: 12px; opacity: 0; transition:0.2s; }
        .tab:hover .tab-close { opacity: 1; }
        .tab-close:hover { background: #cc4444; color: white; }

        #dep-bar { height: 28px; background: #2d2d30; display: none; align-items: center; padding: 0 10px; gap:10px; font-size:11px; border-bottom:1px solid #333; overflow-x: auto; }
        .dep-label { font-weight: bold; color: #666; font-size: 10px; text-transform: uppercase; }
        .dep-link { color: var(--file); cursor: pointer; text-decoration: none; padding: 2px 6px; border-radius: 3px; display:flex; align-items:center; gap:4px; }
        .dep-link:hover { background: #3e3e42; color: white; }

        #split-container { flex: 1; display: flex; position: relative; background: #1e1e1e; }
        .editor-wrapper { flex: 1; display: flex; flex-direction: column; min-width: 0; position:relative; border-right: 1px solid #000; }
        #wrapper-right { display: none; border-left: 1px solid var(--border); width: 50%; }
        
        .editor-label { position:absolute; top:0; right:15px; background:rgba(0,0,0,0.6); color:#888; font-size:10px; padding:2px 8px; z-index:10; pointer-events:none; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; }
        .editor-wrapper.focused .editor-label { color: var(--accent); background: rgba(0,122,204,0.1); border: 1px solid var(--accent); border-top:none; }

        #ctx-menu { display: none; position: absolute; z-index: 9999; background: #252526; border: 1px solid #454545; box-shadow: 0 5px 15px rgba(0,0,0,0.5); min-width: 180px; padding: 5px 0; border-radius: 4px; }
        .ctx-item { padding: 8px 15px; cursor: pointer; font-size: 12px; display: flex; align-items: center; gap: 10px; color: #ccc; }
        .ctx-item:hover { background: var(--accent); color: white; }

        #toast { position: fixed; bottom: 22px; right: 22px; background: #333; color: white; padding: 12px 20px; border-radius: 4px; transform: translateY(100px); transition: 0.3s; z-index: 2000; box-shadow: 0 10px 30px rgba(0,0,0,0.5); display:flex; gap:12px; align-items:center; font-weight: 500; border-left: 4px solid var(--success); }
        #toast.show { transform: translateY(0); }
        #toast.error { border-left-color: var(--danger); }
        #toast.warning { border-left-color: var(--warning); background: #333; }
        
        /* Ajuste para la caja de búsqueda de ACE */
        .ace_search { background-color: #252526 !important; border: 1px solid #454545 !important; color: #ccc !important; }
        .ace_search_field { background-color: #3c3c3c !important; color: white !important; border: 1px solid #555 !important; }
        .ace_button { border: 1px solid #444 !important; color: #ccc !important; }
        .ace_button:hover { background-color: #444 !important; }
    </style>
</head>
<body onclick="closeDropdowns()">

<div id="sidebar">
    <div class="sidebar-head">
        <span>Explorador</span>
        <i class="material-icons tool-btn" onclick="initTree()" title="Recargar">refresh</i>
    </div>
    <div id="file-tree" oncontextmenu="showCtxGlobal(event)"></div>
</div>

<div id="main">
    <div id="tab-bar"></div>
    
    <div id="toolbar">
        <button class="tool-btn" onclick="saveAll()" title="Guardar Todo (Ctrl+S)">
            <i class="material-icons" style="color:var(--success)">save</i>
        </button>
        <div class="tool-sep"></div>
        <button class="tool-btn" onclick="triggerUndo()" title="Deshacer (Ctrl+Z)"><i class="material-icons">undo</i></button>
        <button class="tool-btn" onclick="triggerRedo()" title="Rehacer (Ctrl+Y)"><i class="material-icons">redo</i></button>
        
        <div class="tool-sep"></div>
        <button class="tool-btn" onclick="copySelected()" title="Copiar (Ctrl+C)"><i class="material-icons">content_copy</i></button>
        <button class="tool-btn" onclick="pasteContent()" title="Pegar (Ctrl+V)"><i class="material-icons">content_paste</i></button>
        <button class="tool-btn" onclick="selectAll()" title="Seleccionar Todo (Ctrl+A)"><i class="material-icons">select_all</i></button>
        
        <div class="tool-sep"></div>
        <button class="tool-btn" onclick="triggerSearch()" title="Buscar (Ctrl+F)"><i class="material-icons">search</i></button>
        <button class="tool-btn" onclick="triggerReplace()" title="Reemplazar (Ctrl+H)"><i class="material-icons">find_replace</i></button>

        <div class="tool-sep"></div>
        <div style="position: relative;">
            <button class="tool-btn" onclick="toggleDropdown('snip-menu', event)" title="Insertar Snippets">
                <i class="material-icons" style="color:var(--folder)">code</i>
            </button>
            <div id="snip-menu" class="dropdown-menu"></div>
        </div>
        <button class="tool-btn" onclick="formatActive()" title="Formatear"><i class="material-icons">auto_fix_high</i></button>
        <div style="flex:1"></div>
        <button class="tool-btn" id="btn-close-split" style="display:none; color:var(--danger); margin-right:5px;" onclick="closeSplit()" title="Cerrar Panel Derecho">
            <i class="material-icons">vertical_split</i>
        </button>
        <a href="?logout" class="tool-btn" title="Cerrar Sesión"><i class="material-icons" style="color:var(--danger)">logout</i></a>
    </div>

    <div id="dep-bar">
        <span class="dep-label">Dependencias:</span> 
        <div id="dep-list" style="display:flex; gap:10px;"></div>
    </div>

    <div id="split-container">
        <div class="editor-wrapper focused" id="wrapper-left" onclick="setFocus('left')">
            <div class="editor-label">PRINCIPAL</div>
            <div id="editor-left" style="flex:1;"></div>
        </div>
        <div class="editor-wrapper" id="wrapper-right" onclick="setFocus('right')">
            <div class="editor-label">VISIÓN DUAL</div>
            <div id="editor-right" style="flex:1;"></div>
        </div>
    </div>
</div>

<div id="ctx-menu">
    <div class="ctx-item" onclick="fileAction('newFile')"><i class="material-icons" style="color:var(--success)">note_add</i> Nuevo Archivo</div>
    <div class="ctx-item" onclick="fileAction('newFolder')"><i class="material-icons" style="color:var(--folder)">create_new_folder</i> Nueva Carpeta</div>
    <div style="height:1px; background:#444; margin:4px 0;"></div>
    <div class="ctx-item" onclick="fileAction('copy')"><i class="material-icons">content_copy</i> Copiar</div>
    <div class="ctx-item" onclick="fileAction('paste')"><i class="material-icons">content_paste</i> Pegar</div>
    <div style="height:1px; background:#444; margin:4px 0;"></div>
    <div class="ctx-item" onclick="fileAction('rename')"><i class="material-icons">edit</i> Renombrar</div>
    <div class="ctx-item" onclick="fileAction('delete')"><i class="material-icons" style="color:var(--danger)">delete</i> Eliminar</div>
</div>

<div id="toast"><i class="material-icons">check_circle</i> <span>Mensaje</span></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-beautify.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-modelist.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-searchbox.js"></script> <script>
    const sessionState = <?php echo $editor_state_json; ?>;
    let editorLeft, editorRight, activeEditorObj = null;
    let leftPath = null, rightPath = null, isSplit = false;
    let openSessions = {}, ctxTarget = null, clipboard = null;

    const snippets = {
        'PHP': [
            {n:'PHP Block', c:"<" + "?php\n    ${1}\n?" + ">"},
            {n:'Echo', c:"echo '${1}';"},
            {n:'Echo HTML', c:"<" + "?= ${1} ?" + ">"},
            {n:'If Statement', c:"if (${1:condition}) {\n    ${2}\n}"},
            {n:'If / Else', c:"if (${1}) {\n    ${2}\n} else {\n    ${3}\n}"},
            {n:'Foreach', c:"foreach ($${1:vars} as $${2:val}) {\n    ${3}\n}"},
            {n:'Function', c:"function ${1:name}(${2:params}) {\n    ${3}\n}"},
            {n:'Class', c:"class ${1:Name} {\n    public function __construct() {\n        ${2}\n    }\n}"},
            {n:'Try Catch', c:"try {\n    ${1}\n} catch (Exception $e) {\n    die($e->getMessage());\n}"},
            {n:'Include', c:"include '${1:file}.php';"},
            {n:'Require', c:"require '${1:file}.php';"},
            {n:'Isset', c:"isset($${1:var})"},
            {n:'Empty', c:"!empty($${1:var})"},
            {n:'JSON Enc', c:"json_encode(${1:array});"},
            {n:'JSON Dec', c:"json_decode(${1:json}, true);"},
            {n:'Redirect', c:"header('Location: ${1:url}');\nexit;"},
            {n:'Session', c:"session_start();"},
            {n:'POST', c:"$_POST['${1:key}']"},
            {n:'GET', c:"$_GET['${1:key}']"},
            {n:'Debug', c:"var_dump(${1}); exit;"}
        ],
        'HTML': [
            {n:'HTML5 Boiler', c:"<!DOCTYPE html>\n<html lang=\"es\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>${1:Title}</title>\n</head>\n<body>\n    ${2}\n</body>\n</html>"},
            {n:'Div Class', c:"<div class=\"${1:class}\">\n    ${2}\n</div>"},
            {n:'Div ID', c:"<div id=\"${1:id}\">\n    ${2}\n</div>"},
            {n:'Span', c:"<span>${1}</span>"},
            {n:'Link', c:"<a href=\"${1:#}\">${2:Link}</a>"},
            {n:'Image', c:"<img src=\"${1:url}\" alt=\"${2:alt}\">"},
            {n:'UL List', c:"<ul>\n    <li>${1}</li>\n</ul>"},
            {n:'Table', c:"<table>\n    <tr>\n        <td>${1}</td>\n    </tr>\n</table>"},
            {n:'Form Post', c:"<form method=\"POST\" action=\"${1}\">\n    ${2}\n</form>"},
            {n:'Input', c:"<input type=\"text\" name=\"${1:name}\" placeholder=\"${2}\">"},
            {n:'Button', c:"<button type=\"submit\">${1:Send}</button>"},
            {n:'Script', c:"<script>\n    ${1}\n<\/script>"},
            {n:'Script Src', c:"<script src=\"${1}.js\"><\/script>"},
            {n:'Style', c:"<style>\n    ${1}\n<\/style>"},
            {n:'CSS Link', c:"<link rel=\"stylesheet\" href=\"${1}.css\">"},
            {n:'Viewport', c:"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"},
            {n:'Select', c:"<select name=\"${1}\">\n    <option value=\"${2}\">${3}</option>\n</select>"},
            {n:'Textarea', c:"<textarea name=\"${1}\"></textarea>"},
            {n:'Label', c:"<label for=\"${1}\">${2}</label>"}
        ]
    };

    window.onload = function() {
        editorLeft = ace.edit("editor-left"); setupEditor(editorLeft);
        editorRight = ace.edit("editor-right"); setupEditor(editorRight);
        activeEditorObj = editorLeft;
        
        buildSnippetsMenu();
        initTree();
        loadInitialState();
        
        document.addEventListener('keydown', e => { 
            if ((e.ctrlKey || e.metaKey) && e.key === 's') { e.preventDefault(); saveAll(); } 
        });
    };

    function setupEditor(ed) {
        ed.setTheme("ace/theme/tomorrow_night_eighties");
        ed.setFontSize(14);
        ed.setOptions({ enableBasicAutocompletion: true, enableLiveAutocompletion: true, enableSnippets: true, showPrintMargin: false, fontFamily: "'Fira Code', monospace" });
        ed.on("focus", function() {
            activeEditorObj = ed;
            if(ed === editorLeft) setFocus('left');
            if(ed === editorRight) setFocus('right');
        });
    }

    async function loadFile(path, target = 'left') {
        path = path.replace(/^\/+/, '');
        let session;
        if (openSessions[path]) {
            session = openSessions[path];
        } else {
            try {
                const r = await fetch(`?action=load&file=${path}`);
                if (!r.ok) throw new Error("Error cargando archivo");
                const d = await r.json();
                const mode = ace.require("ace/ext/modelist").getModeForPath(path).mode;
                session = ace.createEditSession(d.content, mode);
                session.setUndoManager(new ace.UndoManager());
                session.on('change', () => { 
                    const isDirty = session.getValue() !== d.content; 
                    const tab = document.querySelector(`.tab[data-path="${path}"]`);
                    if(tab) tab.classList.toggle('dirty', isDirty);
                    if (leftPath === path) setTimeout(scanDeps, 1000);
                });
                openSessions[path] = session;
                if (target === 'left') createTabUI(path);
            } catch (e) { toast(e.message, 'error'); return; }
        }

        if (target === 'left') {
            leftPath = path;
            editorLeft.setSession(session);
            activeEditorObj = editorLeft;
            updateTabsUI(path);
            scanDeps(); 
            if (rightPath === path) closeSplit();
        } else if (target === 'right') {
            rightPath = path;
            editorRight.setSession(session);
            openSplitView();
            activeEditorObj = editorRight;
        }
    }

    async function saveAll() {
        const promises = [];
        const pathsToUpdate = [];

        if (leftPath && openSessions[leftPath]) pathsToUpdate.push(leftPath);
        if (isSplit && rightPath && rightPath !== leftPath && openSessions[rightPath]) pathsToUpdate.push(rightPath);
        
        for (const path of pathsToUpdate) {
            const session = openSessions[path];
            const content = session.getValue();
            promises.push(doSave(path, content, session));
        }
        
        Promise.all(promises).then(() => {
            toast("Archivos guardados correctamente");
        });
    }

    async function doSave(path, content, session) {
        try {
            const r = await fetch('?action=save', { method: 'POST', body: JSON.stringify({ file: path, content: content }) });
            if(!r.ok) throw new Error("Fallo al guardar " + path);
            session.initialContent = content;
            const tab = document.querySelector(`.tab[data-path="${path}"]`);
            if(tab) tab.classList.remove('dirty');

        } catch(e) { toast(e.message, 'error'); }
    }

    function openSplitView() {
        if(isSplit) return;
        document.getElementById('wrapper-right').style.display = 'flex';
        document.getElementById('btn-close-split').style.display = 'flex';
        editorRight.resize();
        isSplit = true;
    }

    function closeSplit() {
        document.getElementById('wrapper-right').style.display = 'none';
        document.getElementById('btn-close-split').style.display = 'none';
        editorLeft.resize();
        isSplit = false;
        rightPath = null;
        activeEditorObj = editorLeft;
        setFocus('left');
    }

    function scanDeps() {
        if (!leftPath || !openSessions[leftPath]) return;
        const txt = openSessions[leftPath].getValue();
        const container = document.getElementById('dep-list');
        const bar = document.getElementById('dep-bar');
        const found = new Set();
        const regexes = [ /(?:include|require|include_once|require_once)\s*\(?\s*['"]([^'"]+)['"]/g, /(?:href|src|action)=['"]([^'"]+)['"]/g, /url\(['"]?([^'")]+)['"]?\)/g ];

        regexes.forEach(r => {
            let m;
            while ((m = r.exec(txt)) !== null) {
                if (!m[1].match(/^(http|https|ftp|mailto|#|data:)/) && !m[1].includes(leftPath)) found.add(m[1]);
            }
        });

        container.innerHTML = '';
        if (found.size === 0) { bar.style.display = 'none'; return; }
        bar.style.display = 'flex';
        found.forEach(f => {
            const btn = document.createElement('a'); btn.className = 'dep-link';
            btn.innerHTML = `<i class="material-icons">link</i> ${f}`;
            btn.onclick = () => { const resolved = resolvePath(leftPath, f); loadFile(resolved, 'right'); };
            container.appendChild(btn);
        });
    }

    function buildSnippetsMenu() {
        const menu = document.getElementById('snip-menu');
        for (const [lang, list] of Object.entries(snippets)) {
            const head = document.createElement('div'); head.className = 'dd-header'; head.textContent = lang; menu.appendChild(head);
            list.forEach(s => {
                const item = document.createElement('div'); item.className = 'dd-item';
                item.innerHTML = `<i class="material-icons" style="font-size:14px; color:#dcb67a">code</i> ${s.n} <small>TAB</small>`;
                item.onclick = () => insertSnip(s.c);
                menu.appendChild(item);
            });
        }
    }

    function insertSnip(code) {
        if (!activeEditorObj) activeEditorObj = editorLeft;
        ace.require("ace/snippets").snippetManager.insertSnippet(activeEditorObj, code);
        activeEditorObj.focus();
        closeDropdowns();
    }

    function createTabUI(path) {
        if (document.querySelector(`.tab[data-path="${path}"]`)) return;
        const t = document.createElement('div'); t.className = 'tab'; t.dataset.path = path;
        t.innerHTML = `<span>${path.split('/').pop()}</span> <i class="material-icons tab-close" onclick="closeTab('${path}', event)">close</i>`;
        t.onclick = (e) => { if (!e.target.classList.contains('tab-close')) loadFile(path, 'left'); };
        document.getElementById('tab-bar').appendChild(t);
    }
    function updateTabsUI(path) { document.querySelectorAll('.tab').forEach(t => t.classList.toggle('active', t.dataset.path === path)); }

    function closeTab(path, e) {
        if(e) e.stopPropagation();
        const tab = document.querySelector(`.tab[data-path="${path}"]`);
        if(tab && tab.classList.contains('dirty') && !confirm("¿Cerrar sin guardar?")) return;
        delete openSessions[path];
        if(tab) tab.remove();
        if(leftPath === path) {
            leftPath = null; editorLeft.setSession(ace.createEditSession("","text"));
            const keys = Object.keys(openSessions);
            if(keys.length > 0) loadFile(keys[keys.length-1], 'left'); else document.getElementById('dep-bar').style.display='none';
        }
        if(rightPath === path) closeSplit();
    }

    async function initTree() { const c = document.getElementById('file-tree'); c.innerHTML = ''; loadTreeLevel('', c); }
    async function loadTreeLevel(path, container) {
        try {
            const r = await fetch(`?action=list&path=${path}`);
            const d = await r.json();
            d.items.forEach(item => {
                const node = document.createElement('div'); node.className = 'tree-node'; node.dataset.path = item.path; node.dataset.type = item.type;
                const content = document.createElement('div'); content.className = `tree-content ${item.type}`;
                content.innerHTML = `${item.type==='folder' ? '<i class="material-icons tree-arrow">play_arrow</i>' : '<span style="width:14px;display:inline-block"></span>'} <i class="material-icons">${item.type==='folder'?'folder':'description'}</i> ${item.name}`;
                content.onclick = (e) => { e.stopPropagation(); if(item.type==='file') loadFile(item.path, 'left'); else toggleFolder(node, item.path); };
                content.oncontextmenu = (e) => showCtx(e, item.path, item.type);
                node.appendChild(content);
                if(item.type==='folder') { const children = document.createElement('div'); children.className = 'tree-children'; node.appendChild(children); }
                container.appendChild(node);
            });
        } catch(e){ console.error(e); }
    }

    function toggleFolder(node, path) {
        const kids = node.querySelector('.tree-children');
        node.classList.toggle('expanded');
        if (node.classList.contains('expanded')) { kids.style.display = 'block'; if (kids.innerHTML === '') loadTreeLevel(path, kids); } else { kids.style.display = 'none'; }
    }

    function setFocus(side) {
        document.querySelectorAll('.editor-wrapper').forEach(e => e.classList.remove('focused'));
        document.getElementById(`wrapper-${side}`).classList.add('focused');
        activeEditorObj = (side === 'left') ? editorLeft : editorRight;
    }

    function resolvePath(base, rel) {
        if(rel.startsWith('/')) return rel.substring(1);
        let stack = base.split('/'); stack.pop();
        let parts = rel.split('/');
        for (let i=0; i<parts.length; i++) { if (parts[i] == '.') continue; if (parts[i] == '..') stack.pop(); else stack.push(parts[i]); }
        return stack.join('/');
    }

    // === HERRAMIENTAS DE EDICIÓN ===
    function formatActive() { if(activeEditorObj) ace.require("ace/ext/beautify").beautify(activeEditorObj.getSession()); }
    function triggerUndo() { if(activeEditorObj) activeEditorObj.undo(); }
    function triggerRedo() { if(activeEditorObj) activeEditorObj.redo(); }
    
    // -- BUSQUEDA Y REEMPLAZO --
    function triggerSearch() { if(activeEditorObj) activeEditorObj.execCommand('find'); }
    function triggerReplace() { if(activeEditorObj) activeEditorObj.execCommand('replace'); }

    // -- COPIAR Y PEGAR SEGURO --
    async function copySelected() { 
        if (!activeEditorObj) return;
        const selectedText = activeEditorObj.getCopyText();
        if (!selectedText) { toast("Nada seleccionado", "warning"); return; }
        
        if (!navigator.clipboard) { try { activeEditorObj.execCommand('copy'); } catch(e){} return; }

        try { await navigator.clipboard.writeText(selectedText); toast("Copiado al sistema"); activeEditorObj.focus(); }
        catch (err) { try { activeEditorObj.execCommand('copy'); toast("Copiado (Interno)"); } catch (e) { toast("Usa Ctrl+C", "error"); } }
    }

    async function pasteContent() { 
        if (!activeEditorObj) return;
        if (!navigator.clipboard) { toast("Pegar requiere HTTPS", "error"); return; }

        try {
            const text = await navigator.clipboard.readText();
            if (typeof text === 'string' && text.length > 0) {
                activeEditorObj.insert(text); activeEditorObj.focus(); toast("Pegado desde sistema");
            } else { toast("Portapapeles vacío", "warning"); }
        } catch (err) {
            if (err.name === 'NotAllowedError') toast("¡Permiso bloqueado! Revisa el icono del candado.", "error");
            else toast("Usa Ctrl+V", "error");
        }
    }

    function selectAll() { 
        if(activeEditorObj) activeEditorObj.execCommand('selectall'); 
    }
    // =================================

    function toggleDropdown(id, e) { e.stopPropagation(); const el = document.getElementById(id); const showing = el.classList.contains('show'); closeDropdowns(); if(!showing) el.classList.add('show'); }
    function closeDropdowns() { document.querySelectorAll('.dropdown-menu').forEach(e => e.classList.remove('show')); document.getElementById('ctx-menu').style.display = 'none'; }
    
    function toast(msg, type='success') { 
        const t = document.getElementById('toast'); 
        let icon = 'check_circle';
        if (type === 'error') icon = 'error';
        if (type === 'warning') icon = 'warning'; 

        t.innerHTML = `<i class="material-icons">${icon}</i> <span>${msg}</span>`; 
        t.className = type; 
        t.classList.add('show'); 
        setTimeout(() => t.classList.remove('show'), 4000); 
    }
    
    function showCtxGlobal(e) { if(e.target.id==='file-tree') showCtx(e, '', 'folder'); }
    function showCtx(e, path, type) { e.preventDefault(); e.stopPropagation(); ctxTarget = {path, type}; const m = document.getElementById('ctx-menu'); m.style.display = 'block'; m.style.left = e.pageX + 'px'; m.style.top = e.pageY + 'px'; }

    async function fileAction(act) {
        closeDropdowns();
        let path = ctxTarget ? ctxTarget.path : '';
        let base = (path && ctxTarget.type==='folder') ? path : (path.includes('/') ? path.substring(0, path.lastIndexOf('/')) : '');
        if(base && !base.endsWith('/')) base += '/';
        try {
            if (act === 'newFile' || act === 'newFolder') { const name = prompt(act==='newFile' ? "Nombre Archivo:" : "Nombre Carpeta:"); if(!name) return; await apiCall('create', {path: base + name, type: act==='newFolder'?'folder':'file'}); }
            else if (act === 'delete') { if(!confirm("¿Eliminar " + path + "?")) return; await apiCall('delete', {path}); if(leftPath === path) closeTab(path); if(rightPath === path) closeSplit(); }
            else if (act === 'rename') { const newName = prompt("Nuevo nombre:", path.split('/').pop()); if(!newName) return; const newPath = (path.includes('/') ? path.substring(0, path.lastIndexOf('/')+1) : '') + newName; await apiCall('rename', {old: path, new: newPath}); }
            else if (act === 'copy') { clipboard = path; toast("Ruta copiada"); return; }
            else if (act === 'paste') { if(!clipboard) return; await apiCall('copy', {src: clipboard, dest: base || ''}); }
            initTree();
        } catch(e) { toast(e.message, 'error'); }
    }
    async function apiCall(act, data) { const r = await fetch(`?action=${act}`, {method:'POST', body:JSON.stringify(data)}); const j = await r.json(); if(!r.ok || j.status !== 'success') throw new Error(j.error || "Error API"); return j; }
    async function loadInitialState() { if(sessionState && sessionState.forcedOpenPath) await loadFile(sessionState.forcedOpenPath, 'left'); }
</script>
</body>
</html>