<?php
/**
 * -------------------------------------------------------------------
 * Ultimate PHP File Manager v16.0 (Zoom Lock & App-Like Feel)
 * -------------------------------------------------------------------
 * Features:
 * 1. ZOOM LOCKED: Prevents Double-Tap & Pinch Zoom on Mobile/Tablet
 * 2. Mobile Optimized: "Select All" button & Responsive Layout
 * 3. Save & Close / Close buttons
 * 4. All Pro Features: Undo Fix, Server Sync, History, Timezone
 * -------------------------------------------------------------------
 */

// --- 1. CONFIGURATION ---
date_default_timezone_set('Asia/Dhaka'); // BD Time
$auth_password = "123@#TAmi";
$root_dir = __DIR__;
$history_dir = $root_dir . '/.fm_history';
$config_file = $root_dir . '/.fm_config.json';

if (!file_exists($history_dir)) { mkdir($history_dir, 0755, true); }

session_start();

// --- 2. AJAX HANDLER ---
if (isset($_POST['ajax_action']) && isset($_SESSION['fm_logged_in'])) {
    $file_path = $_POST['file_path'];
    $file_hash = md5($file_path);
    $history_file = $history_dir . '/' . $file_hash . '.json';
    
    if (strpos(realpath($file_path), realpath($root_dir)) !== 0) { echo json_encode(['status'=>'error']); exit; }

    $history_data = file_exists($history_file) ? json_decode(file_get_contents($history_file), true) : ['draft'=>'', 'versions'=>[]];

    if ($_POST['ajax_action'] === 'autosave') {
        $history_data['draft'] = $_POST['content'];
        $history_data['last_updated'] = date("d M, h:i A");
        file_put_contents($history_file, json_encode($history_data));
        echo json_encode(['status'=>'success', 'msg'=>'Draft Synced']);
    }

    if ($_POST['ajax_action'] === 'save_commit') {
        if (file_put_contents($file_path, $_POST['content']) !== false) {
            // নতুন ভার্সনে কন্টেন্ট এবং লেবেল ডিফল্ট রাখা হচ্ছে
            $new_version = [
                'time' => date("d M, h:i:s A"), 
                'content' => $_POST['content'],
                'starred' => false,
                'label' => ''
            ];
            array_unshift($history_data['versions'], $new_version);
            if(count($history_data['versions']) > 30) array_pop($history_data['versions']); // ৩০টি ভার্সন পর্যন্ত রাখা যাবে
            $history_data['draft'] = ''; 
            file_put_contents($history_file, json_encode($history_data, JSON_UNESCAPED_UNICODE));
            echo json_encode(['status'=>'success', 'msg'=>'Saved Successfully', 'versions'=>$history_data['versions']]);
        } else {
            echo json_encode(['status'=>'error', 'msg'=>'Write Failed']);
        }
    }

    if ($_POST['ajax_action'] === 'clear_history') {
        if(file_exists($history_file)) {
            $h_data = json_decode(file_get_contents($history_file), true);
            // নিশ্চিত করা হচ্ছে যে কন্টেন্টসহ পুরো ডাটা কপি হচ্ছে
            $kept_versions = [];
            if(!empty($h_data['versions'])){
                foreach($h_data['versions'] as $v) {
                    if(isset($v['starred']) && $v['starred'] === true) {
                        $kept_versions[] = $v; // পুরো অবজেক্ট (কন্টেন্টসহ) রাখা হচ্ছে
                    }
                }
            }
            $h_data['versions'] = $kept_versions;
            $h_data['draft'] = ''; 
            // ডাটা সেভ করার সময় JSON_PRETTY_PRINT যোগ করা হয়েছে যাতে ফাইল নষ্ট না হয়
            file_put_contents($history_file, json_encode($h_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
            echo json_encode(['status'=>'success', 'versions' => $h_data['versions']]);
        } else {
            echo json_encode(['status'=>'success', 'versions' => []]);
        }
    }

    if ($_POST['ajax_action'] === 'toggle_star') {
        $idx = (int)$_POST['index'];
        if(isset($history_data['versions'][$idx])) {
            $history_data['versions'][$idx]['starred'] = !($history_data['versions'][$idx]['starred'] ?? false);
            file_put_contents($history_file, json_encode($history_data, JSON_UNESCAPED_UNICODE));
            echo json_encode(['status'=>'success', 'versions' => $history_data['versions']]);
        } else { echo json_encode(['status'=>'error']); }
    }

    if ($_POST['ajax_action'] === 'rename_version') {
        $idx = (int)$_POST['index'];
        $history_data['versions'][$idx]['label'] = $_POST['new_name'];
        file_put_contents($history_file, json_encode($history_data, JSON_UNESCAPED_UNICODE));
        echo json_encode(['status'=>'success', 'versions' => $history_data['versions']]);
    }
    exit;
}

// --- AUTH CHECK ---
if (!isset($_SESSION['fm_logged_in'])) {
    if (isset($_POST['login_pass']) && $_POST['login_pass'] === $auth_password) {
        $_SESSION['fm_logged_in'] = true;
    } else {
        $error = isset($_POST['login_pass']) ? "Access Denied" : "";
        ?>
        <!DOCTYPE html><html lang="en"><head>
            <meta charset="UTF-8">
            <!-- ZOOM LOCK META TAG -->
            <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
            <title>Login</title>
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
            <style>
                body{background:#000;height:100vh;display:flex;align-items:center;justify-content:center;font-family:'Segoe UI',monospace; touch-action: manipulation;}
                .login-card{width:100%;max-width:380px;background:#111;padding:40px;border-radius:12px;border:1px solid #333;box-shadow:0 0 40px rgba(100,0,255,0.1);margin:20px}
                .form-control{background:#222;border:1px solid #444;color:#fff;padding:12px}.form-control:focus{background:#222;color:#fff;border-color:#0d6efd;box-shadow:none}
                .btn-primary{padding:12px;background:#0d6efd;color:#fff;border:none;font-weight:700;letter-spacing:1px;width:100%}
            </style>
        </head><body><div class="login-card text-center"><h3 class="mb-4 text-white fw-bold">SYSTEM v16</h3><?php if($error) echo "<div class='text-danger mb-3 small'>$error</div>"; ?><form method="post"><input type="password" name="login_pass" class="form-control mb-3" placeholder="Passkey" required><button class="btn btn-primary rounded-1">ENTER</button></form></div></body></html>
        <?php exit;
    }
}
if (isset($_GET['logout'])) { session_destroy(); header("Location: ?"); exit; }

// --- 3. ACTIONS ---
$settings = file_exists($config_file) ? json_decode(file_get_contents($config_file), true) : ['pinned'=>[], 'locked'=>[]];
function saveSettings() { global $config_file, $settings; file_put_contents($config_file, json_encode($settings)); }
function formatSize($bytes) { if ($bytes>=1073741824) return number_format($bytes/1073741824,2).' GB'; if ($bytes>=1048576) return number_format($bytes/1048576,2).' MB'; if ($bytes>=1024) return number_format($bytes/1024,2).' KB'; return $bytes.' B'; }
function countItems($dir) { try{ $fi=new FilesystemIterator($dir,FilesystemIterator::SKIP_DOTS); return iterator_count($fi).' items'; }catch(Exception $e){return '';} }
function getIcon($file) { if(is_dir($file)) return 'fas fa-folder text-warning'; $ext=strtolower(pathinfo($file,PATHINFO_EXTENSION)); $icons=['php'=>'fab fa-php text-primary','html'=>'fab fa-html5 text-danger','css'=>'fab fa-css3 text-info','js'=>'fab fa-js text-warning','png'=>'fas fa-image text-success','jpg'=>'fas fa-image text-success','json'=>'fas fa-code text-warning','txt'=>'fas fa-file-alt text-secondary']; return $icons[$ext]??'fas fa-file text-secondary'; }

$current_dir = isset($_GET['dir']) ? realpath($root_dir.'/'.$_GET['dir']) : $root_dir;
if (!$current_dir || strpos($current_dir, $root_dir) !== 0) $current_dir = $root_dir;
$rel_path = trim(str_replace($root_dir, '', $current_dir), '/');
$msg = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && !isset($_POST['ajax_action'])) {
    if (isset($_POST['bulk_delete']) && isset($_POST['selected_items'])) {
        $count = 0;
        foreach($_POST['selected_items'] as $item) {
            $rel = trim($rel_path . '/' . $item, '/');
            if(in_array($rel, $settings['locked'])) continue; 
            $target = $current_dir . '/' . $item;
            if (file_exists($target)) {
                if(is_dir($target)){ $i=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($target,RecursiveDirectoryIterator::SKIP_DOTS),RecursiveIteratorIterator::CHILD_FIRST); foreach($i as $f) ($f->isDir()?'rmdir':'unlink')($f->getRealPath()); rmdir($target); } else { unlink($target); }
                $count++;
            }
        }
        $msg = "$count items deleted successfully!";
    }
    if (isset($_POST['toggle_pin'])) { $rel=str_replace($root_dir.'/','',$_POST['target_path']); if(in_array($rel,$settings['pinned'])) $settings['pinned']=array_diff($settings['pinned'],[$rel]); else $settings['pinned'][]=$rel; saveSettings(); }
    if (isset($_POST['toggle_lock'])) { $rel=str_replace($root_dir.'/','',$_POST['target_path']); if(in_array($rel,$settings['locked'])) $settings['locked']=array_diff($settings['locked'],[$rel]); else $settings['locked'][]=$rel; saveSettings(); }
    if (isset($_POST['create_name'])) { $p=$current_dir.'/'.$_POST['create_name']; if(!file_exists($p)){ ($_POST['create_type']=='dir')?mkdir($p):file_put_contents($p,''); $msg="Created!"; } }
    if (isset($_FILES['upload_file'])) { move_uploaded_file($_FILES['upload_file']['tmp_name'], $current_dir.'/'.$_FILES['upload_file']['name']); $msg="Uploaded!"; }
    if (isset($_POST['rename_new'])) { rename($current_dir.'/'.$_POST['rename_old'], $current_dir.'/'.$_POST['rename_new']); $msg="Renamed!"; }
}

if (isset($_GET['delete'])) { $t=$current_dir.'/'.$_GET['delete']; if(is_dir($t)){ $i=new RecursiveIteratorIterator(new RecursiveDirectoryIterator($t,RecursiveDirectoryIterator::SKIP_DOTS),RecursiveIteratorIterator::CHILD_FIRST); foreach($i as $f) ($f->isDir()?'rmdir':'unlink')($f->getRealPath()); rmdir($t); } else unlink($t); header("Location: ?dir=".urlencode($rel_path)); exit; }
if (isset($_GET['download'])) { $f=$current_dir.'/'.$_GET['download']; if(file_exists($f)){ header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($f).'"'); readfile($f); exit; } }

$items = scandir($current_dir); $list = [];
foreach ($items as $item) {
    if ($item=='.'||$item=='..'||$item=='.fm_config.json'||$item=='.fm_history') continue;
    $path=$current_dir.'/'.$item; $rel=trim(str_replace($root_dir,'',$path),'/');
    $list[]=['name'=>$item,'path'=>$path,'is_dir'=>is_dir($path),'size'=>is_dir($path)?countItems($path):formatSize(filesize($path)),'mod'=>date("d M, h:i A",filemtime($path)),'pinned'=>in_array($rel,$settings['pinned']),'locked'=>in_array($rel,$settings['locked'])];
}
usort($list, function($a,$b){ if($a['pinned']!=$b['pinned']) return $b['pinned']-$a['pinned']; return $b['is_dir']-$a['is_dir']; });

$editing_file = isset($_GET['edit']) ? $current_dir.'/'.$_GET['edit'] : null;
$editor_content = ''; $server_draft = ''; $history_versions = [];
if ($editing_file) {
    $editor_content = file_get_contents($editing_file);
    $h_file = $history_dir . '/' . md5($editing_file) . '.json';
    if(file_exists($h_file)) {
        $h_data = json_decode(file_get_contents($h_file), true);
        $server_draft = $h_data['draft'] ?? '';
        $history_versions = $h_data['versions'] ?? [];
    }
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- !!! ZOOM LOCK & RESPONSIVE META !!! -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>📁 FILE MANAGER</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.23.4/ace.min.js"></script>
    <style>
        :root { --bg:#121212; --card:#1e1e1e; --text:#e0e0e0; --border:#333; --hover:#2d2d2d; --accent:#bb86fc; --save-btn:#8a4baf; --save-text:#fff; }
        body.light-mode { --bg:#f8f9fa; --card:#ffffff; --text:#212529; --border:#dee2e6; --hover:#e9ecef; --accent:#0d6efd; --save-btn:#0d6efd; --save-text:#fff; }
        
        /* APP FEEL CSS (No Zoom, No Bounce) */
        html, body { 
            height: 100%; 
            overscroll-behavior: none; /* Prevents bounce */
            touch-action: pan-x pan-y; /* Disable zoom gestures, allow scroll */
            -webkit-text-size-adjust: 100%;
        }
        body { background: var(--bg); color: var(--text); font-family: 'Segoe UI', monospace; font-size: 14px; transition: 0.3s; }
        
        /* Prevent double-tap zoom on buttons */
        button, input, textarea, .file-item, .nav-link, .ctx-item { touch-action: manipulation; }

        .navbar, .card { background: var(--card)!important; border: 1px solid var(--border)!important; color: var(--text); }
        .table { color: var(--text); } .table th { border-bottom: 2px solid var(--border); color: var(--accent); } .table td { border-bottom: 1px solid var(--border); vertical-align: middle; }
        .table-hover tbody tr:hover { background: var(--hover); color: var(--text); }
        .row-pinned { background: rgba(255, 215, 0, 0.1)!important; border-left: 3px solid #ffd700; }
        .row-locked { opacity: 0.5; cursor: not-allowed; }
        .form-control, .form-check-input { background: var(--bg); border: 1px solid #555; color: var(--text); }
        .form-control:focus { background: var(--bg); color: var(--text); border-color: var(--accent); box-shadow: none; }
        #bulkBar { display:none; position:fixed; bottom:20px; left:50%; transform:translateX(-50%); background: var(--accent); color: #000; padding: 10px 30px; border-radius: 30px; font-weight: bold; z-index: 1000; }
        #contextOverlay { display:none; position:fixed; top:0; left:0; width:100%; height:100%; z-index:9998; backdrop-filter: blur(2px); }
        #contextMenu { display:none; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%); width:250px; z-index:9999; background: var(--card); border: 1px solid var(--border); box-shadow: 0 10px 40px rgba(0,0,0,0.5); }
        .ctx-item { padding: 12px 20px; cursor: pointer; border-bottom: 1px solid var(--border); color: var(--text); } .ctx-item:hover { background: var(--accent); color: #000; }
        #editor { flex-grow: 1; border: 1px solid var(--border); font-size: 15px; }
        .fr-panel { background: var(--card); border: 1px solid var(--border); padding: 10px; margin-bottom: 10px; }
        .fr-textarea { width: 100%; background: var(--bg); color: var(--text); border: 1px solid var(--border); font-family: monospace; resize: vertical; }
        .toolbar-btn { background: transparent; border: 1px solid var(--border); color: var(--text); padding: 6px 10px; font-size: 13px; margin: 2px; transition: 0.2s; border-radius: 4px; display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
        .toolbar-btn:hover { background: var(--accent); color: #000; border-color: var(--accent); }
        .btn-save { background: var(--save-btn) !important; color: var(--save-text) !important; border: 1px solid var(--save-btn); font-weight: bold; box-shadow: 0 0 10px rgba(138, 75, 175, 0.4); }
        #versionList { overflow-y: auto; background: var(--bg); border-top: 1px solid var(--border); }
        .ver-item { padding: 8px 10px; border-bottom: 1px solid var(--border); cursor: pointer; display: flex; justify-content: space-between; font-size: 12px; color: var(--text); }
        .star-btn { cursor: pointer; padding: 2px 8px; color: #555; transition: 0.2s; font-size: 14px; }
        .star-btn.active { color: #ffd700; }
        .edit-btn { cursor: pointer; padding: 2px 5px; color: #777; font-size: 11px; transition: 0.2s; }
        .edit-btn:hover { color: #0d6efd; }
        .ver-info { flex-grow: 1; display: flex; flex-direction: column; overflow: hidden; margin-right: 5px; }
        .ver-label { font-weight: bold; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .ver-time { font-size: 10px; opacity: 0.5; }
        
        @media (max-width: 768px) {
            .editor-row { flex-direction: column; }
            .sidebar-col { height: auto !important; max-height: 200px; }
            .editor-col { height: 60vh !important; }
            .col-perm, .col-date, .col-type { display: none; }
            .navbar { padding: 10px !important; }
            .toolbar-scroll { overflow-x: auto; white-space: nowrap; padding-bottom: 5px; -webkit-overflow-scrolling: touch; }
        }
    </style>
</head>
<body>

    <nav class="navbar px-3 py-2 sticky-top">
        <div class="d-flex align-items-center w-100 justify-content-between">
            <div class="d-flex align-items-center">
                <a href="?" class="btn btn-sm btn-outline-secondary me-2"><i class="fas fa-home"></i></a>
                <?php if($rel_path): ?><a href="?dir=<?= urlencode(dirname($rel_path)=='.'?'':dirname($rel_path)) ?>" class="btn btn-sm btn-outline-secondary me-2"><i class="fas fa-arrow-left"></i></a><?php endif; ?>
                <span class="ms-2 font-monospace fw-bold text-truncate" style="max-width: 150px;">/<?= $rel_path ?></span>
            </div>
            <div class="d-flex gap-2">
                <button class="btn btn-sm btn-outline-secondary" onclick="toggleTheme()"><i class="fas fa-moon"></i></button>
                <button class="btn btn-sm btn-success" data-bs-toggle="modal" data-bs-target="#createModal"><i class="fas fa-plus"></i></button>
                <button class="btn btn-sm btn-warning text-dark" data-bs-toggle="modal" data-bs-target="#uploadModal"><i class="fas fa-upload"></i></button>
                <a href="?logout" class="btn btn-sm btn-danger"><i class="fas fa-power-off"></i></a>
            </div>
        </div>
    </nav>

    <div class="container-fluid px-2 px-md-4 py-3">
        <?php if($msg): ?><div class="alert alert-success py-2 rounded-0 border-start border-5 border-success"><?= $msg ?><button class="btn-close float-end" data-bs-dismiss="alert"></button></div><?php endif; ?>

        <?php if($editing_file): ?>
            <!-- EDITOR VIEW -->
            <div class="row g-0 editor-row" style="height: calc(100vh - 80px);">
                <div class="col-md-9 editor-col d-flex flex-column h-100">
                    <div class="card rounded-0 border-end-0 h-100 d-flex flex-column">
                        <div class="card-header d-flex justify-content-between py-2 align-items-center border-bottom bg-dark text-white">
                            <span class="fw-bold text-truncate me-2"><i class="fas fa-code me-2"></i><?= basename($editing_file) ?></span>
                            <div class="d-flex align-items-center gap-2">
                                <span id="saveStatus" class="text-warning fst-italic small d-none d-md-inline">Synced</span>
                                <button class="btn btn-sm btn-success fw-bold px-2" onclick="saveAndClose()"><i class="fas fa-check-circle me-1"></i> SAVE & CLOSE</button>
                                <button class="btn btn-sm btn-secondary fw-bold px-2" onclick="closeEditor()"><i class="fas fa-times me-1"></i> CLOSE</button>
                            </div>
                        </div>
                        
                        <div class="p-2 border-bottom toolbar-scroll" style="background: var(--bg);">
                            <div class="d-flex align-items-center">
                                <button class="toolbar-btn d-md-none text-info" onclick="editorSelectAll()"><i class="fas fa-check-double"></i> Select All</button>
                                <div class="vr bg-secondary mx-2 d-md-none"></div>
                                <button class="toolbar-btn" onclick="toggleFR()"><i class="fas fa-search"></i> Find</button>
                                <div class="vr bg-secondary mx-2"></div>
                                <button class="toolbar-btn" onclick="undo()"><i class="fas fa-undo"></i></button>
                                <button class="toolbar-btn" onclick="redo()"><i class="fas fa-redo"></i></button>
                                <button class="toolbar-btn text-warning" onclick="resetOriginal()">Reset</button>
                                <div class="vr bg-secondary mx-2"></div>
                                <button class="toolbar-btn btn-save ms-auto" onclick="commitSave()"><i class="fas fa-save me-1"></i> SAVE</button>
                            </div>
                        </div>

                        <div class="flex-grow-1 position-relative" style="overflow: hidden;">
                             <div id="frPanel" class="fr-panel m-2 position-absolute top-0 start-0 end-0 shadow-lg" style="display:none; z-index: 10;">
                                <div class="row g-2">
                                    <div class="col-6"><textarea id="findText" class="fr-textarea" rows="2" placeholder="Find..."></textarea></div>
                                    <div class="col-6"><textarea id="repText" class="fr-textarea" rows="2" placeholder="Replace..."></textarea></div>
                                    <div class="col-12 d-flex gap-1">
                                        <button class="btn btn-sm btn-primary flex-fill" onclick="editorFindNext()">Next</button>
                                        <button class="btn btn-sm btn-warning text-dark flex-fill" onclick="editorReplace()">Rep</button>
                                        <button class="btn btn-sm btn-danger flex-fill" onclick="editorReplaceAll()">All</button>
                                    </div>
                                </div>
                            </div>
                            <div id="editor" style="width:100%; height:100%; border:none;"></div>
                        </div>
                    </div>
                </div>
                
                <div class="col-md-3 sidebar-col d-flex flex-column h-100">
                    <div class="card rounded-0 h-100 border-start-0 border-top-0">
                        <div class="card-header fw-bold border-bottom bg-secondary text-white small">HISTORY (SERVER)</div>
                        <div class="card-body p-0 d-flex flex-column bg-dark">
                            <div id="versionList" class="flex-grow-1" style="background: FILE(--card);"></div>
                            <div class="p-2 border-top bg-black">
                                <div class="d-grid"><button class="btn btn-sm btn-outline-danger" onclick="clearServerHistory()">Clear History</button></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        <?php else: ?>
            <div class="position-relative mb-3">
                <i class="fas fa-search" style="position:absolute; left:15px; top:12px; color:gray"></i>
                <input type="text" id="searchInput" class="form-control" style="padding-left:40px" placeholder="Search files..." onkeyup="filterFiles()">
            </div>
            <form method="post" id="bulkForm">
                <input type="hidden" name="bulk_delete" value="1">
                <div class="card rounded-0">
                    <div class="table-responsive">
                        <table class="table table-hover mb-0">
                            <thead><tr><th width="40"><input type="checkbox" class="form-check-input" id="selectAll" onclick="toggleAll()"></th><th>NAME</th><th>SIZE</th><th class="d-none d-md-table-cell">MODIFIED</th></tr></thead>
                            <tbody>
                                <?php if(empty($list)): ?><tr><td colspan="4" class="text-center py-5 opacity-50">EMPTY FOLDER</td></tr><?php endif; ?>
                                <?php foreach($list as $f): ?>
                                    <tr class="file-item <?= $f['pinned']?'row-pinned':'' ?> <?= $f['locked']?'row-locked':'' ?>" data-name="<?= strtolower($f['name']) ?>" onclick="handleItemClick('<?= $f['is_dir']?'dir':'file' ?>','<?= htmlspecialchars($f['name']) ?>', <?= $f['locked']?1:0 ?>, event)" oncontextmenu="showContext(event, '<?= $f['name'] ?>', <?= $f['locked']?1:0 ?>, <?= $f['pinned']?1:0 ?>, '<?= $f['path'] ?>', '<?= $f['is_dir']?'dir':'file' ?>')">
                                        <td class="text-center"><input type="checkbox" name="selected_items[]" value="<?= htmlspecialchars($f['name']) ?>" class="form-check-input item-check" onclick="event.stopPropagation(); updateBulk()" <?= $f['locked'] ? 'disabled' : '' ?>></td>
                                        <td>
                                            <span class="me-2"><?= $f['is_dir']?'<i class="fas fa-folder text-warning"></i>':'<i class="'.getIcon($f['path']).'"></i>' ?></span>
                                            <span class="fw-bold"><?= htmlspecialchars($f['name']) ?></span>
                                            <?php if($f['pinned']): ?><i class="fas fa-star text-warning ms-2"></i><?php endif; ?>
                                            <?php if($f['locked']): ?><i class="fas fa-lock ms-2"></i><?php endif; ?>
                                        </td>
                                        <td class="font-monospace small"><?= $f['size'] ?></td>
                                        <td class="d-none d-md-table-cell font-monospace small"><?= $f['mod'] ?></td>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
                <div id="bulkBar"><span id="bulkCount">0</span> SELECTED <button type="button" class="btn btn-sm btn-dark ms-3" onclick="submitBulk()">DELETE</button></div>
            </form>
        <?php endif; ?>
    </div>

    <div id="contextOverlay" onclick="hideContext()"></div>
    <div id="contextMenu">
        <div class="p-3 border-bottom text-center fw-bold bg-secondary text-white text-truncate" id="ctxTitle">OPTIONS</div>
        <div class="ctx-item" onclick="execCtx('open')">OPEN</div>
        <div class="ctx-item" onclick="toggleState('pin')"><span id="lblPin">PIN</span></div>
        <div class="ctx-item" onclick="toggleState('lock')"><span id="lblLock">LOCK</span></div>
        <div class="ctx-item" onclick="execCtx('rename')">RENAME</div>
        <div class="ctx-item" onclick="execCtx('download')">DOWNLOAD</div>
        <div class="ctx-item text-danger fw-bold" onclick="execCtx('delete')">DELETE</div>
    </div>
    
    <form id="stateForm" method="post"><input type="hidden" name="target_path" id="statePath"><input type="hidden" name="toggle_pin" id="doPin" disabled><input type="hidden" name="toggle_lock" id="doLock" disabled></form>
    <?php $modals=[['id'=>'createModal','t'=>'CREATE','b'=>'<input name="create_name" class="form-control mb-2" placeholder="Name" required><select name="create_type" class="form-select"><option value="file">File</option><option value="dir">Folder</option></select>','btn'=>'CREATE','c'=>'primary'],['id'=>'uploadModal','t'=>'UPLOAD','b'=>'<input type="file" name="upload_file" class="form-control" required>','btn'=>'UPLOAD','c'=>'warning'],['id'=>'renameModal','t'=>'RENAME','b'=>'<input type="hidden" name="rename_old" id="rnOld"><input name="rename_new" id="rnNew" class="form-control" required>','btn'=>'SAVE','c'=>'info']]; foreach($modals as $m) echo "<div class='modal fade' id='{$m['id']}'><div class='modal-dialog modal-dialog-centered modal-sm'><div class='modal-content rounded-0' style='background:var(--card);color:var(--text);border:1px solid var(--border);'><form method='post' enctype='multipart/form-data'><div class='modal-header border-bottom-0'><h6 class='modal-title fw-bold'>{$m['t']}</h6><button type='button' class='btn-close ".($m['c']=='dark'?'btn-close-white':'')."' data-bs-dismiss='modal'></button></div><div class='modal-body'>{$m['b']}</div><div class='modal-footer border-top-0 p-3'><button class='btn btn-{$m['c']} w-100 fw-bold'>{$m['btn']}</button></div></form></div></div></div>"; ?>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        function toggleTheme() { document.body.classList.toggle('light-mode'); }
        function filterFiles() { let term = document.getElementById('searchInput').value.toLowerCase(); document.querySelectorAll('.file-item').forEach(row => row.style.display = row.getAttribute('data-name').includes(term) ? '' : 'none'); }
        function toggleAll() { const c = document.getElementById('selectAll').checked; document.querySelectorAll('.item-check:not(:disabled)').forEach(k => k.checked = c); updateBulk(); }
        function updateBulk() { const n = document.querySelectorAll('.item-check:checked').length; document.getElementById('bulkBar').style.display = n > 0 ? 'block' : 'none'; document.getElementById('bulkCount').innerText = n; }
        function submitBulk() { if(confirm('Delete selected?')) document.getElementById('bulkForm').submit(); }
        const currDir = '<?= urlencode($rel_path) ?>';
        function handleItemClick(type, name, isLocked, e) { if(e.target.type === 'checkbox' || isLocked) return; const path = encodeURIComponent((currDir ? decodeURIComponent(currDir)+'/':'') + name); window.location.href = type === 'dir' ? '?dir='+path : '?dir='+currDir+'&edit='+name; }
        let ctxData = {}, longPressTimer, isLongPress = false;
        function showContext(e, name, locked, pinned, path, type) { e.preventDefault(); ctxData = {name, locked, pinned, path, type}; document.getElementById('ctxTitle').innerText = name.toUpperCase(); document.getElementById('lblPin').innerText = pinned ? 'UNPIN' : 'PIN'; document.getElementById('lblLock').innerText = locked ? 'UNLOCK' : 'LOCK'; document.getElementById('contextOverlay').style.display = 'block'; document.getElementById('contextMenu').style.display = 'block'; }
        function hideContext() { document.getElementById('contextOverlay').style.display = 'none'; document.getElementById('contextMenu').style.display = 'none'; }
        function execCtx(action) { hideContext(); if(action=='open') handleItemClick(ctxData.type, ctxData.name, ctxData.locked, {target:{}}); if(action=='download') location.href = '?dir='+currDir+'&download='+encodeURIComponent(ctxData.name); if(action=='delete' && confirm('Delete '+ctxData.name+'?')) location.href = '?dir='+currDir+'&delete='+encodeURIComponent(ctxData.name); if(action=='rename') { document.getElementById('rnOld').value = ctxData.name; document.getElementById('rnNew').value = ctxData.name; new bootstrap.Modal(document.getElementById('renameModal')).show(); } }
        function toggleState(action) { document.getElementById('statePath').value = ctxData.path; if(action=='pin') document.getElementById('doPin').disabled = false; if(action=='lock') document.getElementById('doLock').disabled = false; document.getElementById('stateForm').submit(); }

        if(document.getElementById('editor')) {
            var editor = ace.edit("editor");
            editor.setTheme("ace/theme/dracula");
            editor.session.setMode("ace/mode/php");
            editor.setOptions({fontSize: "15px", showPrintMargin: false, wrap: true});
            
            const initialContent = <?= json_encode($editor_content) ?>;
            editor.setValue(initialContent, -1);
            setTimeout(() => { editor.session.getUndoManager().reset(); }, 100);

            const filePath = '<?= isset($editing_file) ? addslashes($editing_file) : '' ?>';
            const serverDraft = <?= json_encode($server_draft) ?>;
            var versions = <?= json_encode($history_versions) ?>;
            let autoSaveTimer;

            if(serverDraft && serverDraft !== initialContent) {
                if(confirm("⚠ Found unsaved draft on server. Load it?")) {
                    editor.setValue(serverDraft, -1);
                    setTimeout(() => { editor.session.getUndoManager().reset(); }, 100);
                }
            }
            renderVersions();

            editor.session.on('change', function() {
                document.getElementById('saveStatus').innerText = "Typing...";
                clearTimeout(autoSaveTimer);
                autoSaveTimer = setTimeout(() => { sendAjax('autosave'); }, 2000);
            });

            function sendAjax(action, callback) {
                document.getElementById('saveStatus').innerText = "Syncing...";
                let fd = new FormData();
                fd.append('ajax_action', action);
                fd.append('file_path', filePath);
                if(action !== 'clear_history') fd.append('content', editor.getValue());
                fetch('', { method: 'POST', body: fd }).then(r => r.json()).then(data => {
                    if(data.status === 'success') {
                        if(action === 'autosave') document.getElementById('saveStatus').innerText = "Draft Saved";
                        if(action === 'save_commit') { 
                            document.getElementById('saveStatus').innerText = "Saved!"; 
                            versions = data.versions; 
                            renderVersions();
                            if(callback) callback(); 
                        }
                        if(action === 'clear_history') { 
    versions = data.versions; // সার্ভার থেকে শুধু স্টার করা ভার্সনগুলো ফিরে আসবে
    renderVersions(); 
    alert("History Cleared! (Starred versions kept)"); 
}
                    }
                });
            }

            function commitSave() { sendAjax('save_commit'); }
            function clearServerHistory() { if(confirm("Clear history?")) sendAjax('clear_history'); }
            function undo() { editor.undo(); }
            function redo() { editor.redo(); }
            function resetOriginal() { if(confirm("Discard changes?")) editor.setValue(initialContent, -1); }
            
            function renderVersions() {
                const list = document.getElementById('versionList');
                list.innerHTML = '';
                if(!versions || versions.length === 0) { list.innerHTML = '<div class="p-3 text-center text-muted small">No versions yet.</div>'; return; }
                versions.forEach((v, i) => {
                    let isStarred = v.starred === true;
                    let label = (v.label && v.label.trim() !== '') ? v.label : `Ver ${versions.length - i}`;
                    let d = document.createElement('div'); d.className = 'ver-item d-flex align-items-center px-2 py-1';
                    d.innerHTML = `
                        <div class="ver-info" onclick="loadVersion(${i})">
                            <span class="ver-label">${label}</span> 
                            <span class="ver-time">${v.time}</span>
                        </div>
                        <i class="fas fa-pen edit-btn" title="Rename" onclick="renameVersion(event, ${i})"></i>
                        <i class="fas fa-star star-btn ${isStarred ? 'active' : ''}" title="Keep safe" onclick="toggleStar(event, ${i})"></i>
                    `;
                    list.appendChild(d);
                });
            }

            // হিস্টোরি থেকে কোড লোড করার ফাংশন (এটি মুছে গিয়েছিল)
            window.loadVersion = function(i) {
                if (versions[i] && versions[i].content !== undefined) {
                    if(confirm("Load this version into editor? (Current changes will be lost)")) {
                        editor.setValue(versions[i].content, -1); // এডিটরে কোড সেট করা
                        editor.session.getUndoManager().reset();
                        document.getElementById('saveStatus').innerText = "Loaded: " + (versions[i].label || "Ver " + (versions.length - i));
                    }
                } else {
                    alert("Error: Version content missing.");
                }
            }

            // রিনেম করার ফাংশন
            window.renameVersion = function(e, i) {
                e.stopPropagation();
                let oldName = versions[i].label || `Ver ${versions.length - i}`;
                let newName = prompt("Enter new name for this version:", oldName);
                if (newName !== null && newName.trim() !== "") {
                    let fd = new FormData();
                    fd.append('ajax_action', 'rename_version');
                    fd.append('file_path', filePath);
                    fd.append('index', i);
                    fd.append('new_name', newName);
                    fetch('', { method: 'POST', body: fd }).then(r => r.json()).then(data => {
                        if(data.status === 'success') {
                            versions = data.versions;
                            renderVersions();
                        }
                    });
                }
            }

            // স্টার টগল করার ফাংশন
            window.toggleStar = function(e, i) {
                e.stopPropagation(); // যাতে ভার্সন লোড না হয়ে যায়
                let fd = new FormData();
                fd.append('ajax_action', 'toggle_star');
                fd.append('file_path', filePath);
                fd.append('index', i);
                fetch('', { method: 'POST', body: fd }).then(r => r.json()).then(data => {
                    if(data.status === 'success') {
                        versions = data.versions; // আপডেট হওয়া ভার্সন লিস্ট সার্ভার থেকে আনবে
                        renderVersions(); // লিস্ট পুনরায় দেখাবে
                    }
                });
            }

            function closeEditor() { if(confirm("Close file?")) window.location.href = "?dir=<?= urlencode($rel_path) ?>"; }
            function saveAndClose() { sendAjax('save_commit', function() { window.location.href = "?dir=<?= urlencode($rel_path) ?>"; }); }
            function editorSelectAll() { editor.selectAll(); editor.focus(); }

            editor.commands.addCommand({name: 'save', bindKey: {win: 'Ctrl-S', mac: 'Command-S'}, exec: function() { commitSave(); }});
            function toggleFR() { const p = document.getElementById('frPanel'); p.style.display = p.style.display === 'none' ? 'block' : 'none'; if(p.style.display==='block') document.getElementById('findText').focus(); }
            function editorFindNext() { editor.find(document.getElementById('findText').value, {regExp:false, wrap:true}); }
            function editorReplace() { editor.replace(document.getElementById('repText').value); }
            function editorReplaceAll() { editor.replaceAll(document.getElementById('repText').value, {needle: document.getElementById('findText').value, regExp:false}); }
        }
    </script>
</body>
</html>