<?php
/**
 * CRON JOB — run every 20-30 minutes on your host, e.g.:
 *   php-cli:  php /home/USER/public_html/updates/cron/fetch_rss.php
 *   wget:     wget -q -O /dev/null "https://gamesji.com/updates/cron/fetch_rss.php?key=YOUR_SECRET"
 *
 * Only keeps items whose title/summary match KEYWORD_FILTER in config.php,
 * so the feed stays focused on ONLINE / MOBILE game news only.
 */
require_once __DIR__ . '/../includes/functions.php';

// Optional light protection when triggered over HTTP (cron via URL / wget).
// Set CRON_SECRET below and pass ?key=... to prevent random visitors from
// spamming your fetch job. Leave blank to allow open access (fine for most
// low-traffic setups since this endpoint is idempotent).
define('CRON_SECRET', '');
if (php_sapi_name() !== 'cli' && CRON_SECRET !== '') {
    if (!isset($_GET['key']) || $_GET['key'] !== CRON_SECRET) {
        http_response_code(403);
        die('Forbidden');
    }
}

header('Content-Type: text/plain; charset=utf-8');
echo "GamesJi Updates - RSS Fetcher run @ " . date('Y-m-d H:i:s') . "\n";

function fetch_url($url) {
    if (function_exists('curl_init')) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_TIMEOUT => 20,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; GamesJiUpdatesBot/1.0; +' . SITE_URL . ')',
        ]);
        $data = curl_exec($ch);
        $err = curl_error($ch);
        curl_close($ch);
        if ($data === false) {
            echo "  [WARN] cURL error for $url: $err\n";
            return false;
        }
        return $data;
    }
    // Fallback to file_get_contents with a stream context
    $ctx = stream_context_create(['http' => ['timeout' => 20, 'header' => "User-Agent: GamesJiUpdatesBot/1.0\r\n"]]);
    $data = @file_get_contents($url, false, $ctx);
    return $data;
}

function matches_keywords($text) {
    $keywords = unserialize(KEYWORD_FILTER);
    $text = strtolower($text);
    foreach ($keywords as $kw) {
        if (strpos($text, strtolower($kw)) !== false) return true;
    }
    return false;
}

function extract_image($item, $ns) {
    // Try media:content, media:thumbnail, then enclosure
    $media = $item->children($ns['media'] ?? 'http://search.yahoo.com/mrss/');
    if (isset($media->content) && (string)$media->content->attributes()->url) {
        return (string)$media->content->attributes()->url;
    }
    if (isset($media->thumbnail) && (string)$media->thumbnail->attributes()->url) {
        return (string)$media->thumbnail->attributes()->url;
    }
    if (isset($item->enclosure) && (string)$item->enclosure->attributes()->url) {
        return (string)$item->enclosure->attributes()->url;
    }
    return '';
}

$feeds = unserialize(RSS_FEEDS);
$pdo = db();
$checkStmt = $pdo->prepare("SELECT id FROM news WHERE guid = ?");
$insertStmt = $pdo->prepare("INSERT INTO news (guid, title, slug, summary, content, link, image, source, published_at)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");

$totalNew = 0;

foreach ($feeds as $feedUrl) {
    echo "Fetching: $feedUrl\n";
    $raw = fetch_url($feedUrl);
    if (!$raw) { echo "  [SKIP] could not fetch\n"; continue; }

    libxml_use_internal_errors(true);
    $xml = simplexml_load_string($raw);
    if ($xml === false) { echo "  [SKIP] invalid XML\n"; continue; }

    $sourceName = parse_url($feedUrl, PHP_URL_HOST);
    $items = [];

    if (isset($xml->channel->item)) {
        // RSS 2.0
        $sourceName = (string)($xml->channel->title ?: $sourceName);
        foreach ($xml->channel->item as $item) $items[] = $item;
    } elseif (isset($xml->entry)) {
        // Atom
        $sourceName = (string)($xml->title ?: $sourceName);
        foreach ($xml->entry as $item) $items[] = $item;
    }

    $newInFeed = 0;
    foreach ($items as $item) {
        $ns = $item->getNamespaces(true);
        $title = trim((string)$item->title);
        if (!$title) continue;

        // Atom vs RSS field mapping
        $link = '';
        if (isset($item->link)) {
            if (is_object($item->link) && count($item->link->attributes()) > 0 && (string)$item->link->attributes()->href) {
                $link = (string)$item->link->attributes()->href;
            } else {
                $link = trim((string)$item->link);
            }
        }
        $guid = isset($item->guid) ? trim((string)$item->guid) : ($link ?: md5($title));
        $summaryRaw = (string)($item->description ?? $item->summary ?? $item->content ?? '');
        $summary = trim(strip_tags($summaryRaw));
        $summary = mb_strimwidth($summary, 0, 500, '...');
        $pubRaw = (string)($item->pubDate ?? $item->published ?? $item->updated ?? 'now');
        $pubTs = strtotime($pubRaw) ?: time();
        $published_at = date('Y-m-d H:i:s', $pubTs);
        $image = extract_image($item, $ns);

        $searchText = $title . ' ' . $summary;
        if (!matches_keywords($searchText)) continue;

        $checkStmt->execute([$guid]);
        if ($checkStmt->fetch()) continue; // already have it

        $slug = slugify($title) . '-' . substr(md5($guid), 0, 6);

        $insertStmt->execute([
            $guid, $title, $slug, $summary, $summaryRaw, $link, $image, $sourceName, $published_at
        ]);
        $newInFeed++;
        $totalNew++;
    }
    echo "  -> $newInFeed new item(s)\n";
}

// Prune old items beyond MAX_NEWS_ITEMS
$countStmt = $pdo->query("SELECT COUNT(*) FROM news");
$count = (int)$countStmt->fetchColumn();
if ($count > MAX_NEWS_ITEMS) {
    $excess = $count - MAX_NEWS_ITEMS;
    $pdo->exec("DELETE FROM news WHERE id IN (
        SELECT id FROM news ORDER BY published_at ASC LIMIT $excess
    )");
    echo "Pruned $excess old item(s) to stay under MAX_NEWS_ITEMS.\n";
}

meta_set('last_rss_fetch', date('c'));
echo "Done. Total new items this run: $totalNew\n";

// Regenerate sitemap so Google always sees fresh URLs after new content lands
require __DIR__ . '/generate_sitemap.php';
