/* -------------------------------------------------------------
   VOIDSPIDER - URL‑Logger für Hubzilla – mit KLICK‑Counter & Ausschluss-Prüfung
   2026 by 𝖜𝖆𝖗𝖟𝖆𝖟𝖊𝖑⛧ - www.voidofxulub.com @license MIT
   Wiki: https://voidofxulub.com/wiki/warzazel
   ------------------------------------------------------------- */

/* ============================================================
   DEBUGGING: Alle Fehler anzeigen
   ============================================================ */
ini_set('display_errors', 1);
error_reporting(E_ALL);

/* ============================================================
   VERBINDUNGSDATEN - WICHTIG - ANPASSEN
   ============================================================ */
$db1Host = 'localhost';
$db1Name = '...';
$db1User = '...';
$db1Pass = '...';   /*$pdoHits - Url_Logger-Datenbank */
$db1Port = 3306;

$db2Host = 'localhost';
$db2Name = '...';            /* $pdoTitles - Hubzilla-Datenbank mit den articles und cards */
$db2User = '...';
$db2Pass = '...';
$db2Port = 3306;

/* ============================================================
   PDO-FACTORY
   ============================================================ */
function createPdo(string $host, string $name, string $user, string $pass, int $port): PDO
{
    $dsn = "mysql:host=$host;port=$port;dbname=$name;charset=utf8mb4";
    $opt = [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ];
    return new PDO($dsn, $user, $pass, $opt);
}

/* ============================================================
   VERBINDUNGEN
   ============================================================ */
try {
    $pdoHits = createPdo($db1Host, $db1Name, $db1User, $db1Pass, $db1Port);
    $pdoItems = createPdo($db2Host, $db2Name, $db2User, $db2Pass, $db2Port);
} catch (PDOException $e) {
    error_log('DB‑Verbindungsfehler: ' . $e->getMessage());
    die('<p style="color:#c00;">❗️ Datenbankverbindung fehlgeschlagen: ' . htmlspecialchars($e->getMessage()) . '</p>');
}

/* ============================================================
   LIMIT AUS URL AUSLESEN
   ============================================================ */
$limit = 10; // Standard-Wert
if (!empty($_GET['limit'])) {
    $limit = (int)$_GET['limit'];
    $limit = max(1, min($limit, 500)); // Min 1, Max 500
}

/* ============================================================
   DELETE-ROUTINE
   ============================================================ */
if (!empty($_GET['del_id'])) {
    $delId = (int)$_GET['del_id'];

    try {
        $delStmt = $pdoHits->prepare('DELETE FROM url_hits WHERE id = ?');
        $delStmt->execute([$delId]);
        
        if ($delStmt->rowCount() > 0) {
            header('Refresh: 5; url=' . strtok($_SERVER['REQUEST_URI'], '?'));
        }
    } catch (PDOException $e) {
        // Optional: Error-Logging statt Ausgabe
        error_log('DELETE-Fehler: ' . $e->getMessage());
    }
}

/* ============================================================
   AUSBLENDEN-BUTTON - IN AUSSCHLUSSLISTE LADEN
   ============================================================ */
if (!empty($_GET['add_id'])) {
    $addId = (int)$_GET['add_id'];

    try {
        // URL aus url_hits auslesen
        $urlStmt = $pdoHits->prepare('SELECT url FROM url_hits WHERE id = ?');
        $urlStmt->execute([$addId]);
        $addUrl = $urlStmt->fetchColumn();

        // Prüfen, ob bereits vorhanden
        $checkStmt = $pdoHits->prepare('SELECT COUNT(*) as cnt FROM ausschluss WHERE exclude = ?');
        $checkStmt->execute([$addId]);
        
        if ($checkStmt->fetchColumn() == 0) {
            // INSERT ausführen
            $insertStmt = $pdoHits->prepare('INSERT INTO ausschluss (exclude, url) VALUES (?, ?)');
            $insertStmt->execute([$addId, $addUrl]);
            
            if ($insertStmt->rowCount() > 0) {
                header('Refresh: 5; url=' . strtok($_SERVER['REQUEST_URI'], '?'));
            }
        }
    } catch (PDOException $e) {
        error_log('INSERT-Fehler: ' . $e->getMessage());
    }
}

/* ============================================================
   DELETE-ROUTINE FÜR AUSSCHLUSSLISTE
   ============================================================ */
