<?php
/**
 * Universal IndexNow submission script
 * Reads sitemap.xml (supports sitemapindex with recursive sub-sitemap fetching).
 * Run: php indexnow-submit.php  or  curl https://{host}/indexnow-submit.php
 */

// --- CONFIG ---
$SITES = [
    'academictuning.com'   => ['key' => 'at-7k3x9p2m5r8q1w4', 'sitemap' => 'sitemap.xml'],
    'classifora.com'       => ['key' => 'cf-2x8c4v7b5n1m3z9', 'sitemap' => 'sitemap.xml'],
    'conciergeservice.fr'  => ['key' => 'cs-9p4r7q2w5y8k3x6', 'sitemap' => 'sitemap.xml'],
    'coverfar.com'         => ['key' => 'cv-4v7b5n1m3z9x2c8', 'sitemap' => 'sitemap.xml'],
    'frenchpropertycare.com' => ['key' => 'fp-7q2w5y8k3x6p9r4', 'sitemap' => 'sitemap.xml'],
    'heatquotes.com'       => ['key' => 'hq-5n1m3z9x2c8v4b7', 'sitemap' => 'sitemap.php'],
    'melikhov.fr'          => ['key' => 'ml-8k3x6p9r4q7w2y5', 'sitemap' => 'sitemap.xml'],
    'monviso.us'           => ['key' => 'mv-1m3z9x2c8v4b7n5', 'sitemap' => 'sitemap.xml'],
    'privet.fr'            => ['key' => 'pf-6p9r4q7w2y5k8x3', 'sitemap' => 'sitemap.xml'],
    'privet.su'            => ['key' => 'ps-3z9x2c8v4b7n5m1', 'sitemap' => 'sitemap.xml'],
];

define('INDEXNOW_API', 'https://api.indexnow.org/indexnow');

// Auto-detect host from script location
$host = null;
$key = null;
$sitemapFile = 'sitemap.xml';

if (isset($_SERVER['SERVER_NAME'])) {
    $host = $_SERVER['SERVER_NAME'];
    if (isset($SITES[$host])) {
        $key = $SITES[$host]['key'];
        $sitemapFile = $SITES[$host]['sitemap'];
    }
} elseif (PHP_SAPI === 'cli' && isset($argv[1])) {
    $host = $argv[1];
    if (isset($SITES[$host])) {
        $key = $SITES[$host]['key'];
        $sitemapFile = $SITES[$host]['sitemap'];
    }
} else {
    // CLI without arg — try to detect from directory name
    $dir = basename(__DIR__);
    foreach ($SITES as $h => $cfg) {
        if (strpos($dir, $h) !== false || $h === $dir) {
            $host = $h;
            $key = $cfg['key'];
            $sitemapFile = $cfg['sitemap'];
            break;
        }
    }
}

if (!$host || !$key) {
    $msg = "Error: Could not determine site. Run with: php indexnow-submit.php {host}\n";
    if (PHP_SAPI === 'cli') fwrite(STDERR, $msg);
    else { http_response_code(400); echo $msg; }
    exit(1);
}

define('HOST', $host);
define('KEY', $key);
define('KEY_LOCATION', 'https://' . HOST . '/' . KEY . '.txt');

