<?php
// --- PERFORMANCE SETTINGS ---
// Erlaubt mehr Speicher für kurzzeitige Spitzen, obwohl der neue Code sehr sparsam ist.
ini_set('memory_limit', '1024M'); 
set_time_limit(0); // Kein Timeout bei riesigen Listen

session_start();
$db = new PDO("sqlite:db.sqlite");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$LOCAL_M3U = "master_playlist.m3u";

// --- HELPER FUNCTIONS ---
function formatBytes($bytes, $precision = 2) { 
    $units = ['B', 'KB', 'MB', 'GB', 'TB']; 
    $bytes = max($bytes, 0); 
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); 
    $pow = min($pow, count($units) - 1); 
    return round($bytes, $precision) . ' ' . $units[$pow]; 
}

// --- ACTIONS ---
if (isset($_GET['action'])) {
    $act = $_GET['action'];
    $u = $_GET['user'] ?? '';
    
    // 1. Einzelner IP Reset
    if ($act == 'reset_ip' && $u) {
        @unlink("/tmp/ips_".$u.".json");
        $_SESSION['msg'] = "IPs für $u zurückgesetzt.";
    }
    // 2. Alle IPs auf einmal zurücksetzen
    if ($act == 'reset_all') {
        array_map('unlink', glob("/tmp/ips_*.json"));
        $_SESSION['msg'] = "ALLE Verbindungen im System wurden getrennt.";
    }
    // 3. User Löschen
    if ($act == 'delete' && $u) {
        $stmt = $db->prepare("DELETE FROM users WHERE username=?");
        $stmt->execute([$u]);
        @unlink("/tmp/ips_".$u.".json");
        @unlink("/tmp/logs_".$u.".json");
        $_SESSION['msg'] = "User $u gelöscht.";
    }
    // 4. User Sperren/Entsperren
    if ($act == 'toggle_ban' && $u) {
        $stmt = $db->prepare("UPDATE users SET active = NOT active WHERE username=?");
        $stmt->execute([$u]);
    }
    // 5. Playlist Import (Fallback, falls nicht via wget gemacht)
    if ($act == 'import' && isset($_POST['url'])) {
        $data = @file_get_contents($_POST['url']);
        if($data) {
            file_put_contents($LOCAL_M3U, $data);
            $_SESSION['msg'] = "Playlist Update erfolgreich (" . formatBytes(strlen($data)) . ")";
        } else {
            $_SESSION['err'] = "Download fehlgeschlagen.";
        }
    }
    // 6. User Speichern (Create/Edit)
    if ($act == 'save_user' && isset($_POST['u'])) {
        // Wenn "Alle auswählen" aktiv war oder viele Kategorien, Array zusammenfügen
        $cats = isset($_POST['cats']) ? implode(",", $_POST['cats']) : "*";
        $active = isset($_POST['banned']) ? 0 : 1;
        
        $check = $db->prepare("SELECT username FROM users WHERE username=?");
        $check->execute([$_POST['u']]);
        
        // Prüfen ob neuer User und Name schon vergeben
        if($check->fetch() && $_POST['is_new'] == '1') {
            $_SESSION['err'] = "Username existiert bereits!";
        } else {
            $stmt = $db->prepare("REPLACE INTO users (username, password, expires, max_ips, categories, notes, active) VALUES (?,?,?,?,?,?,?)");
            $stmt->execute([
                $_POST['u'], $_POST['p'], 
                time() + ($_POST['h']*3600), 
                $_POST['i'], $cats, $_POST['notes'], $active
            ]);
            $_SESSION['msg'] = "User gespeichert.";
        }
    }
    header("Location: admin.php"); exit;
}

// --- DATA LOADING (OPTIMIERT) ---
$users = $db->query("SELECT * FROM users ORDER BY expires DESC")->fetchAll(PDO::FETCH_ASSOC);

// Kategorien einlesen (RAM-Schonend Zeile für Zeile)
$cats = [];
if(file_exists($LOCAL_M3U)) {
    $handle = fopen($LOCAL_M3U, "r");
    if ($handle) {
        while (($line = fgets($handle)) !== false) {
            // Nur Zeilen mit group-title verarbeiten
            if (strpos($line, 'group-title="') !== false) {
                if(preg_match('/group-title="([^"]+)"/i', $line, $m)) {
                    // Verwende Array-Keys um Duplikate automatisch zu entfernen
                    $cats[trim($m[1])] = true;
                }
            }
        }
        fclose($handle);
    }
    $cats = array_keys($cats);
    // sort($cats); // Deaktiviert für 1:1 Reihenfolge
}