if (!empty($_GET['del_exclude_id'])) {
    $delExcludeId = (int)$_GET['del_exclude_id'];

    try {
        $delStmt = $pdoHits->prepare('DELETE FROM ausschluss WHERE id = ?');
        $delStmt->execute([$delExcludeId]);
        
        if ($delStmt->rowCount() > 0) {
            header('Refresh: 3; url=' . strtok($_SERVER['REQUEST_URI'], '?'));
        }
    } catch (PDOException $e) {
        error_log('DELETE EXCLUDE-Fehler: ' . $e->getMessage());
    }
}

/* ============================================================
   AUSSCHLUSS-MUSTER UND IDs AUS DATENBANK
   ============================================================ */
$excludeLike = [];
$excludeIds = [];

try {
    $excludeStmt = $pdoHits->prepare('SELECT exclude FROM ausschluss');
    $excludeStmt->execute();
    $excludeRows = $excludeStmt->fetchAll();
    
    foreach ($excludeRows as $row) {
        if (!empty($row['exclude'])) {
            // Prüfen, ob es eine Zahl ist (ID) oder ein Text-Muster
            if (is_numeric($row['exclude'])) {
                $excludeIds[] = (int)$row['exclude'];
            } else {
                $excludeLike[] = $row['exclude'];
            }
        }
    }
    
    if (empty($excludeLike) && empty($excludeIds)) {
        error_log('Warnung: Keine Ausschlussmuster in der Datenbank gefunden');
    }
} catch (PDOException $e) {
    error_log('Fehler beim Abrufen der Ausschlussmuster: ' . $e->getMessage());
    $excludeLike = [];
    $excludeIds = [];
}

/* ============================================================
   HAUPTABFRAGE
   ============================================================ */
$whereParts = [];
$havingParts = [];
$params     = [];

// URL-Muster ausschließen (WHERE)
foreach ($excludeLike as $pat) {
    $whereParts[] = 'url NOT LIKE ?';
    $params[]     = $pat;
}

$whereSql = $whereParts ? 'WHERE ' . implode(' AND ', $whereParts) : '';

// IDs ausschließen (HAVING)
if (!empty($excludeIds)) {
    $placeholders = rtrim(str_repeat('?,', count($excludeIds)), ',');
    $havingParts[] = "MIN(id) NOT IN ($placeholders)";
    $params = array_merge($params, $excludeIds);
}

$havingSql = $havingParts ? 'HAVING ' . implode(' AND ', $havingParts) : '';

$sql = "
    SELECT
        MIN(id)        AS id,
        url,
        hitcount       AS hits,
        DATE_FORMAT(MAX(ts), '%d.%m.%Y %H:%i:%S') AS last_seen
    FROM url_hits
    $whereSql
    GROUP BY url, hitcount
    $havingSql
    ORDER BY hitcount DESC
    LIMIT ?
";

try {
    $stmt = $pdoHits->prepare($sql);
    $params[] = $limit;
    $stmt->execute($params);
    $rows = $stmt->fetchAll();
} catch (PDOException $e) {
    die('<p style="color:#f44336;">❌ Haupt-Abfrage-Fehler: ' . htmlspecialchars($e->getMessage()) . '</p>');
}

/* ============================================================
   SLUGS EXTRAHIEREN - HAT MICH WAHNSINNIG GEMACHT LOL
   ============================================================ */
$slugs   = [];
$slugMap = [];
$typeMap = [];

foreach ($rows as $row) {
    $id  = (int)$row['id'];
    $url = $row['url'];
    
    // Match: /(articles|cards|wiki)/CHANNEL (2 Ebenen - Übersichtsseiten)
    // ✅ [^/]+ statt warzazel = beliebiger Channel
    if (preg_match('#^/(articles|cards|wiki)/([^/]+)/?$#', $url, $m)) {
        $typeNames = [
            'articles' => 'Artikel',
            'cards'    => 'Karten',
            'wiki'     => 'Wiki'
        ];
        $type = $typeNames[$m[1]];
        $channel = $m[2];  // z.B. "warzazel" oder "max_mueller"
        
        $slugMap[$id] = null;
        $typeMap[$id] = $type;
    }
    // Match: /(articles|cards)/CHANNEL/SLUG (3 Ebenen)
    elseif (preg_match('#/(articles|cards)/([^/]+)/([^/?]+)#', $url, $m)) {
        $typeNames = [
            'articles' => 'Artikel',
            'cards'    => 'Karten'
        ];
        $type = $typeNames[$m[1]];
        $channel = $m[2];  // Channel-Name
        $slug = $m[3];     // Der eigentliche Slug
        
        $slugs[] = $slug;
        $slugMap[$id] = $slug;
        $typeMap[$id] = $type;
    } 
    // Match: /wiki/CHANNEL/WIKINAME/SLUG (4 Ebenen)
    elseif (preg_match('#/wiki/([^/]+)/([^/?]+)/([^/?]+)#', $url, $m)) {
        $channel = $m[1];   // Channel-Name
        $wikiName = $m[2];  // Wiki-Name
        $slug = $m[3];      // Page-Slug
        
        $slugs[] = $slug;
        $slugMap[$id] = $slug;
        $typeMap[$id] = 'Wiki';
    } 
    else {
        $slugMap[$id] = null;
        $typeMap[$id] = null;
    }
}

