<?php

require_once __DIR__ . "/core.php";

// Start buffering with the minify callback
ob_start("minify_html");

// index.php

$db_path = __DIR__ . "/data.sqlite";
$db = new PDO("sqlite:" . $db_path);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$res = $db->query("SELECT name, value FROM tblConfig");
$config = $res->fetchAll(PDO::FETCH_KEY_PAIR);

// Load JSON config
$json_path = __DIR__ . "/config.json";
$json_config = file_exists($json_path) ? json_decode(file_get_contents($json_path), true) : [];
$config = array_merge($config, $json_config);



// --- GEOIP, BLOCKING & REDIRECT LOGIC ---
if (file_exists(__DIR__ . "/lib/geo/geo_ip.php")) {
    require_once __DIR__ . "/lib/geo/geo_ip.php";
}

if (!empty($countryCode)) {
    $countryCode = strtoupper($countryCode);
    $blocked_list = $config['blocked_countries'] ?? '';
    if (!empty($blocked_list)) {
        $blocked_array = array_map('trim', explode(',', strtoupper($blocked_list)));
        if (in_array($countryCode, $blocked_array)) {
            header("HTTP/1.1 403 Forbidden");
            die("<h1>403 Forbidden</h1><p>Access denied.</p>");
        }
    }
    if (!is_bot() && !empty($config['redirect_rules'])) {
        $rules = json_decode($config['redirect_rules'], true);
        if (isset($rules[$countryCode])) {
            header("Location: " . $rules[$countryCode], true, 302);
            exit;
        }
    }
}

//Theme Define
$theme_name = $config['theme'] ?? 'default';
$theme_path = __DIR__ . "/themes/" . $theme_name;
$uri = $_SERVER['REQUEST_URI'];
$url_path = parse_url($uri, PHP_URL_PATH);

// SEO Global Defaults
$site_name = $config['blogName'] ?? 'CMS Native';
$site_desc = $config['blogDesc'] ?? 'A lightweight fast CMS';


// --- APACHE-FRIENDLY PROTOCOL DETECTION ---
$protocol=$_SERVER['HTTP_X_FORWARDED_PROTO'];
if (!empty( $protocol)) {
  $protocol= $protocol."://";
} else {
  $protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
}
// --- Force to https ---
$protocol="https://";

$base_url = $protocol . $_SERVER['HTTP_HOST'];
$current_url = $base_url . $_SERVER['REQUEST_URI'];


// --- ROUTER: SITEMAPS, FEEDS & ROBOTS ---
$sitemap_slug = $config['sitemap_slug'] ?? '/sitemap.xml';
if ($url_path === '/robots.txt') { 
    ob_end_clean(); // Stop HTML minification for text file
    header("Content-Type: text/plain");
    echo "User-agent: *\n";
    
    // 1. BLOCK SENSITIVE FOLDERS
    echo "Disallow: /logs/\n";       // Don't let Google index your server logs
    echo "Disallow: /libs/\n";       // Don't let bots crawl your system core files

    // 2. ALLOW EVERYTHING ELSE
    // (Assets, Themes, and Uploads are allowed by default, so we don't need to explicitly 'Allow' them unless we blocked a parent folder)
    echo "Allow: /\n";
    
    // 3. SITEMAPS
    echo "Sitemap: " . $base_url . $sitemap_slug . "\n";
    echo "Sitemap: " . $base_url . "/rss.xml\n";
    echo "Sitemap: " . $base_url . "/sitemap-news.xml\n";
    exit; 
}

if (strpos($url_path,'.txt') !==false) { 
    ob_end_clean(); // Stop HTML minification for text file
    $temp = $url_path;
    $temp = str_replace("/", "", $temp);
    $temp = str_replace(".txt", "", $temp);
    header("HTTP/1.1 200 OK");
    echo $temp;
    exit;
}

if ($url_path === $sitemap_slug) { include __DIR__ . '/sitemap.php'; exit; }
if ($url_path === '/sitemap-news.xml') { include __DIR__ . '/sitemap-news.php'; exit; }
if ($url_path === '/rss.xml') { include __DIR__ . '/rss.php'; exit; }

//Arsae
if ($config['arsae_server']) {
    define('ARSAE_SERVER', $config['arsae_server']); 
    require_once __DIR__ . "/arsae.php";
}



// --- MAIN ROUTER ---
$is_category = (strpos($url_path, '/category/') === 0);