// Gruppierung für das Modal (z.B. nach DE, TR, US anhand von "DE | Sports")
$groupedCats = [];
foreach($cats as $c) {
    // Trenne am ersten "|"
    $parts = explode('|', $c);
    if(count($parts) > 1) {
        // Alles vor dem | ist der Prefix (Land)
        $prefix = trim($parts[0]);
    } else {
        // Kein | gefunden -> "Andere"
        $prefix = "Andere";
    }
    $groupedCats[$prefix][] = $c;
}
// Sortiere die Gruppen alphabetisch deaktiviert für 1:1 Doganlar -> TRX
// ksort($groupedCats); 

// Stats Calculation
$stats = ['total'=>count($users), 'active'=>0, 'expired'=>0, 'online'=>0];
foreach($users as $usr) {
    if(time() > $usr['expires']) $stats['expired']++; else $stats['active']++;
    if(file_exists("/tmp/ips_".$usr['username'].".json")) $stats['online']++;
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>IPTV PRO PANEL</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <style>
        :root {
            --primary: #4361ee; --secondary: #3f37c9; --success: #4cc9f0; 
            --danger: #f72585; --dark: #1b263b; --light: #f8f9fa; --grey: #e0e1dd;
        }
        * { box-sizing: border-box; outline: none; }
        body { margin: 0; font-family: 'Segoe UI', system-ui, sans-serif; background: #f0f2f5; color: #333; padding-bottom: 60px; }
        
        .header { background: var(--dark); color: white; padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; position: sticky; top: 0; z-index: 100; box-shadow: 0 2px 10px rgba(0,0,0,0.2); }
        .header h1 { margin: 0; font-size: 1.2rem; display: flex; align-items: center; gap: 10px; }
        
        .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 15px; padding: 20px; }
        .stat-card { background: white; padding: 15px; border-radius: 12px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); text-align: center; }
        .stat-val { font-size: 1.8rem; font-weight: bold; color: var(--primary); display: block; }
        .stat-lbl { font-size: 0.85rem; color: #666; text-transform: uppercase; letter-spacing: 1px; }

        .toolbar { padding: 0 20px; display: flex; gap: 10px; flex-wrap: wrap; }
        .search-box { flex: 1; position: relative; }
        .search-box input { width: 100%; padding: 12px 15px 12px 40px; border: 1px solid #ddd; border-radius: 8px; font-size: 1rem; }
        .search-box i { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); color: #999; }
        
        .btn { padding: 10px 20px; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; display: inline-flex; align-items: center; gap: 8px; text-decoration: none; transition: 0.2s; }
        .btn-primary { background: var(--primary); color: white; }
        .btn-success { background: #2ecc71; color: white; }
        .btn-danger { background: var(--danger); color: white; }
        .btn-sm { padding: 5px 10px; font-size: 0.85rem; }

        .table-container { padding: 20px; overflow-x: auto; }
        table { width: 100%; border-collapse: collapse; background: white; border-radius: 12px; overflow: hidden; }
        th { background: #e9ecef; text-align: left; padding: 15px; color: #555; font-size: 0.9rem; }
        td { padding: 15px; border-bottom: 1px solid #eee; vertical-align: middle; }
        
        .status-badge { padding: 4px 8px; border-radius: 20px; font-size: 0.75rem; font-weight: bold; }
        .status-active { background: #d4edda; color: #155724; }
        .status-expired { background: #f8d7da; color: #721c24; }
        .status-banned { background: #333; color: white; }

        @media (max-width: 768px) {
            table, thead, tbody, th, td, tr { display: block; }
            thead { display: none; }
            tr { margin-bottom: 15px; background: white; border-radius: 10px; box-shadow: 0 2px 5px rgba(0,0,0,0.05); padding: 15px; }
            td { padding: 8px 0; border: none; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; align-items: center; }
            td:last-child { border: none; flex-wrap: wrap; gap: 5px; justify-content: flex-start; margin-top: 10px; }
            td::before { content: attr(data-label); font-weight: bold; color: #777; font-size: 0.9rem; }
        }

        .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
        .modal.active { display: flex; }
        .modal-content { background: white; width: 90%; max-width: 500px; padding: 25px; border-radius: 15px; animation: slideUp 0.3s ease; max-height: 90vh; overflow-y: auto; }
        @keyframes slideUp { from { transform: translateY(50px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
        
        .form-group { margin-bottom: 15px; }
        .form-group label { display: block; margin-bottom: 5px; font-weight: 600; color: #555; }
        .form-group input, .form-group textarea { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 6px; }
        
        /* Neue CSS für Kategorien-Liste & Schnell-Optionen */
        .quick-bar { 
            display: flex; gap: 5px; overflow-x: auto; padding: 10px 0; margin-bottom: 10px; 
            white-space: nowrap; -webkit-overflow-scrolling: touch; border-bottom: 1px solid #eee;
        }
        .quick-tag { 
            background: #e2e8f0; color: #334155; padding: 6px 12px; border-radius: 20px; 
            font-size: 0.8rem; font-weight: bold; cursor: pointer; border: 1px solid transparent; 
        }
        .quick-tag:hover { background: #cbd5e1; }
        .quick-tag.special { background: var(--dark); color: white; }

        .cat-scroll { max-height: 250px; overflow-y: auto; border: 1px solid #eee; padding: 10px; border-radius: 6px; background: #fafafa; }
        .cat-group-header { background: #e9ecef; padding: 5px 8px; font-size: 0.8rem; font-weight: bold; margin-top: 5px; margin-bottom: 5px; border-radius: 4px; display: flex; justify-content: space-between; align-items: center; cursor: pointer;}
        .cat-item { display: block; font-size: 0.85rem; padding: 2px 0 2px 10px; }
        
        .toast { position: fixed; bottom: 20px; right: 20px; background: #333; color: white; padding: 12px 20px; border-radius: 8px; z-index: 2000; display: none; animation: fadeIn 0.3s; }
        .toast.error { background: var(--danger); }
        .toast.success { background: #2ecc71; }

        .fab { position: fixed; bottom: 20px; right: 20px; width: 56px; height: 56px; background: var(--primary); border-radius: 50%; color: white; display: flex; align-items: center; justify-content: center; font-size: 24px; box-shadow: 0 4px 10px rgba(67, 97, 238, 0.4); cursor: pointer; z-index: 90; }
    </style>
</head>
<body>

<div class="header">
    <h1><i class="fa-solid fa-tv"></i> IPTV Admin Pro</h1>
    <div style="display:flex; gap:10px; align-items:center;">
        <a href="admin.php?action=reset_all" class="btn btn-danger btn-sm" onclick="return confirm('Alle aktiven IPs löschen?')"><i class="fa-solid fa-bolt"></i> Global Reset</a>
        <div style="font-size:0.8rem; opacity:0.8;" class="d-none d-md-block">
            Disk: <?=formatBytes(disk_free_space("/"))?> Free
        </div>
    </div>
</div>

<div class="stats-grid">
    <div class="stat-card"><span class="stat-val"><?=$stats['total']?></span><span class="stat-lbl">Kunden</span></div>
    <div class="stat-card"><span class="stat-val" style="color:#2ecc71"><?=$stats['active']?></span><span class="stat-lbl">Aktiv</span></div>
    <div class="stat-card"><span class="stat-val" style="color:#e67e22"><?=$stats['online']?></span><span class="stat-lbl">Online</span></div>
    <div class="stat-card"><span class="stat-val" style="color:#f72585"><?=$stats['expired']?></span><span class="stat-lbl">Abgelaufen</span></div>
</div>

<div class="toolbar">
    <div class="search-box">
        <i class="fa-solid fa-search"></i>
        <input type="text" id="searchInput" placeholder="Suche User, Notizen...">
    </div>
    <button onclick="openModal('importModal')" class="btn btn-primary btn-sm"><i class="fa-solid fa-cloud-arrow-down"></i> Playlist</button>
</div>

<div class="table-container">
    <table>
        <thead>
            <tr>
                <th>User / Info</th>
                <th>Status</th>
                <th>Verbindungen</th>
                <th>Notizen</th>
                <th style="text-align:right">Aktionen</th>
            </tr>
        </thead>
        <tbody id="userTableBody">
            <?php foreach($users as $u): 
                $exp = time() > $u['expires'];
                $banned = !$u['active'];
                $ipFile = "/tmp/ips_".$u['username'].".json";
                $ips = file_exists($ipFile) ? json_decode(file_get_contents($ipFile),true) : [];
                $countIP = is_array($ips) ? count($ips) : 0;
                
                $statusClass = 'status-active'; $statusText = 'Aktiv';
                if($exp) { $statusClass = 'status-expired'; $statusText = 'Abgelaufen'; }
                if($banned) { $statusClass = 'status-banned'; $statusText = 'Gesperrt'; }
            ?>
            <tr class="user-row">
                <td data-label="User">
                    <strong><?=htmlspecialchars($u['username'])?></strong><br>
                    <small style="color:#888;">PW: <?=htmlspecialchars($u['password'])?></small>
                </td>
                <td data-label="Status">
                    <span class="status-badge <?=$statusClass?>"><?=$statusText?></span><br>
                    <small><?=date("d.m.y H:i", $u['expires'])?></small>
                </td>
                <td data-label="IPs">
                    <i class="fa-solid fa-network-wired"></i> <b><?=$countIP?></b> / <?=$u['max_ips']?>
                    <?php if($countIP > 0): ?>
                        <a href="admin.php?action=reset_ip&user=<?=urlencode($u['username'])?>" title="IP Reset" style="color:var(--danger); margin-left:8px;"><i class="fa-solid fa-sync"></i></a>
                    <?php endif; ?>
                </td>
                <td data-label="Notiz">
                    <small style="font-style:italic"><?=htmlspecialchars($u['notes'] ?? '-')?></small>
                </td>
                <td data-label="Aktionen" style="text-align:right">
                    <button onclick='editUser(<?=json_encode($u)?>)' class="btn btn-sm" style="background:#eee;"><i class="fa-solid fa-pen"></i></button>
                    <button onclick="copyLink('http://<?=$_SERVER['HTTP_HOST']?>/get.php?username=<?=$u['username']?>&password=<?=$u['password']?>')" class="btn btn-sm btn-success"><i class="fa-solid fa-link"></i></button>
                    <a href="admin.php?action=toggle_ban&user=<?=urlencode($u['username'])?>" class="btn btn-sm" style="background:var(--dark);color:white"><i class="fa-solid fa-ban"></i></a>
                    <a href="admin.php?action=delete&user=<?=urlencode($u['username'])?>" class="btn btn-sm btn-danger" onclick="return confirm('Wirklich löschen?')"><i class="fa-solid fa-trash"></i></a>
                </td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
</div>

<div class="fab" onclick="openModal('userModal')"><i class="fa-solid fa-plus"></i></div>

<div id="userModal" class="modal">
    <div class="modal-content">
        <h3 id="modalTitle">Benutzer-Konfiguration</h3>
        <form method="post" action="admin.php?action=save_user">
            <input type="hidden" name="is_new" id="is_new" value="1">
            <div class="form-group"><label>Username</label><input name="u" id="input_u" required></div>
            <div class="form-group"><label>Passwort</label><input name="p" id="input_p" required></div>
            <div style="display:flex; gap:10px;">
                <div class="form-group" style="flex:1"><label>Laufzeit (h)</label><input type="number" name="h" id="input_h" value="720" required></div>
                <div class="form-group" style="flex:1"><label>Max IPs</label><input type="number" name="i" id="input_i" value="1" required></div>
            </div>
            <div class="form-group"><label>Admin Notiz</label><textarea name="notes" id="input_notes" rows="2"></textarea></div>
            
            <div class="form-group">
                <label>Schnell-Auswahl & Länder</label>
                
                <div class="quick-bar">
                    <div class="quick-tag special" onclick="toggleAll(true)">ALLE AN</div>
                    <div class="quick-tag special" style="background:#64748b" onclick="toggleAll(false)">ALLE AUS</div>
                    <?php foreach(array_keys($groupedCats) as $prefix): ?>
                        <div class="quick-tag" onclick="toggleGroup('<?=htmlspecialchars($prefix)?>', true)">+ <?=htmlspecialchars($prefix)?></div>
                    <?php endforeach; ?>
                </div>

                <input type="text" id="catSearch" placeholder="Filter (z.B. Sky)..." onkeyup="filterCats()" style="width:100%; margin-bottom:5px; padding:6px; font-size:0.9rem;">
                
                <div class="cat-scroll">
                    <?php foreach($groupedCats as $prefix => $list): ?>
                        <div class="cat-group-wrapper">
                            <div class="cat-group-header">
                                <span><?=htmlspecialchars($prefix)?></span>
                                <input type="checkbox" onclick="toggleGroup('<?=htmlspecialchars($prefix)?>', this.checked)">
                            </div>
                            <?php foreach($list as $c): ?>
                                <label class="cat-item" data-name="<?=htmlspecialchars(strtolower($c))?>">
                                    <input type="checkbox" name="cats[]" value="<?=htmlspecialchars($c)?>" class="cat-check" data-group="<?=htmlspecialchars($prefix)?>"> 
                                    <?=htmlspecialchars($c)?>
                                </label>
                            <?php endforeach; ?>
                        </div>
                    <?php endforeach; ?>
                </div>
            </div>
            
            <button class="btn btn-primary" style="width:100%">Speichern</button>
            <button type="button" class="btn" onclick="closeModal('userModal')" style="width:100%; margin-top:10px; background:#ddd;">Abbrechen</button>
        </form>
    </div>
</div>

<div id="importModal" class="modal">
    <div class="modal-content">
        <h3>M3U Playlist Import</h3>
        <form method="post" action="admin.php?action=import">
            <div class="form-group"><label>URL</label><input type="url" name="url" placeholder="http://..." required></div>
            <button class="btn btn-primary" style="width:100%">Download</button>
            <button type="button" class="btn" onclick="closeModal('importModal')" style="width:100%; margin-top:10px; background:#ddd;">Abbrechen</button>
        </form>
    </div>
</div>

<?php if(isset($_SESSION['msg']) || isset($_SESSION['err'])): ?>
<div id="toast" class="toast <?=isset($_SESSION['err'])?'error':'success'?>" style="display:block"><?= $_SESSION['msg'] ?? $_SESSION['err'] ?></div>
<?php unset($_SESSION['msg']); unset($_SESSION['err']); endif; ?>

<script>
function openModal(id) { document.getElementById(id).classList.add('active'); if(id === 'userModal') { document.getElementById('is_new').value = "1"; document.getElementById('input_u').readOnly = false; } }
function closeModal(id) { document.getElementById(id).classList.remove('active'); }

function editUser(u) {
    openModal('userModal');
    document.getElementById('modalTitle').innerText = "Edit: " + u.username;
    document.getElementById('is_new').value = "0";
    document.getElementById('input_u').value = u.username;
    document.getElementById('input_u').readOnly = true;
    document.getElementById('input_p').value = u.password;
    document.getElementById('input_i').value = u.max_ips;
    document.getElementById('input_notes').value = u.notes || "";
    
    // Kategorien Logik
    let userCats = (u.categories || "").split(",");
    // Erstmal alle aus
    document.querySelectorAll('.cat-check').forEach(c => c.checked = false);
    // Dann die richtigen an
    if(userCats.includes("*")) {
        toggleAll(true);
    } else {
        document.querySelectorAll('.cat-check').forEach(c => { 
            if(userCats.includes(c.value)) c.checked = true; 
        });
    }
}

// NEUE QUICK-FUNKTIONEN
function toggleAll(state) {
    document.querySelectorAll('.cat-check').forEach(c => c.checked = state);
    document.querySelectorAll('.cat-group-header input').forEach(c => c.checked = state);
}

function toggleGroup(group, state) {
    document.querySelectorAll(`.cat-check[data-group="${group}"]`).forEach(c => c.checked = state);
    // Setzt auch den Haken im Gruppen-Header falls vorhanden
    let headers = document.querySelectorAll('.cat-group-header');
    headers.forEach(h => {
        if(h.querySelector('span').innerText === group) {
            h.querySelector('input').checked = state;
        }
    });
}

function filterCats() {
    let term = document.getElementById('catSearch').value.toLowerCase();
    document.querySelectorAll('.cat-item').forEach(item => {
        let name = item.getAttribute('data-name');
        if(name.includes(term)) {
            item.style.display = "block";
        } else {
            item.style.display = "none";
        }
    });
    // Verstecke leere Gruppen (Optional, aber schön)
    document.querySelectorAll('.cat-group-wrapper').forEach(grp => {
        let visibleChildren = grp.querySelectorAll('.cat-item[style="display: block;"]').length;
        if(term === "") {
             grp.style.display = "block";
        } else {
             grp.style.display = (visibleChildren > 0) ? "block" : "none";
        }
    });
}

function copyLink(text) { navigator.clipboard.writeText(text).then(() => { showToast("Link kopiert!", "success"); }); }
function showToast(msg, type) { let t = document.createElement("div"); t.className = "toast " + type; t.innerText = msg; t.style.display = "block"; document.body.appendChild(t); setTimeout(() => t.remove(), 3000); }
document.getElementById('searchInput').addEventListener('keyup', function(e) {
    let term = e.target.value.toLowerCase();
    document.querySelectorAll('.user-row').forEach(row => { row.style.display = row.innerText.toLowerCase().includes(term) ? "" : "none"; });
});
setTimeout(() => { if(document.getElementById('toast')) document.getElementById('toast').style.display = 'none'; }, 3000);
</script>
</body>
</html>