/* ============================================================
   TITEL-BATCH-QUERY
   ============================================================ */
$titles = [];
if ($slugs) {
    try {
        $placeholders = rtrim(str_repeat('?,', count($slugs)), ',');
        $titleSql = "SELECT uuid, title FROM item WHERE uuid IN ($placeholders)";
        $titleStmt = $pdoItems->prepare($titleSql);
        $titleStmt->execute($slugs);
        foreach ($titleStmt->fetchAll() as $t) {
            $titles[$t['uuid']] = $t['title'];
        }
    } catch (PDOException $e) {
        error_log('Titel-Query-Fehler: ' . $e->getMessage());
    }
}

/* ============================================================
   HILFSFUNKTION
   ============================================================ */
function slugToTitle(string $slug): string
{
    $withSpaces = str_replace('_', ' ', $slug);
    return mb_convert_case($withSpaces, MB_CASE_TITLE, 'UTF-8');
}

/* ============================================================
   GESAMTZAHL ALLER KLICKS ZÄHLEN
   ============================================================ */
$totalHits = 0;
$totalEntries = 0;  // ✅ Neue Variable für Einträge

try {
    $sumStmt = $pdoHits->prepare('SELECT SUM(hitcount) AS total FROM url_hits');
    $sumStmt->execute();
    $result = $sumStmt->fetch();
    $totalHits = (int)($result['total'] ?? 0);
    
    // ✅ Anzahl der Einträge zählen
    $countStmt = $pdoHits->prepare('SELECT COUNT(*) AS entries FROM url_hits');
    $countStmt->execute();
    $countResult = $countStmt->fetch();
    $totalEntries = (int)($countResult['entries'] ?? 0);
} catch (PDOException $e) {
    error_log('Fehler beim Zählen der Klicks: ' . $e->getMessage());
}

/* ============================================================
   HTML-AUSGABE
   ============================================================ */
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$path = strtok($_SERVER['REQUEST_URI'], '?'); // Entfernt alles nach ?
$currentUrl = $protocol . '://' . $host . $path;

// DEBUG-MELDUNG ANZEIGEN
if (!empty($debugMsg)) {
    echo $debugMsg;
}

echo '<div class="logo"><IMG SRC="https://voidofxulub.com/cloud/warzazel/voidspider/logo.jpeg" class="logo-img"></div>';
echo '<div class="header_top"> Top‑Einträge aus Artikeln, Karten und Wikis</div>';
echo '<div class="header_top"><strong>Statistik:</strong> <span class="hits">' . $totalHits . '</span> Klicks gesamt auf <span class="cats">' . $totalEntries . '</span> Links...</div>';
echo '<div class="entry">Top <a href="' . $currentUrl . '?limit=5">5</a> - 
<a href="' . $currentUrl . '?limit=10">10</a> - 
<a href="' . $currentUrl . '?limit=25">25</a> - 
<a href="' . $currentUrl . '?limit=50">50</a> - 
<a href="' . $currentUrl . '?limit=100">100</a></div>';

// DEBUG-MELDUNG ANZEIGEN
if (!empty($debugMsg)) {
    echo $debugMsg;
}

