<?php
// sitemap_xml.php — the automatic XML sitemap for Google Search Console (v1).
// Save path: public_html/sitemap_xml.php        Address to submit: https://www.tnt024.com/sitemap_xml.php
//
// WHAT IT LISTS (and nothing else)
//  1. The public pages named in $static below (a page is listed only when its file really exists on the server).
//  2. Every published product that customers can buy retail:  product_details.php?id=NUMBER
//     (drafts and wholesale-only products are never listed).
//  3. Every approved store:  seller_shop.php?id=NUMBER
//  4. Every category that has at least one such product:  products.php?category=NAME
// It rebuilds itself on every request, so a new product appears without any work. Nothing is saved or changed in the database.
//
// TEST STORE: store numbers in $SM_EXCLUDE_STORE_IDS (and their products) are left out. Store 2 is the Test Store.
// ADMIN CHECK: open sitemap_xml.php?report=1 while signed in as admin to see what is included and what was left out.

ob_start();                                   // guards against stray spaces from other files before the XML starts
require_once __DIR__ . '/config.php';

$SM_BASE = 'https://www.tnt024.com';          // the address your site really uses (with www)
$SM_EXCLUDE_STORE_IDS = [2];                  // Test Store; add other test store numbers here
$SM_MAX_URLS = 50000;                         // Google's limit for one sitemap file

// Public pages. Remove a line to leave a page out; add a line (and its file name) to include another page.
// Pages still marked "coming soon" in the menu (services, job portal, property, ride, freelancing) are left out on purpose.
$static = [
    ['/',                        'index.php'],
    ['/products.php',            'products.php'],
    ['/wholesale.php',           'wholesale.php'],
    ['/stores.php',              'stores.php'],
    ['/reviews.php',             'reviews.php'],
    ['/about_us.php',            'about_us.php'],
    ['/contact.php',             'contact.php'],
    ['/faq.php',                 'faq.php'],
    ['/careers.php',             'careers.php'],
    ['/seller_pricing_plans.php','seller_pricing_plans.php'],
    ['/seller_agreement.php',    'seller_agreement.php'],
    ['/terms_conditions.php',    'terms_conditions.php'],
    ['/privacy_policy.php',      'privacy_policy.php'],
    ['/cookie_policy.php',       'cookie_policy.php'],
    ['/shipping_policy.php',     'shipping_policy.php'],
    ['/cancellation_policy.php', 'cancellation_policy.php'],
    ['/return_policy.php',       'return_policy.php'],
];

function sm_date($value): ?string {
    if ($value === null || $value === '' || strpos((string) $value, '0000') === 0) { return null; }
    $ts = is_numeric($value) ? (int) $value : strtotime((string) $value);
    return ($ts && $ts > 946684800) ? gmdate('Y-m-d\TH:i:s\Z', $ts) : null;
}

$urls = [];                                   // each: [address, lastmod or null, section]
$rep  = ['missing' => [], 'cats' => [], 'products' => 0, 'stores' => 0, 'excluded_products' => 0, 'db_error' => ''];

// 1) public pages
foreach ($static as $s) {
    $file = __DIR__ . '/' . $s[1];
    if (is_file($file)) { $urls[] = [$SM_BASE . $s[0], sm_date(filemtime($file)), 'page']; }
    else { $rep['missing'][] = $s[1]; }
}