function fetchUrlsFromSitemap(string $sitemapUrl): array {
    $urls = [];
    $seen = [];

    // If local file contains PHP code, fetch via HTTP instead
    if (!str_starts_with($sitemapUrl, 'http') && file_exists($sitemapUrl)) {
        $firstBytes = file_get_contents($sitemapUrl, false, null, 0, 50);
        if (str_contains($firstBytes, '<?php')) {
            $sitemapUrl = 'https://' . HOST . '/' . basename($sitemapUrl);
        }
    }

    $xml = @simplexml_load_file($sitemapUrl);
    if ($xml === false) {
        // Broken sitemap — scan local sitemap*.xml as fallback
        if (!str_starts_with($sitemapUrl, 'http') && basename($sitemapUrl) === 'sitemap.xml') {
            $dir = dirname($sitemapUrl) ?: __DIR__;
            foreach (glob($dir . '/sitemap*.xml') as $file) {
                if ($file === $sitemapUrl) continue;
                if (str_contains(basename($file), 'sitemap-images')) continue;
                $subUrls = fetchUrlsFromSitemap($file);
                $urls = array_merge($urls, $subUrls);
            }
        }
        return $urls;
    }

    $rootName = $xml->getName();
    $isIndex = $rootName === 'sitemapindex';

    if ($isIndex) {
        // First try <sitemap> children in the XML
        if (isset($xml->sitemap) && count($xml->sitemap) > 0) {
            foreach ($xml->sitemap as $sub) {
                $subLoc = (string) $sub->loc;
                if ($subLoc && !isset($seen[$subLoc])) {
                    $seen[$subLoc] = true;
                    $subUrls = fetchUrlsFromSitemap($subLoc);
                    $urls = array_merge($urls, $subUrls);
                }
            }
        }
        // Fallback: sitemapindex was empty — scan local sitemap-*.xml files
        if (empty($urls) && !str_starts_with($sitemapUrl, 'http')) {
            $dir = dirname($sitemapUrl) ?: __DIR__;
            foreach (glob($dir . '/sitemap*.xml') as $file) {
                if ($file === $sitemapUrl) continue;
                if (basename($file) === 'sitemap-images.xml') continue;
                $subUrls = fetchUrlsFromSitemap($file);
                $urls = array_merge($urls, $subUrls);
            }
        }
    } else {
        $xml->registerXPathNamespace('s', 'http://www.sitemaps.org/schemas/sitemap/0.9');
        $nodes = $xml->xpath('//s:url/s:loc');
        if (empty($nodes)) {
            $nodes = $xml->xpath('//url/loc');
        }
        foreach ($nodes as $node) {
            $loc = (string) $node;
            if ($loc && !isset($seen[$loc])) {
                $seen[$loc] = true;
                $urls[] = $loc;
            }
        }
    }

    return $urls;
}

// Fetch URLs
$sitemapPath = __DIR__ . '/' . $sitemapFile;
$sitemapSrc = file_exists($sitemapPath) ? $sitemapPath : ('https://' . HOST . '/' . $sitemapFile);

$urls = fetchUrlsFromSitemap($sitemapSrc);
$urls = array_unique($urls);
$urls = array_values($urls);

if (empty($urls)) {
    $msg = "Error: No URLs found in sitemap for " . HOST;
    if (PHP_SAPI === 'cli') fwrite(STDERR, $msg . "\n");
    else { http_response_code(500); echo $msg; }
    exit(1);
}

// Submit to IndexNow (chunked batches of 500)
$CHUNK_SIZE = 500;
$totalSubmitted = 0;
$lastHttpCode = 0;
$lastResponse = '';
$allOk = true;

$chunks = array_chunk($urls, $CHUNK_SIZE);

foreach ($chunks as $i => $chunk) {
    $payload = json_encode([
        'host' => HOST,
        'key' => KEY,
        'keyLocation' => KEY_LOCATION,
        'urlList' => $chunk,
    ]);

    $ch = curl_init(INDEXNOW_API);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 60,
        CURLOPT_FOLLOWLOCATION => true,
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    $lastHttpCode = $httpCode;
    $lastResponse = $response;
    $totalSubmitted += count($chunk);

    if ($error) {
        if (PHP_SAPI === 'cli') fwrite(STDERR, "cURL error (chunk $i): $error\n");
        $allOk = false;
        break;
    }
    if ($httpCode < 200 || $httpCode >= 300) {
        if (count($chunks) > 1 && PHP_SAPI === 'cli') {
            fwrite(STDERR, "Chunk $i failed: HTTP $httpCode\n");
        }
        $allOk = false;
    }
}

// Output
$result = [
    'host' => HOST,
    'status' => $lastHttpCode,
    'urls_submitted' => $totalSubmitted,
    'response' => $lastResponse ?: '(empty)',
    'time' => date('c'),
    'chunks' => count($chunks),
    'ok' => $allOk,
];

if (PHP_SAPI === 'cli') {
    echo "IndexNow: " . HOST . " — HTTP $lastHttpCode — $totalSubmitted URLs (" . count($chunks) . " chunk(s)) — " . ($allOk ? "OK" : "FAIL") . "\n";
} else {
    header('Content-Type: application/json');
    echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
exit($allOk ? 0 : 1);
