<?php

/**

 * Blog post generator — picks a topic from DB, calls Groq, saves to DB, pings sitemaps.

 */



require_once __DIR__ . '/db.php';

require_once __DIR__ . '/groq.php';

require_once __DIR__ . '/../config.php';



/**

 * Pick the next available topic from blog_topics.

 * Uses topics with use_count < max_uses, ordered by fewest uses first.

 * When all topics are exhausted, resets all counts and starts over.

 *

 * @return array{id: int, text: string}

 */

function pick_next_topic(): array

{

    $conn = blog_db();



    // Find topic with remaining uses

    $stmt = $conn->prepare(

        "SELECT id, topic_text FROM blog_topics

         WHERE use_count < max_uses AND is_active = 1

         ORDER BY use_count ASC, id ASC

         LIMIT 1"

    );

    $stmt->execute();

    $row = $stmt->get_result()->fetch_assoc();

    $stmt->close();



    if ($row) {

        return ['id' => (int) $row['id'], 'text' => (string) $row['topic_text']];

    }



    // All topics exhausted — reset and start the next cycle

    $conn->query("UPDATE blog_topics SET use_count = 0 WHERE is_active = 1");

    blog_log('All topics reached max_uses — resetting use counts for next cycle.');



    $stmt = $conn->prepare(

        "SELECT id, topic_text FROM blog_topics

         WHERE is_active = 1

         ORDER BY id ASC

         LIMIT 1"

    );

    $stmt->execute();

    $row = $stmt->get_result()->fetch_assoc();

    $stmt->close();



    if (!$row) {

        throw new RuntimeException('No active topics found in blog_topics. Add topics via the admin.');

    }



    return ['id' => (int) $row['id'], 'text' => (string) $row['topic_text']];

}



/**

 * Build the system + user prompt for a given topic.

 */

function build_prompt(string $topic): array

{

    $cta_url        = CTA_PRIMARY_URL;

    $cta_text       = CTA_PRIMARY_TEXT;

    $whatsapp_url   = CTA_WHATSAPP_URL;

    $whatsapp_text  = CTA_WHATSAPP_TEXT;



    $system = <<<SYSTEM

You are an expert content writer for EduTrack, a school management software platform built by ORIC Network in Ghana.

Your job is to write high-quality, SEO-optimised blog posts for school administrators, headteachers, bursars, and principals across Ghana and Africa.



WRITING RULES:

- Write for a real human audience of Ghanaian school administrators (not AI or developers).

- Use plain, professional English. No jargon. Friendly but authoritative tone.

- The article must be genuinely useful — practical tips, step-by-step guidance, real Ghana context (cedis, MoMo, GES, BECE, WASSCE, term structure, etc.).

- Target length: 1000–1500 words of body text.

- No markdown whatsoever — output clean HTML only.

- Use <h2> and <h3> for headings. Use <p>, <ul>, <ol>, <li>, <strong>, <em> for body content.

- No inline styles. No external images. No placeholder images.

- Include exactly 2 CTA blocks embedded naturally in the article (not at the very start):

    CTA 1 — after the second or third section:

    <div class="blog-cta-inline">

      <p><strong>Ready to simplify school management?</strong> EduTrack is built for schools in Ghana.</p>

      <a href="{$cta_url}" class="btn-cta">$cta_text</a>

      <a href="{$whatsapp_url}" class="btn-cta-outline" target="_blank" rel="noopener">$whatsapp_text</a>

    </div>

    CTA 2 — before the conclusion section:

    (same HTML block)

- End with a <section class="blog-faq"> containing exactly 5 FAQ items:

    <h2>Frequently Asked Questions</h2>

    <div class="faq-item"><h3>Question?</h3><p>Answer.</p></div>

    (repeat × 5)

- FAQs must be questions real school administrators in Ghana would actually Google.



OUTPUT FORMAT: Return a single JSON object with these exact keys:

{

  "title": "...",

  "meta_description": "...",

  "category": "...",

  "tags": ["tag1","tag2","tag3","tag4","tag5"],

  "reading_time_minutes": 5,

  "html_content": "...full article HTML..."

}



- title: compelling, SEO-optimised, includes the main keyword naturally (max 70 characters)

- meta_description: exactly 140–160 characters, includes main keyword, ends with a benefit

- category: one of: School Management | Fees & Payments | Attendance | Reports | Staff | Canteen | Parent Portal | Technology | Ghana Education

- tags: 5 relevant lowercase tags

- reading_time_minutes: integer (estimate 200 words/minute)

- html_content: the full article HTML — everything from the first <h2> to the closing FAQ </section>

SYSTEM;



    $user = "Write a blog post about the following topic for Ghanaian and African school administrators:\n\n{$topic}";



    return [

        ['role' => 'system', 'content' => $system],

        ['role' => 'user',   'content' => $user],

    ];

}



/**

 * Slugify a title for the URL.

 */

function slugify(string $text): string