// 2-4) products, categories, stores
if (isset($conn) && $conn instanceof mysqli) {
    try {
        $ids = array_map('intval', $SM_EXCLUDE_STORE_IDS);
        $excl = $ids ? ' AND (store_id IS NULL OR store_id NOT IN (' . implode(',', $ids) . '))' : '';
        $ok   = "publish_status = 'published' AND sale_type IN ('retail','both')";

        $r = $conn->query("SELECT id, updated_at FROM products WHERE $ok $excl ORDER BY id");
        while ($row = $r->fetch_assoc()) {
            $urls[] = [$SM_BASE . '/product_details.php?id=' . (int) $row['id'], sm_date($row['updated_at']), 'product'];
            $rep['products']++;
        }
        if ($ids) {
            $r = $conn->query("SELECT COUNT(*) AS n FROM products WHERE $ok AND store_id IN (" . implode(',', $ids) . ')');
            $rep['excluded_products'] = (int) ($r->fetch_assoc()['n'] ?? 0);
        }

        $r = $conn->query("SELECT DISTINCT LOWER(TRIM(category)) AS c FROM products
                           WHERE $ok $excl AND category IS NOT NULL AND TRIM(category) <> '' AND TRIM(category) <> '0' ORDER BY c");
        while ($row = $r->fetch_assoc()) {
            $urls[] = [$SM_BASE . '/products.php?category=' . rawurlencode($row['c']), null, 'category'];
            $rep['cats'][] = $row['c'];
        }

        $exS = $ids ? ' AND id NOT IN (' . implode(',', $ids) . ')' : '';
        $r = $conn->query("SELECT id FROM stores WHERE status = 'approved' $exS ORDER BY id");
        while ($row = $r->fetch_assoc()) {
            $urls[] = [$SM_BASE . '/seller_shop.php?id=' . (int) $row['id'], null, 'store'];
            $rep['stores']++;
        }
    } catch (Throwable $e) {
        $rep['db_error'] = $e->getMessage();
        error_log('sitemap_xml.php database part failed: ' . $e->getMessage());
    }
} else {
    $rep['db_error'] = 'no database connection';
}
$urls = array_slice($urls, 0, $SM_MAX_URLS);

// ---------------------------------------------------------------- admin report
if (isset($_GET['report'])) {
    if (session_status() === PHP_SESSION_NONE) { session_start(); }
    $uid = (int) ($_SESSION['user_id'] ?? $_SESSION['id'] ?? 0);
    $role = strtolower((string) ($_SESSION['role'] ?? $_SESSION['user_role'] ?? $_SESSION['user_type'] ?? ''));
    $adminId = defined('ADMIN_USER_ID') ? (int) ADMIN_USER_ID : 4;
    if (($uid > 0 && $uid === $adminId) || $role === 'admin') {
        ob_end_clean();
        header('Content-Type: text/html; charset=utf-8');
        header('X-Robots-Tag: noindex, nofollow');
        $h = function ($v) { return htmlspecialchars((string) $v, ENT_QUOTES, 'UTF-8'); };
        $counts = ['page' => 0, 'product' => 0, 'category' => 0, 'store' => 0];
        foreach ($urls as $u) { $counts[$u[2]]++; }
        echo '<!DOCTYPE html><meta charset="utf-8"><meta name="robots" content="noindex"><title>Sitemap report</title>'
           . '<body style="font:14px/1.6 system-ui,sans-serif;max-width:900px;margin:20px auto;padding:0 14px">'
           . '<h2>Sitemap report</h2><p><a href="sitemap_xml.php">Open the real XML</a></p><ul>'
           . '<li><strong>' . count($urls) . '</strong> addresses in total</li>'
           . '<li>Public pages: <strong>' . $counts['page'] . '</strong>' . ($rep['missing'] ? ' (file not found, so left out: ' . $h(implode(', ', $rep['missing'])) . ')' : '') . '</li>'
           . '<li>Products: <strong>' . $counts['product'] . '</strong> (published, retail or retail + wholesale)</li>'
           . '<li>Left out as Test Store products: <strong>' . (int) $rep['excluded_products'] . '</strong></li>'
           . '<li>Stores: <strong>' . $counts['store'] . '</strong> (approved only)</li>'
           . '<li>Categories: <strong>' . $counts['category'] . '</strong>: ' . $h(implode(', ', $rep['cats'])) . '</li>'
           . ($rep['db_error'] !== '' ? '<li style="color:#b00">Database problem: ' . $h($rep['db_error']) . '</li>' : '')
           . '</ul><h3>First 40 addresses</h3><pre style="white-space:pre-wrap">';
        foreach (array_slice($urls, 0, 40) as $u) { echo $h($u[0]) . "\n"; }
        echo '</pre></body>';
        exit;
    }
}

// ---------------------------------------------------------------- the XML
ob_end_clean();
header('Content-Type: application/xml; charset=UTF-8');
header('Cache-Control: public, max-age=3600');
echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
foreach ($urls as $u) {
    echo '  <url><loc>' . htmlspecialchars($u[0], ENT_XML1 | ENT_QUOTES, 'UTF-8') . '</loc>';
    if ($u[1] !== null) { echo '<lastmod>' . $u[1] . '</lastmod>'; }
    echo '</url>' . "\n";
}
echo '</urlset>' . "\n";