echo <<<HTML
<style>
    /* === LAYOUT & CONTAINER === */
    .list { 
        max-width: 800px; 
        margin: auto; 
        font-family: Arial, Helvetica, sans-serif; 
        color: #eee; 
    }
    
    .entry { 
        background: #2c2c2c; 
        border-radius: 6px; 
        padding: 1rem; 
        margin-bottom: 1rem; 
        box-shadow: 0 2px 6px rgba(0,0,0,.3); 
    }
    
    .entry > div { 
        display: flex; 
        align-items: baseline; 
        margin: .4rem 0; 
    }
    
    .entry a:hover { 
        text-decoration: underline; 
    }
    
    /* === BUTTONS === */
    .delete-btn { 
        padding: 0.5rem 1rem; 
        margin-right: .5rem; 
        background: #670000; 
        color: white; 
        border: none; 
        border-radius: 4px; 
        cursor: pointer; 
    }
    
    .delete-btn:hover { 
        background: #550000; 
    }
    
    .optout-btn { 
        padding: 0.5rem 1rem; 
        margin-right: .5rem; 
        background: #5a5a5a; 
        color: white; 
        border: none; 
        border-radius: 4px; 
        cursor: pointer; 
    }
    
    .optout-btn:hover { 
        background: #3f3e3e; 
    }
    
    .hide-btn { 
        padding: 0.5rem 1rem; 
        margin-right: .5rem; 
        background: #f0b80e; 
        color: white; 
        border: none; 
        border-radius: 4px; 
        cursor: pointer; 
    }
    
    .hide-btn:hover { 
        background: #d8a306; 
    }
    
    /* === SPEZIFISCHE ELEMENTE === */
    .icon { 
        width: 1.2rem; 
        margin-right: .5rem; 
    }
    
    .logo { 
        background: #000000; 
        border: 1px solid #ffd800;
        border-radius: 6px;
        padding: 1rem; 
        margin-bottom: 1rem; 
        box-shadow: 0 2px 6px rgba(0,0,0,.3); 
        text-align: left; 
        font-size: 2em; 
        color: #ffc107; 
    }
    
    .logo-img { 
        max-width: 90%; 
        height: auto; 
        display: block; 
    }
    
    .header_top { 
        background: #2c2c2c; 
        border-radius: 6px; 
        padding: 1rem; 
        margin-bottom: 1rem; 
        box-shadow: 0 2px 6px rgba(0,0,0,.3); 
        text-align: left; 
        font-size: 1.2em; 
        color: #fff; 
    }
    
    .copy { 
        background: #2c2c2c; 
        border-radius: 6px; 
        padding: 1rem; 
        margin-bottom: 1rem; 
        box-shadow: 0 2px 6px rgba(0,0,0,.3); 
        text-align: right; 
        color: #f0b80e; 
    }
    
    .auliste { 
        background: #2c2c2c; 
        border-radius: 6px; 
        padding: 1rem; 
        margin-bottom: 1rem; 
        box-shadow: 0 2px 6px rgba(0,0,0,.3); 
        text-align: left; 
        font-size: 2em; 
    }
        .typecattext { 
        color: #f0b80e; 
        text-align: left; 
        font-size: 1em; 
    }
        .typelinktext { 
        color: #ffffff; 
        text-align: left; 
        font-size: 1em; 
    }
        .hits { 
        font-style: bold;
        background: #141414;
        padding: 0 0.2rem;        
        border-radius: 2px;
        font-size: 2em;
        color: #f0b80e; 
        font-size: 1em; 
    }
        .cats { 
        font-style: bold;
        background: #141414;
        padding: 0 0.2rem;        
        border-radius: 2px;
        font-size: 2em;
        color: #f0b80e; 
        font-size: 1em; 
    }
    
    /* === RESPONSIVE === */
    @media(max-width: 500px) { 
        .entry { 
            padding: .8rem; 
        } 
    }
</style>
<div class="list">
HTML;