if (empty($url_path) || $url_path == "/" || $is_category) {
    // --- define limit for certain theme ---
    if ($theme_name=='magnum') {
        $limit=15;
    } else if ($theme_name=='saas') {
        $limit=12;
    } else if ($theme_name=='magz') {
        $limit=13;
    } else {
        $limit=10;
    }
    
    // CATEGORY SECTION LOGIC: Fetch 5 posts for each of the top 4 categories
    if  ($theme_name=='complex')  {
        $limit=12;
        $categories_data = [];
        $cat_res = $db->query("SELECT DISTINCT post_category FROM tblPost LIMIT 4");
        $cats = $cat_res->fetchAll(PDO::FETCH_COLUMN);
    
        foreach ($cats as $cat) {
            $stmt_cat = $db->prepare("SELECT * FROM tblPost WHERE post_category = ? AND post_date <= DATETIME('now') ORDER BY post_date DESC LIMIT 7");
            $stmt_cat->execute([$cat]);
            $categories_data[$cat] = $stmt_cat->fetchAll(PDO::FETCH_ASSOC);
        }
    }
    if ($theme_name=='viral') {
        $nav_res = $db->query("SELECT DISTINCT post_category FROM tblPost");
        $nav_categories= $nav_res->fetchAll(PDO::FETCH_COLUMN);
    }
    // --- LISTING LOGIC (Homepage & Category) ---
    $page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
    $offset = (max(1, $page) - 1) * $limit;

    if ($is_category) {
        $category_slug = str_replace('/category/', '', $url_path);
        $category_name = str_replace('-', ' ', $category_slug);
        
        $stmt_count = $db->prepare("SELECT COUNT(*) FROM tblPost WHERE post_category LIKE ? AND post_date <= DATETIME('now')");
        $stmt_count->execute(["%$category_name%"]);
        $total_posts = $stmt_count->fetchColumn();

        $stmt = $db->prepare("SELECT * FROM tblPost WHERE post_category LIKE ? AND post_date <= DATETIME('now') ORDER BY post_date DESC LIMIT ? OFFSET ?");
        $stmt->execute(["%$category_name%", $limit, $offset]);
        $category_name=ucwords($category_name);
        
    } else {
        $total_posts = $db->query("SELECT COUNT(*) FROM tblPost WHERE post_date <= DATETIME('now')")->fetchColumn();
        $stmt = $db->prepare("SELECT * FROM tblPost WHERE post_date <= DATETIME('now') ORDER BY post_date DESC LIMIT ? OFFSET ?");
        $stmt->execute([$limit, $offset]);
    }

    $total_pages = ceil($total_posts / $limit);
    $raw_posts = $stmt->fetchAll(PDO::FETCH_ASSOC);

    $posts = array_map(function($p) {
        $sourceText = !empty(trim($p['post_desc'])) ? $p['post_desc'] : $p['post_content'];
        $excerpt = strip_tags($sourceText);
        $p['post_excerpt'] = mb_strimwidth(preg_replace('/\s+/', ' ', $excerpt), 0, 157, "...");
        return $p;
    }, $raw_posts);

    $popular_posts = $db->query("SELECT post_title, post_permalink, hit, post_category, post_img, post_date,post_keyword FROM tblPost WHERE post_date <= DATETIME('now') ORDER BY hit DESC LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
    
    $jsonld = [
        "@context" => "https://schema.org",
        "@type" => "WebSite",
        "url" => $current_url,
        "name" => $site_name,
        "description" => $site_desc
    ];

    $meta = [
        'title' => ($is_category ? ucfirst($category_name) . " - " : "") . $site_name,
        'desc'  => $is_category ? "Browse all posts in " . $category_name : $site_desc,
        'img'   => $base_url . "/logo.png",
        'url'   => $current_url,
        'type'  => 'website'
    ];
    
    include $theme_path . "/header.php";
    include $theme_path . "/home.php";
    include $theme_path . "/footer.php";

} else {
    if ($theme_name=='viral') {
        $nav_res = $db->query("SELECT DISTINCT post_category FROM tblPost");
        $nav_categories= $nav_res->fetchAll(PDO::FETCH_COLUMN);
    }
    if ($theme_name=='complex') {
        $cat_res = $db->query("SELECT DISTINCT post_category FROM tblPost LIMIT 4");
        $cats = $cat_res->fetchAll(PDO::FETCH_COLUMN);
    
    }
     // --- SINGLE POST LOGIC ---
    $stmt = $db->prepare("SELECT * FROM tblPost WHERE post_permalink = ? AND post_date <= DATETIME('now') LIMIT 1");
    $stmt->execute([$url_path]);
    $post = $stmt->fetch(PDO::FETCH_ASSOC);
    
    if ($post) {
        // 1. Clean and Generate TOC
        $post['post_content'] = clean_post_content($post['post_content']);
        $post['toc'] = generate_toc($post['post_content']);
        $post['post_author_img'] = "/assets/authors/".slugify($post['post_author'] ?? 'admin').".jpg";
        $post_img = get_post_image($post);
    
        // 2. FETCH RELATED POSTS (The Missing Logic)
        $stmt_rel = $db->prepare("SELECT * FROM tblPost WHERE post_category = ? AND id != ? AND post_date <= DATETIME('now') ORDER BY post_date DESC LIMIT 10");
        $stmt_rel->execute([$post['post_category'], $post['id']]);
        $related_posts = $stmt_rel->fetchAll(PDO::FETCH_ASSOC);
    
        // 3. Fetch Popular for sidebar
        $popular_posts = $db->query("SELECT post_title, post_permalink, hit FROM tblPost WHERE post_date <= DATETIME('now') ORDER BY hit DESC LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
    

    
       // 5. Structured Data & Meta
        // --- PREPARE DATA ---
        // Force HTTPS
        $schema_url = str_replace("http://", "https://", $current_url);
        $schema_base = str_replace("http://", "https://", $base_url);
        $schema_img = str_replace("http://", "https://", $post_img);
        
        // ISO 8601 Dates
        $pub_date = date('c', strtotime($post['post_date'])); 
        $mod_date = isset($post['post_updated']) ? date('c', strtotime($post['post_updated'])) : $pub_date;
        $author_name = $post['post_author'] ?? 'Admin';
        if (!empty($post['post_desc'])) {
            $meta_desc = trim($post['post_desc']);
        } else {
            // Fallback: Strip HTML, remove line breaks/extra spaces, and trim
            $clean_text = strip_tags($post['post_content']);
            // Find the last full stop before 200 characters
            $pos = strrpos(substr($clean_text, 0, 250), '.');
            // If a period is found, cut there. Otherwise, fallback to space.
            if ($pos !== false) {
                $meta_desc = substr($clean_text, 0, $pos + 1); // +1 to include the dot
            } else {
                // Fallback: Cut at last space if no sentence end found
                $meta_desc = substr($clean_text, 0, strrpos(substr($clean_text, 0, 200), ' ')) . "...";
            }
        }
        $clean_desc=$meta_desc;
        

        // --- 1. BREADCRUMB ---
        $breadcrumb_ld = [
            "@type" => "BreadcrumbList", 
            "itemListElement" => [
                [
                    "@type" => "ListItem", 
                    "position" => 1, 
                    "name" => "Home", 
                    "item" => $schema_base
                ],
                [
                    "@type" => "ListItem", 
                    "position" => 2, 
                    "name" => ucwords($post['post_category']), 
                    "item" => $schema_base . "/category/" . slugify($post['post_category'])
                ],
                [
                    "@type" => "ListItem", 
                    "position" => 3, 
                    "name" => $post['post_title'], 
                    "item" => $schema_url
                ]
            ]
        ];

        // --- 2. DETERMINE MAIN TYPE ---
        // Valid types: BlogPosting, NewsArticle, Article
        $target_type = $config['schema_type'] ?? 'BlogPosting';
        if (!in_array($target_type, ['NewsArticle', 'Article', 'BlogPosting'])) {
            $target_type = 'BlogPosting';
        }

        // --- 3. MAIN ENTITY CONSTRUCTION ---
        $main_entity = [
            "@type" => $target_type,
            "mainEntityOfPage" => [
                "@type" => "WebPage",
                "@id" => $schema_url
            ],
            "headline" => $post['post_title'],
            "image" => [$schema_img],
            "datePublished" => $pub_date,
            "dateModified" => $mod_date,
            "author" => [
                "@type" => "Person",
                "name" => $author_name,
                "url" => $schema_base . "/author/" . slugify($author_name)
            ],
            "publisher" => [
                "@type" => "Organization",
                "name" => $config['blogName'] ?? 'Site Name',
                "logo" => [
                    "@type" => "ImageObject",
                    "url" => $schema_base . "/logo.png"
                ]
            ],
            "description" => $clean_desc
        ];

// --- 4. INJECT OPTIONAL SCHEMAS ---

        // Generate consistent stats based on Title
        $fake_rating_value = generate_consistent_number($post['post_title'] . "_rate", 45, 50, 1); // 4.5 - 5.0
        $fake_rating_count = generate_consistent_number($post['post_title'], 100, 500); // 100 - 500

        // Option A: AggregateRating (Review Snippet)
        if (!empty($config['schema_opt_rating'])) {
            $main_entity["aggregateRating"] = [
                "@type" => "AggregateRating",
                "ratingValue" => $fake_rating_value, 
                "bestRating" => "5",
                "ratingCount" => $fake_rating_count,
                "itemReviewed" => [
                    "@type" => "Thing",
                    "name" => $post['post_title']
                ]
            ];
        }

        // Option B: Review (Critic Review)
        if (!empty($config['schema_opt_review'])) {
            $main_entity["review"] = [
                "@type" => "Review",
                "reviewRating" => [
                    "@type" => "Rating",
                    "ratingValue" => $fake_rating_value,
                    "bestRating" => "5"
                ],
                "author" => [
                    "@type" => "Person",
                    "name" => $author_name
                ],
                "itemReviewed" => [
                    "@type" => "Thing",
                    "name" => $post['post_title']
                ]
            ];
        }

        // Option C: Offer (Product)
        if (!empty($config['schema_opt_offer'])) {
            $product_entity = [
                "@type" => "Product",
                "name" => $post['post_title'],
                "description" => $clean_desc,
                "image" => [$schema_img],
                // Add the aggregate rating to the Product entity as well for rich snippets
                "aggregateRating" => [
                    "@type" => "AggregateRating",
                    "ratingValue" => $fake_rating_value,
                    "reviewCount" => $fake_rating_count
                ],
                "offers" => [
                    "@type" => "Offer",
                    "url" => $schema_url,
                    "priceCurrency" => "USD",
                    "price" => "0.00", 
                    "availability" => "https://schema.org/InStock"
                ]
            ];
            $extra_entity = $product_entity;
        }

        // --- 5. COMPILE GRAPH ---
        $graph_data = [
            $breadcrumb_ld,
            $main_entity
        ];

        // Add the Product entity to the graph if it exists
        if (isset($extra_entity)) {
            $graph_data[] = $extra_entity;
        }

        $jsonld = [
            "@context" => "https://schema.org", 
            "@graph" => $graph_data
        ];
        
        
        
        
        // 2. Build the final meta array
        $meta = [
            'title' => $post['post_title'] . " - " . $site_name, 
            'desc'  => $meta_desc, // Limit to 160 chars with ellipsis
            'img'   => $post_img, 
            'url'   => $current_url, 
            'type'  => 'article'
        ];
        
        // 4. Ads Injection (Process before including templates)
        $ad_code = $config['main_ad_code'] ?? '';
        $placement = $config['main_ad_placement'] ?? 'floating';
        if (!is_bot() && !empty($ad_code)) {
            $ad_html = '<div class="my-8 flex justify-center w-full clear-both">' . $ad_code . '</div>';
            if ($placement === 'before_h2') {
                $post['post_content'] = preg_replace('/(<h2\b[^>]*>)/i', $ad_html . '$1', $post['post_content'], 1);
            } elseif ($placement === 'after_h1' || $placement === 'below_image') {
                $post['post_content'] = $ad_html . $post['post_content'];
            }
        }
        
        // 6. Render
        include $theme_path . "/header.php";
        include $theme_path . "/post.php";
        include $theme_path . "/footer.php";
        
        // 7. Background hits logic
        if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); }
        if (!is_bot()) {
            $log_dir = __DIR__ . '/logs';
            if (!is_dir($log_dir)) mkdir($log_dir, 0755, true);
            file_put_contents($log_dir . '/hits.buffer', $post['id'] . PHP_EOL, FILE_APPEND | LOCK_EX);
            $pid_file = $log_dir . '/worker.pid';
            if (!file_exists($pid_file) || (time() - filemtime($pid_file) > 60)) {
                exec("nohup php " . __DIR__ . "/worker.php > /dev/null 2>&1 &");
            }
        }
    } else {
        // --- 404 ---
        header("HTTP/1.0 404 Not Found");
        $recent_posts = $db->query("SELECT post_title, post_permalink, post_date, post_keyword, hit, post_category FROM tblPost WHERE post_date <= DATETIME('now') ORDER BY hit DESC LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
        $meta = ['title' => "404 Not Found", 'desc' => "Page not found", 'url' => $current_url, 'type' => 'website'];
        include $theme_path . "/header.php";
        include $theme_path . "/404.php";
        include $theme_path . "/footer.php";
    }
}
// --- AT THE VERY END OF THE FILE ---
if (ob_get_length()) ob_end_flush();
?>