<?php
declare(strict_types=1);
// ==================================================
// Nuclear Fancy Pants Edition™ -- NUCLEAR+++
// File: /home/ploi/automarketer-ai.com/public/wp-content/plugins/automarketer-ai/includes/class-blog-announcer.php
// Description: Announces published blog posts to all active and connected social channels - NUCLEAR+++
// Last Edited: 2026-05-14
// ==================================================
namespace AutoMarketerAI;

if (!defined('ABSPATH')) {
    exit('No direct script access allowed.');
}

final class BlogAnnouncer
{
    // --------------------------------------------------
    // Channel registry -- add new channels here as they launch
    // Each entry: connection class => channel slug
    // --------------------------------------------------
    private const CHANNEL_MAP = [
        'AutoMarketerAI\\FacebookAuth'  => 'facebook',
        'AutoMarketerAI\\InstagramChannel' => 'instagram',
        'AutoMarketerAI\\XAuth'         => 'x',
        'AutoMarketerAI\\TikTokAuth'    => 'tiktok',
    ];

    // --------------------------------------------------
    // Per-channel prompt instructions
    // --------------------------------------------------
    private const CHANNEL_STYLE = [
        'facebook'  => 'Write a Facebook post announcing this blog article. Conversational and warm tone. 2-3 sentences. Include the article title naturally. End with the URL on its own line. No hashtags.',
        'instagram' => 'Write an Instagram caption announcing this blog article. Punchy opening line, then 3-4 lines of value. End with "Link in bio." then 6-8 relevant hashtags on a new line. No URL in the caption.',
        'x'         => 'Write a single tweet announcing this blog article. Under 220 characters leaving room for a URL. Punchy and direct. 1-2 hashtags max at the end.',
        'tiktok'    => 'Write a TikTok caption announcing this blog article. Hook-first, casual and energetic tone. 2-3 short lines. End with "Link in bio." and 3-5 hashtags.',
        'linkedin'  => 'Write a LinkedIn post announcing this blog article. Professional and insight-led. Open with a compelling observation or question. 3-4 sentences. End with the URL on its own line. No hashtags.',
    ];

    // --------------------------------------------------
    // Register hooks
    // --------------------------------------------------
    public static function register(): void
    {
        add_action('transition_post_status', [self::class, 'onPublish'], 10, 3);
    }

    // --------------------------------------------------
    // Hook handler -- fires when any post changes status
    // --------------------------------------------------
    public static function onPublish(string $new_status, string $old_status, \WP_Post $post): void
    {
        if ($new_status !== 'publish' || $old_status === 'publish') {
            return;
        }
        if ($post->post_type !== 'post' || $post->post_status !== 'publish') {
            return;
        }
        // Avoid auto-draft saves and revisions
        if (wp_is_post_revision($post->ID) || wp_is_post_autosave($post->ID)) {
            return;
        }
        self::announce($post);
    }

    // --------------------------------------------------
    // Generate and store announcements for all active channels
    // --------------------------------------------------
    private static function announce(\WP_Post $post): void
    {
        $provider = self::resolveAiProvider();
        if ($provider === null) {
            return;
        }

        $title   = get_the_title($post->ID);
        $excerpt = self::buildExcerpt($post);
        $url     = get_permalink($post->ID);

        $channels = self::getActiveConnectedChannels();
        if (empty($channels)) {
            return;
        }

        $status = (get_option('amai_approval_mode', 'review') === 'autopilot') ? 'approved' : 'draft';
        $batch  = 'blog-announce-' . $post->ID . '-' . gmdate('YmdHis');
        $now    = gmdate('Y-m-d');

        foreach ($channels as $channel) {
            $content = self::generateAnnouncement($provider, $channel, $title, $excerpt, $url);
            if ($content === '') {
                continue;
            }
            self::storeAnnouncement($channel, $content, $status, $batch, $now);
        }
    }

    // --------------------------------------------------
    // Generate announcement copy for a single channel
    // --------------------------------------------------
    private static function generateAnnouncement(
        array $provider,
        string $channel,
        string $title,
        string $excerpt,
        string $url
    ): string {
        $style = self::CHANNEL_STYLE[$channel] ?? self::CHANNEL_STYLE['facebook'];

        $business_name = (string) get_option('amai_business_name', get_bloginfo('name'));
        $prompt = $style . "\n\n"
            . 'Business: ' . $business_name . "\n"
            . 'Article title: ' . $title . "\n"
            . 'Article summary: ' . $excerpt . "\n"
            . 'Article URL: ' . $url . "\n\n"
            . 'Anti-hallucination rule: Do not invent features, services, or capabilities the business does not have. '
            . 'Only reference what is described above. Reply with only the post copy, nothing else.';

        $raw = $provider['instance']->generate_raw(
            $prompt,
            $provider['api_key'],
            $provider['model'],
            1024
        );

        if ($raw === '') {
            return '';
        }

        // Strip non-ASCII to avoid wpdb corruption
        return preg_replace('/[^\x00-\x7F]/', '', trim($raw));
    }