foreach ($rows as $row) {
    $id    = (int)$row['id'];
    $url   = htmlspecialchars($row['url'], ENT_QUOTES, 'UTF-8');
    $hits  = (int)$row['hits'];
    $last  = htmlspecialchars($row['last_seen'], ENT_QUOTES, 'UTF-8');

    $slug = $slugMap[$id] ?? null;
    $type = $typeMap[$id] ?? null;
    
    // Titel bestimmen
    if ($slug && isset($titles[$slug])) {
        $titleText = htmlspecialchars($titles[$slug], ENT_QUOTES, 'UTF-8');
    } elseif ($slug) {
        $titleText = htmlspecialchars(slugToTitle($slug), ENT_QUOTES, 'UTF-8');
    } else {
        // Kein Slug → zeige URL als Titel
        $titleText = $url;
    }
    
    // Präfix hinzufügen, falls vorhanden
    if ($type) {
        $display = "<span class=\"typecattext\">{$type}:&nbsp;</span> <span class=\"typelinktext\">{$titleText}</span>";
    } else {
        $display = $titleText;
    }

// Delete-Button
$deleteBtn = '<form method="GET" style="display:inline;" onsubmit="return confirm(\'Eintrag mit ID ' . $id . ' wirklich aus der Datenbank löschen?\n\nBereits gezählte Klicks werden auch gelöscht und der Zählerstand beginnt wieder bei 0!!!\n\nSeite lädt automatisch neu\');">
    <input type="hidden" name="del_id" value="' . $id . '">
    <button type="submit" class="delete-btn">🗑️ Löschen</button>
</form>';

// Hide-Button
$addBtn = '<form method="GET" style="display:inline;" onsubmit="return confirm(\'Eintrag mit ID ' . $id . ' wirklich ausblenden?\n\nDer Eintrag wird lediglich nicht mehr in der Top-Liste angezeigt, Klicks werden aber weiter gezählt.\n\nÜber die Ausschlussliste kann der Eintrag wieder in der Top-Liste aufgenommen werden.\');">
    <input type="hidden" name="add_id" value="' . $id . '">
    <button type="submit" class="hide-btn">🗑️ Ausblenden</button>
</form>';

    echo <<<ENTRY
    <div class="entry">
        <div><span class="icon">⚰️</span><strong>Kategorie/Titel: &nbsp;</strong>{$display}</div>
        <div><span class="icon">⛓️</span><a href="{$url}" target="_blank">Link öffnen</a></div>
        <div><span class="icon">💥</span><strong>Klicks:&nbsp;</strong> {$hits}</div>
        <div><span class="icon">🕰️</span><strong>Zuletzt geklickt:&nbsp;</strong> {$last}</div>
        <div><span class="icon">⚔️</span><strong>ID:&nbsp; </strong>{$id}</div>
        <div>{$deleteBtn}{$addBtn}</div>
    </div>

ENTRY;
}

/* ============================================================
   AUSSCHLUSSLISTE ANZEIGEN
   ============================================================ */
echo '<hr style="margin: 2rem 0; border: none; border-top: 2px solid #444;">';