{

    $text = strtolower(trim($text));

    $text = preg_replace('/[^a-z0-9\s-]/', '', $text);

    $text = preg_replace('/[\s-]+/', '-', $text);

    return trim($text, '-');

}



/**

 * Generate and save one blog post. Returns the new post slug on success.

 *

 * @param int|null $topic_id  Specific topic ID to use. Null = auto-pick next available.

 * @throws RuntimeException on Groq or DB failure

 */

function generate_and_save_post(?int $topic_id = null): string

{

    $conn = blog_db();



    if ($topic_id !== null) {

        $stmt = $conn->prepare(

            "SELECT id, topic_text FROM blog_topics WHERE id = ? AND is_active = 1 LIMIT 1"

        );

        $stmt->bind_param('i', $topic_id);

        $stmt->execute();

        $row = $stmt->get_result()->fetch_assoc();

        $stmt->close();

        if (!$row) {

            throw new RuntimeException("Topic #{$topic_id} not found or is inactive.");

        }

        $resolved_id = (int) $row['id'];

        $topic_text  = (string) $row['topic_text'];

    } else {

        $picked      = pick_next_topic();

        $resolved_id = $picked['id'];

        $topic_text  = $picked['text'];

    }



    blog_log("Generating post for topic: {$topic_text}");



    $messages = build_prompt($topic_text);

    $data     = groq_chat($messages, json_mode: true);



    // Validate required keys

    $required = ['title', 'meta_description', 'category', 'html_content'];

    foreach ($required as $k) {

        if (empty($data[$k])) {

            throw new RuntimeException("Groq response missing field: {$k}");

        }

    }



    $title     = trim($data['title']);

    $meta_desc = trim($data['meta_description']);

    $category  = trim($data['category']);

    $tags      = implode(',', array_map('trim', (array) ($data['tags'] ?? [])));

    $read_time = (int) ($data['reading_time_minutes'] ?? 5);

    $html      = $data['html_content'];

    $slug      = slugify($title);

    $excerpt   = strip_tags(substr($html, 0, 300));

    $excerpt   = rtrim(substr($excerpt, 0, strrpos($excerpt, ' ')), ' .,') . '...';



    // Ensure unique slug

    $base_slug = $slug;

    $i = 1;

    while (true) {

        $st = $conn->prepare('SELECT id FROM blog_posts WHERE slug = ? LIMIT 1');

        $st->bind_param('s', $slug);

        $st->execute();

        $st->store_result();

        $exists = $st->num_rows > 0;

        $st->close();

        if (!$exists) break;

        $slug = $base_slug . '-' . $i++;

    }



    $stmt = $conn->prepare(

        'INSERT INTO blog_posts

         (title, slug, meta_description, category, tags, excerpt, html_content,

          reading_time_minutes, status, topic_source, topic_id, published_at, created_at)

         VALUES (?, ?, ?, ?, ?, ?, ?, ?, "published", ?, ?, NOW(), NOW())'

    );

    $stmt->bind_param(

        'sssssssssi',

        $title, $slug, $meta_desc, $category, $tags, $excerpt, $html,

        $read_time, $topic_text, $resolved_id

    );



    if (!$stmt->execute()) {

        throw new RuntimeException('DB insert failed: ' . $stmt->error);

    }

    $stmt->close();



    // Increment topic use_count

    $st = $conn->prepare(

        'UPDATE blog_topics SET use_count = use_count + 1, last_used_at = NOW() WHERE id = ?'

    );

    $st->bind_param('i', $resolved_id);

    $st->execute();

    $st->close();



    blog_log("Saved post: [{$slug}] {$title}");



    ping_sitemap();



    return $slug;

}



/**

 * Ping Google and Bing with the updated sitemap URL.

 */

function ping_sitemap(): void

{

    $sitemap = urlencode(BLOG_BASE_URL . '/sitemap.php');

    $urls    = [

        'https://www.google.com/ping?sitemap=' . $sitemap,

        'https://www.bing.com/ping?sitemap='   . $sitemap,

    ];

    foreach ($urls as $url) {

        $ch = curl_init($url);

        curl_setopt_array($ch, [

            CURLOPT_RETURNTRANSFER => true,

            CURLOPT_TIMEOUT        => 10,

            CURLOPT_FOLLOWLOCATION => true,

            CURLOPT_SSL_VERIFYPEER => true,

        ]);

        curl_exec($ch);

        curl_close($ch);

    }

    blog_log('Sitemap pinged to Google and Bing.');

}



/**

 * Append a line to the cron log file.

 */

function blog_log(string $message): void

{

    $log_dir  = __DIR__ . '/../logs';

    $log_file = $log_dir . '/cron.log';

    if (!is_dir($log_dir)) {

        @mkdir($log_dir, 0755, true);

    }

    $line = '[' . date('Y-m-d H:i:s') . '] ' . $message . PHP_EOL;

    @file_put_contents($log_file, $line, FILE_APPEND | LOCK_EX);

}