    // --------------------------------------------------
    // Insert the announcement into wp_amai_scheduled_posts
    // --------------------------------------------------
    private static function storeAnnouncement(
        string $channel,
        string $content,
        string $status,
        string $batch,
        string $date
    ): void {
        global $wpdb;
        $table     = $wpdb->prefix . 'amai_scheduled_posts';
        $day_index = (int) gmdate('N') - 1; // 0=Mon ... 6=Sun
        $post_time = BestTimeLearner::getBestTime($channel, $day_index);
        $page_id   = '';
        if ($channel === 'facebook' || $channel === 'instagram') {
            $conn    = FacebookAuth::getConnection();
            $page_id = (string) ($conn['page_id'] ?? '');
        }
        $sql = $wpdb->prepare(
            "INSERT INTO `{$table}`
                (tenant_id, channel, facebook_page_id, post_type, scheduled_date, scheduled_time,
                 status, post_content, generation_batch, created_at, updated_at)
             VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, UTC_TIMESTAMP(), UTC_TIMESTAMP())",
            'default',
            $channel,
            $page_id,
            'blog_announcement',
            $date,
            $post_time,
            $status,
            $content,
            $batch
        );
        $wpdb->query($sql);
    }

    // --------------------------------------------------
    // Return list of channel slugs that are active + connected
    // --------------------------------------------------
    private static function getActiveConnectedChannels(): array
    {
        $active_modules = (array) get_option('amai_active_modules', []);
        $channels       = [];

        foreach (self::CHANNEL_MAP as $class => $channel) {
            // Channel module must be active
            if (!in_array($channel, $active_modules, true)) {
                continue;
            }
            // Connection class must exist and report connected
            if (!class_exists($class)) {
                $file = AMAI_PLUGIN_DIR . 'includes/class-' . str_replace('_', '-', strtolower(
                    preg_replace('/([A-Z])/', '-$1', lcfirst(basename(str_replace('\\', '/', $class))))
                )) . '.php';
                if (is_file($file)) {
                    require_once $file;
                }
            }
            if (!class_exists($class)) {
                continue;
            }
            // Instagram: check via FacebookAuth::getInstagramAccountId()
            if ($channel === 'instagram') {
                if (FacebookAuth::getInstagramAccountId() === null) {
                    continue;
                }
                $channels[] = $channel;
                continue;
            }
            // All other channels: call getConnection()
            if (!method_exists($class, 'getConnection')) {
                continue;
            }
            $conn = $class::getConnection();
            if ($conn !== null) {
                $channels[] = $channel;
            }
        }

        return $channels;
    }

    // --------------------------------------------------
    // Resolve the active AI provider -- returns array or null
    // --------------------------------------------------
    private static function resolveAiProvider(): ?array
    {
        $active      = (array) get_option('amai_active_modules', []);
        $provider_id = null;
        foreach ($active as $module_id) {
            if (is_string($module_id) && str_starts_with($module_id, 'ai-')) {
                $provider_id = $module_id;
                break;
            }
        }
        if ($provider_id === null) {
            return null;
        }
        $module_file = AMAI_PLUGIN_DIR . 'modules/' . $provider_id . '.php';
        if (!is_file($module_file)) {
            return null;
        }
        require_once $module_file;
        $basename  = substr($provider_id, 3);
        $classname = 'AutoMarketerAI\\Modules\\' . ucfirst($basename);
        if (!class_exists($classname)) {
            return null;
        }
        $api_key = KeyVault::decrypt((string) get_option('amai_api_key_' . $provider_id, ''));
        if ($api_key === '') {
            return null;
        }
        $instance = new $classname();
        $model    = (string) get_option('amai_model_' . $provider_id, '');
        if ($model === '') {
            $model = $instance->get_default_model();
        }
        return [
            'instance' => $instance,
            'api_key'  => $api_key,
            'model'    => $model,
        ];
    }

    // --------------------------------------------------
    // Build a clean excerpt from post content
    // --------------------------------------------------
    private static function buildExcerpt(\WP_Post $post): string
    {
        if (!empty($post->post_excerpt)) {
            return wp_strip_all_tags($post->post_excerpt);
        }
        $content = wp_strip_all_tags($post->post_content);
        $content = preg_replace('/\s+/', ' ', $content);
        $content = trim((string) $content);
        if (mb_strlen($content) <= 300) {
            return $content;
        }
        $trimmed = mb_substr($content, 0, 300);
        $last    = mb_strrpos($trimmed, ' ');
        return ($last !== false ? mb_substr($trimmed, 0, $last) : $trimmed) . '...';
    }
}