try {
    $excludeListStmt = $pdoHits->prepare('SELECT id, exclude FROM ausschluss ORDER BY id DESC');
    $excludeListStmt->execute();
    $excludeList = $excludeListStmt->fetchAll();
    
    // ✅ Anzahl berechnen und in der Überschrift anzeigen
    $excludeCount = count($excludeList);
    echo '<div class="auliste">💀 Ausschlussliste (' . $excludeCount . ')</div>';
    
    if (!empty($excludeList)) {
        // Alle URLs für die Ausschlussliste abrufen
        $excludeSlugs = [];
        $excludeSlugMap = [];
        $excludeTypeMap = [];  // ✅ Typen speichern
        
        foreach ($excludeList as $excludeRow) {
            $excludeId = (int)$excludeRow['id'];
            $excludeValue = $excludeRow['exclude'];
            
            // Wenn es eine ID ist, die URL aus url_hits abrufen
            if (is_numeric($excludeValue)) {
                $urlStmt = $pdoHits->prepare('SELECT url FROM ausschluss WHERE id = ? LIMIT 1');
                $urlStmt->execute([$excludeId]);
                $urlRow = $urlStmt->fetch();
                $excludeUrl = $urlRow ? $urlRow['url'] : '';
            } else {
                $excludeUrl = $excludeValue;
            }
            
            // ✅ Slug extrahieren (mit dynamischem Channel und allen Typen)
            // Match: /(articles|cards|wiki)/CHANNEL (2 Ebenen)
            if (preg_match('#^/(articles|cards|wiki)/([^/]+)/?$#', $excludeUrl, $m)) {
                $typeNames = [
                    'articles' => 'Artikel',
                    'cards'    => 'Karten',
                    'wiki'     => 'Wiki'
                ];
                $type = $typeNames[$m[1]];
                
                $excludeSlugMap[$excludeId] = null;
                $excludeTypeMap[$excludeId] = $type;
            }
            // Match: /(articles|cards)/CHANNEL/SLUG (3 Ebenen)
            elseif (preg_match('#/(articles|cards)/([^/]+)/([^/?]+)#', $excludeUrl, $m)) {
                $typeNames = [
                    'articles' => 'Artikel',
                    'cards'    => 'Karten'
                ];
                $type = $typeNames[$m[1]];
                $slug = $m[3];  // ✅ $m[3] weil $m[2] = Channel
                
                $excludeSlugs[] = $slug;
                $excludeSlugMap[$excludeId] = $slug;
                $excludeTypeMap[$excludeId] = $type;
            }
            // Match: /wiki/CHANNEL/WIKINAME/SLUG (4 Ebenen)
            elseif (preg_match('#/wiki/([^/]+)/([^/?]+)/([^/?]+)#', $excludeUrl, $m)) {
                $slug = $m[3];  // Page-Slug
                
                $excludeSlugs[] = $slug;
                $excludeSlugMap[$excludeId] = $slug;
                $excludeTypeMap[$excludeId] = 'Wiki';
            }
            else {
                $excludeSlugMap[$excludeId] = null;
                $excludeTypeMap[$excludeId] = null;
            }
        }
        
        // Titel-Batch-Query für Ausschlussliste
        $excludeTitles = [];
        if ($excludeSlugs) {
            try {
                $placeholders = rtrim(str_repeat('?,', count($excludeSlugs)), ',');
                $titleSql = "SELECT uuid, title FROM item WHERE uuid IN ($placeholders)";
                $titleStmt = $pdoItems->prepare($titleSql);
                $titleStmt->execute($excludeSlugs);
                foreach ($titleStmt->fetchAll() as $t) {
                    $excludeTitles[$t['uuid']] = $t['title'];
                }
            } catch (PDOException $e) {
                error_log('Titel-Query-Fehler (Ausschlussliste): ' . $e->getMessage());
            }
        }
        
        // Ausschlussliste anzeigen
        foreach ($excludeList as $excludeRow) {
            $excludeId = (int)$excludeRow['id'];
            $excludeValue = $excludeRow['exclude'];
            
            // URL abrufen
            if (is_numeric($excludeValue)) {
                $urlStmt = $pdoHits->prepare('SELECT url FROM ausschluss WHERE id = ? LIMIT 1');
                $urlStmt->execute([$excludeId]);
                $urlRow = $urlStmt->fetch();
                $excludeUrl = $urlRow ? htmlspecialchars($urlRow['url'], ENT_QUOTES, 'UTF-8') : htmlspecialchars($excludeValue, ENT_QUOTES, 'UTF-8');
            } else {
                $excludeUrl = htmlspecialchars($excludeValue, ENT_QUOTES, 'UTF-8');
            }
            
            // ✅ Display-Text wie in der Hauptausgabe (mit Typ-Präfix)
            $slug = $excludeSlugMap[$excludeId] ?? null;
            $type = $excludeTypeMap[$excludeId] ?? null;
            
            // Titel bestimmen
            if ($slug && isset($excludeTitles[$slug])) {
                $titleText = htmlspecialchars($excludeTitles[$slug], ENT_QUOTES, 'UTF-8');
            } elseif ($slug) {
                $titleText = htmlspecialchars(slugToTitle($slug), ENT_QUOTES, 'UTF-8');
            } else {
                $titleText = $excludeUrl;
            }
            
            // Präfix hinzufügen, falls vorhanden
            if ($type) {
        $display = "<span class=\"typecattext\">{$type}:&nbsp;</span> <span class=\"typelinktext\">{$titleText}</span>";
            } else {
                $display = $titleText;
            }
            
            // Delete-Exclude-Button (für die Ausschlussliste)
            $deleteExcludeBtn = '<form method="GET" style="display:inline;" onsubmit="return confirm(\'Diesen Eintrag aus der Ausschlussliste entfernen und wieder in die Top-Liste aufnehmen?\n\nID: ' . $excludeId . '\');">
                <input type="hidden" name="del_exclude_id" value="' . $excludeId . '">
                <button type="submit" class="optout-btn">🗑️ Entfernen</button>
            </form>';
            
            echo <<<EXCLUDE_ENTRY
            <div class="entry">
                <div><span class="icon">⚰️</span><strong>Kategorie&Titel: &nbsp;</strong>{$display}</div>
                <div><span class="icon">⛓️</span><a href="{$excludeUrl}" target="_blank">Link öffnen</a></div>
                <div>{$deleteExcludeBtn}</div>
            </div>
EXCLUDE_ENTRY;
        }
    } else {
        echo '<p style="color:#999;">Keine Einträge in der Ausschlussliste.</p>';
    }
} catch (PDOException $e) {
    error_log('Fehler beim Abrufen der Ausschlussliste: ' . $e->getMessage());
    echo '<p style="color:#f44336;">❌ Fehler beim Laden der Ausschlussliste</p>';
}

echo '<div class="copy"><a href="https://voidofxulub.com" target="_blank">🕸️ 2026 by 𝖜𝖆𝖗𝖟𝖆𝖟𝖊𝖑⛧</a></div></div>';