<?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-generator.php
// Description: Blog post generator -- title modal, content generation, Unsplash image, Auto-Optimize trigger, image management panel - NUCLEAR+++
// Last Edited: 2026-05-01
// ==================================================

namespace AutoMarketerAI;

defined('ABSPATH') || exit;

class BlogGenerator
{
    public static function register(): void
    {
        add_action('admin_enqueue_scripts',               [self::class, 'enqueueAssets']);
        add_action('wp_ajax_amai_blog_gen_titles',        [self::class, 'handleGenerateTitles']);
        add_action('wp_ajax_amai_blog_gen_create',        [self::class, 'handleCreatePost']);
        add_action('wp_ajax_amai_blog_gen_content',       [self::class, 'handleGenerateContent']);
        add_action('wp_ajax_amai_blog_img_unsplash',      [self::class, 'handleUnsplashSearch']);
        add_action('wp_ajax_amai_blog_img_unsplash_set',  [self::class, 'handleUnsplashSet']);
        add_action('wp_ajax_amai_blog_img_ai_generate',   [self::class, 'handleAiImageGenerate']);
        add_action('wp_ajax_amai_blog_img_remove',        [self::class, 'handleImageRemove']);
        add_action('edit_form_after_title',               [self::class, 'renderButton']);
        add_action('admin_footer',                        [self::class, 'renderModal']);
        add_action('add_meta_boxes',                      [self::class, 'registerImageMetaBox']);
    }

    // --------------------------------------------------
    // Enqueue assets on post screens only
    // --------------------------------------------------
    public static function enqueueAssets(string $hook): void
    {
        if ($hook !== 'post.php' && $hook !== 'post-new.php') {
            return;
        }
        $screen = get_current_screen();
        if (!$screen instanceof \WP_Screen || $screen->post_type !== 'post') {
            return;
        }
        wp_enqueue_style(
            'amai-blog-generator',
            AMAI_PLUGIN_URL . 'assets/css/blog-generator.css',
            [],
            (string) filemtime(AMAI_PLUGIN_DIR . 'assets/css/blog-generator.css')
        );
        wp_enqueue_script(
            'amai-blog-generator',
            AMAI_PLUGIN_URL . 'assets/js/amai-blog-generator.js',
            [],
            (string) filemtime(AMAI_PLUGIN_DIR . 'assets/js/amai-blog-generator.js'),
            true
        );

        $post_id         = (int) (get_the_ID() ?: 0);
        $focus_keyword   = '';
        $default_prompt  = '';
        $business_name   = get_bloginfo('name');

        if ($post_id > 0) {
            $focus_keyword  = class_exists('\AutoMarketerAI\SeoData') ? (string) SeoData::get($post_id, 'focus_keyword') : '';
            $post           = get_post($post_id);
            $title          = $post instanceof \WP_Post ? $post->post_title : '';
            $default_prompt = 'A high-quality professional photo for a blog post titled: ' . $title
                . '. Business: ' . $business_name . '. Photorealistic, suitable for a business blog.';
        }

        wp_localize_script('amai-blog-generator', 'amaiGen', [
            'ajaxurl'        => admin_url('admin-ajax.php'),
            'nonce'          => wp_create_nonce('amai_blog_gen'),
            'postId'         => $post_id,
            'autoWrite'      => isset($_GET['amai_gen']) && $_GET['amai_gen'] === '1' ? '1' : '0',
            'autoOpt'        => isset($_GET['amai_opt']) && $_GET['amai_opt'] === '1' ? '1' : '0',
            'isGenerated'    => get_post_meta($post_id, '_amai_blog_generated', true) === '1' ? '1' : '0',
            'focusKeyword'   => $focus_keyword,
            'defaultPrompt'  => $default_prompt,
        ]);
    }

    // --------------------------------------------------
    // Register image management meta box
    // --------------------------------------------------
    public static function registerImageMetaBox(): void
    {
        $screen = get_current_screen();
        if (!$screen instanceof \WP_Screen || $screen->post_type !== 'post') {
            return;
        }
        $post_id = (int) (get_the_ID() ?: 0);
        if ($post_id <= 0 || get_post_meta($post_id, '_amai_blog_generated', true) !== '1') {
            return;
        }
        add_meta_box(
            'amai-img-manager',
            'Featured Image Options',
            [self::class, 'renderImageMetaBox'],
            'post',
            'side',
            'low'
        );
    }

    // --------------------------------------------------
    // Render image management meta box content
    // --------------------------------------------------
    public static function renderImageMetaBox(\WP_Post $post): void
    {
        $focus_keyword  = class_exists('\AutoMarketerAI\SeoData') ? (string) SeoData::get($post->ID, 'focus_keyword') : '';
        $default_search = $focus_keyword !== '' ? $focus_keyword : $post->post_title;
        $default_prompt = 'A high-quality professional photo for a blog post titled: ' . $post->post_title
            . '. Business: ' . get_bloginfo('name') . '. Photorealistic, suitable for a business blog.';
        ?>
        <div id="amai-img-manager" class="amai-img-manager">
            <div class="amai-img-tabs">
                <button type="button" class="amai-img-tab active" data-tab="unsplash">Unsplash</button>
                <button type="button" class="amai-img-tab" data-tab="ai">AI Generate</button>
                <button type="button" class="amai-img-tab amai-img-tab--remove" data-tab="remove">Remove</button>
            </div>

            <div id="amai-img-panel-unsplash" class="amai-img-panel active">
                <div class="amai-img-search-row">
                    <input
                        type="text"
                        id="amai-img-unsplash-query"
                        class="amai-img-input"
                        value="<?php echo esc_attr($default_search); ?>"
                        placeholder="Search photos..."
                    />
                    <button type="button" id="amai-img-unsplash-btn" class="amai-img-btn-primary">Search</button>
                </div>
                <div id="amai-img-unsplash-grid" class="amai-img-grid"></div>
                <div id="amai-img-unsplash-loading" class="amai-img-loading" style="display:none;">
                    <div class="amai-img-spinner"></div>
                    <span>Searching photos...</span>
                </div>
                <div id="amai-img-unsplash-error" class="amai-img-error" style="display:none;"></div>
            </div>

            <div id="amai-img-panel-ai" class="amai-img-panel">
                <textarea
                    id="amai-img-ai-prompt"
                    class="amai-img-textarea"
                    rows="3"
                    placeholder="Describe the image..."
                ><?php echo esc_textarea($default_prompt); ?></textarea>
                <button type="button" id="amai-img-ai-btn" class="amai-img-btn-primary">Generate Image</button>
                <div id="amai-img-ai-loading" class="amai-img-loading" style="display:none;">
                    <div class="amai-img-spinner"></div>
                    <span>Generating image...</span>
                </div>
                <div id="amai-img-ai-error" class="amai-img-error" style="display:none;"></div>
            </div>

            <div id="amai-img-panel-remove" class="amai-img-panel">
                <p class="amai-img-remove-desc">This removes the featured image from the post. The file stays in your media library.</p>
                <button type="button" id="amai-img-remove-btn" class="amai-img-btn-danger">Remove Featured Image</button>
                <div id="amai-img-remove-error" class="amai-img-error" style="display:none;"></div>
            </div>

            <div id="amai-img-success" class="amai-img-success" style="display:none;">Image updated. Refresh to preview.</div>
        </div>
        <?php
    }

    // --------------------------------------------------
    // Render "Write with AI" button above title field
    // --------------------------------------------------
    public static function renderButton(\WP_Post $post): void
    {
        if ($post->post_type !== 'post') {
            return;
        }
        if (trim($post->post_title) !== '') {
            return;
        }
        echo '<div class="amai-gen-btn-wrap">' .
             '<button type="button" id="amai-gen-open-btn" class="amai-gen-trigger-btn">' .
             '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/></svg>' .
             ' Write with AI</button>' .
             '<span class="amai-gen-start-here">' .
             '<svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg"><line x1="24" y1="8" x2="6" y2="8" stroke="#D97757" stroke-width="2.5" stroke-linecap="round"/><polyline points="12,2 4,8 12,14" fill="none" stroke="#D97757" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>' .
             ' <strong>Start here</strong></span>' .
             '</div>';
    }

    // --------------------------------------------------
    // Render modal shell and writing overlay in admin footer
    // --------------------------------------------------
    public static function renderModal(): void
    {
        $screen = get_current_screen();
        if (!$screen instanceof \WP_Screen || !in_array($screen->base, ['post'], true) || $screen->post_type !== 'post') {
            return;
        }
        ?>
        <div id="amai-gen-modal" class="amai-gen-modal">
            <div class="amai-gen-wrap">
                <div class="amai-gen-header">
                    <div>
                        <div class="amai-gen-eyebrow">AutoMarketer AI</div>
                        <div class="amai-gen-title">Write a New Blog Post</div>
                    </div>
                    <button type="button" class="amai-gen-close" id="amai-gen-close">&times;</button>
                </div>
                <div class="amai-gen-body">
                    <div id="amai-gen-step-titles">
                        <p class="amai-gen-desc">Choose a title and we'll write the full post, add an image, and optimize everything automatically.</p>
                        <div id="amai-gen-titles-list" class="amai-gen-titles-list"></div>
                        <div id="amai-gen-loading" class="amai-gen-loading" style="display:none;">
                            <div class="amai-gen-spinner"></div>
                            <span id="amai-gen-loading-msg">Generating title ideas...</span>
                        </div>
                        <div id="amai-gen-error" class="amai-gen-error" style="display:none;"></div>
                    </div>
                </div>
                <div class="amai-gen-footer">
                    <button type="button" id="amai-gen-refresh-btn" class="amai-gen-btn-secondary" style="display:none;">Generate New Titles</button>
                    <button type="button" id="amai-gen-write-btn" class="amai-gen-btn-primary" disabled>Write with AI</button>
                </div>
            </div>
        </div>
        <div id="amai-gen-overlay" class="amai-gen-overlay" style="display:none;">
            <div class="amai-gen-overlay-inner">
                <div class="amai-gen-spinner amai-gen-spinner--lg"></div>
                <div class="amai-gen-overlay-title">Writing your post...</div>
                <div id="amai-gen-overlay-msg" class="amai-gen-overlay-msg">Generating content</div>
            </div>
        </div>
        <?php
    }

    // --------------------------------------------------
    // AJAX -- generate 5 title options
    // --------------------------------------------------
    public static function handleGenerateTitles(): void
    {
        check_ajax_referer('amai_blog_gen', 'nonce');
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Unauthorized.'], 403);
        }

        $profile           = (new BusinessProfile())->get();
        $business_name     = get_bloginfo('name');
        $business_category = '';
        $context_parts     = [];

        if (is_array($profile)) {
            $cat_map           = BusinessProfile::BUSINESS_CATEGORIES;
            $cat_key           = (string) ($profile['business_category'] ?? '');
            $business_category = $cat_map[$cat_key] ?? $cat_key;
            if (!empty($profile['differentiator'])) {
                $context_parts[] = 'What makes us different: ' . $profile['differentiator'];
            }
            if (!empty($profile['values_and_causes'])) {
                $context_parts[] = 'Our values: ' . $profile['values_and_causes'];
            }
            if (!empty($profile['customer_descriptor'])) {
                $context_parts[] = 'Our customers: ' . $profile['customer_descriptor'];
            }
            if (($profile['website_status'] ?? '') === 'has_website' && !empty($profile['website_url'])) {
                $url      = esc_url_raw($profile['website_url']);
                $response = wp_remote_get($url, ['timeout' => 8, 'sslverify' => false]);
                if (!is_wp_error($response)) {
                    $body = wp_remote_retrieve_body($response);
                    $text = wp_strip_all_tags($body);
                    $text = preg_replace('/\s+/', ' ', $text) ?? '';
                    $text = trim(mb_substr($text, 0, 800));
                    if ($text !== '') {
                        $context_parts[] = 'Website content: ' . $text;
                    }
                }
            }
        }

        global $wpdb;
        $table = $wpdb->prefix . 'amai_scheduled_posts';
        $posts = $wpdb->get_col(
            "SELECT post_content FROM `{$table}` WHERE status = 'approved' ORDER BY created_at DESC LIMIT 5"
        );
        if (!empty($posts)) {
            $context_parts[] = 'Recent social posts: ' . implode(' | ', array_map('wp_strip_all_tags', $posts));
        }

        $context = implode("\n", $context_parts);

        // Append previously shown titles so AI avoids repeating them
        $shown_titles = (array) get_transient('amai_blog_shown_titles');
        if (!empty($shown_titles)) {
            $context .= "\n\nDo not suggest these titles or close variations of them:\n- " . implode("\n- ", $shown_titles);
        }
        // Append published post titles so AI knows what is already written
        $published = get_posts(['post_type' => 'post', 'post_status' => 'publish', 'numberposts' => 10, 'fields' => 'ids']);
        if (!empty($published)) {
            $pub_titles = array_map('get_the_title', $published);
            $context .= "\n\nAlready published posts - do not suggest similar titles:\n- " . implode("\n- ", $pub_titles);
        }

        // Append existing focus keywords so AI never targets an already-used keyword
        if (!empty($published)) {
            $used_keywords = get_posts([
                'post_type'   => 'post',
                'post_status' => 'publish',
                'numberposts' => -1,
                'fields'      => 'ids',
            ]);
            $kw_list = [];
            foreach ($used_keywords as $kw_post_id) {
                $kw = trim((string) get_post_meta((int) $kw_post_id, '_amai_seo_focus_keyword', true));
                if ($kw !== '') {
                    $kw_list[] = $kw;
                }
            }
            if (!empty($kw_list)) {
                $context .= "\n\nThese focus keywords are already in use on other posts - each new title must target a completely different keyword, do not overlap with any of these:\n- " . implode("\n- ", $kw_list);
            }
        }
        $titles = self::callCoreGenerateTitles($business_name, $business_category, $context);
        if ($titles === null) {
            wp_send_json_error(['message' => 'Title generation failed. Please try again.'], 502);
        }

        // Store shown titles in transient (keep last 20, expires in 2 hours)
        $new_titles = array_map(function($t) { return is_array($t) ? ($t['title'] ?? '') : (string) $t; }, $titles);
        $new_titles = array_filter($new_titles);
        $all_shown  = array_merge($shown_titles, array_values($new_titles));
        $all_shown  = array_values(array_unique(array_slice($all_shown, -20)));
        set_transient('amai_blog_shown_titles', $all_shown, 2 * HOUR_IN_SECONDS);
        wp_send_json_success(['titles' => $titles]);
    }

    // --------------------------------------------------
    // AJAX -- create draft post with chosen title
    // --------------------------------------------------
    public static function handleCreatePost(): void
    {
        check_ajax_referer('amai_blog_gen', 'nonce');
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Unauthorized.'], 403);
        }

        $title = sanitize_text_field(wp_unslash((string) ($_POST['title'] ?? '')));
        if ($title === '') {
            wp_send_json_error(['message' => 'Missing title.'], 400);
        }

        $ai_write = (string) ($_POST['ai_write'] ?? '0');

        $post_id = wp_insert_post([
            'post_title'  => $title,
            'post_status' => 'draft',
            'post_type'   => 'post',
            'post_author' => get_current_user_id(),
        ], true);

        if (is_wp_error($post_id)) {
            wp_send_json_error(['message' => 'Failed to create post.'], 500);
        }

        $edit_url = get_edit_post_link($post_id, 'raw');
        if ($ai_write === '1') {
            $edit_url = add_query_arg('amai_gen', '1', $edit_url);
        }

        wp_send_json_success(['post_id' => $post_id, 'edit_url' => $edit_url]);
    }

    // --------------------------------------------------
    // AJAX -- generate full post content, set featured image
    // --------------------------------------------------
    public static function handleGenerateContent(): void
    {
        check_ajax_referer('amai_blog_gen', 'nonce');
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Unauthorized.'], 403);
        }

        $post_id = (int) ($_POST['post_id'] ?? 0);
        if ($post_id <= 0) {
            wp_send_json_error(['message' => 'Missing post_id.'], 400);
        }

        $post = get_post($post_id);
        if (!$post instanceof \WP_Post || $post->post_type !== 'post') {
            wp_send_json_error(['message' => 'Invalid post.'], 400);
        }

        $title             = $post->post_title;
        $profile           = (new BusinessProfile())->get();
        $business_name     = get_bloginfo('name');
        $business_category = '';
        $context_parts     = [];

        if (is_array($profile)) {
            $cat_map           = BusinessProfile::BUSINESS_CATEGORIES;
            $cat_key           = (string) ($profile['business_category'] ?? '');
            $business_category = $cat_map[$cat_key] ?? $cat_key;
            if (!empty($profile['differentiator'])) {
                $context_parts[] = 'What makes us different: ' . $profile['differentiator'];
            }
            if (!empty($profile['values_and_causes'])) {
                $context_parts[] = 'Our values: ' . $profile['values_and_causes'];
            }
            if (!empty($profile['customer_descriptor'])) {
                $context_parts[] = 'Our customers: ' . $profile['customer_descriptor'];
            }
            if (($profile['website_status'] ?? '') === 'has_website' && !empty($profile['website_url'])) {
                $url      = esc_url_raw($profile['website_url']);
                $response = wp_remote_get($url, ['timeout' => 8, 'sslverify' => false]);
                if (!is_wp_error($response)) {
                    $body = wp_remote_retrieve_body($response);
                    $text = wp_strip_all_tags($body);
                    $text = preg_replace('/\s+/', ' ', $text) ?? '';
                    $text = trim(mb_substr($text, 0, 800));
                    if ($text !== '') {
                        $context_parts[] = 'Website content: ' . $text;
                    }
                }
            }
        }

        $context = implode("\n", $context_parts);

        $content = self::callCoreGenerateContent($title, $business_name, $business_category, $context);
        if ($content === null) {
            wp_send_json_error(['message' => 'Content generation failed. Please try again.'], 502);
        }

        $result = wp_update_post([
            'ID'           => $post_id,
            'post_content' => $content,
            'post_status'  => 'draft',
        ], true);

        if (is_wp_error($result)) {
            wp_send_json_error(['message' => 'Failed to save content.'], 500);
        }

        // Mark post as AI-generated to enable image manager meta box
        update_post_meta($post_id, '_amai_blog_generated', '1');

        // Run SEO analysis to extract and persist focus keyword before image fetch
        if (class_exists('\AutoMarketerAI\SeoAnalyzer')) {
            SeoAnalyzer::analyze($post_id);
        }

        // Fetch featured image -- source determined by amai_blog_image_source setting.
        // AI mode: try AI image provider first, fall back to Unsplash on failure.
        // Unsplash mode: try Unsplash first, fall back to AI on failure.
        $image_source  = (string) get_option('amai_blog_image_source', 'unsplash');
        $attachment_id = 0;

        // Resolve active image provider ID if any
        $active          = (array) get_option('amai_active_modules', []);
        $img_provider_id = null;
        foreach ($active as $module_id) {
            if (is_string($module_id) && str_starts_with($module_id, 'img-')) {
                $img_provider_id = $module_id;
                break;
            }
        }

        $try_ai = static function () use ($img_provider_id, $title, $business_category, $post_id, &$attachment_id): void {
            if ($img_provider_id === null) { return; }
            $module_file = AMAI_PLUGIN_DIR . '/modules/' . $img_provider_id . '.php';
            if (!is_file($module_file)) { return; }
            require_once $module_file;
            $parts     = array_map('ucfirst', explode('-', $img_provider_id));
            $classname = 'AutoMarketerAI\\Modules\\' . implode('', $parts);
            if (!class_exists($classname)) { return; }
            $api_key = KeyVault::decrypt((string) get_option('amai_api_key_' . $img_provider_id, ''));
            if ($api_key === '') { return; }
            $prompt     = 'A high-quality professional photo for a blog post titled: ' . $title . '. Business context: ' . $business_category . '. Photorealistic, suitable for a business blog.';
            $provider   = new $classname();
            $gen_result = $provider->generate_image($prompt, $api_key);
            if ($gen_result !== null && $gen_result !== '') {
                $attach_id = is_numeric($gen_result) ? (int) $gen_result : (int) attachment_url_to_postid($gen_result);
                if ($attach_id > 0) {
                    set_post_thumbnail($post_id, $attach_id);
                    $attachment_id = $attach_id;
                }
            }
        };

        $try_unsplash = static function () use ($title, $post_id, &$attachment_id): void {
            if (!class_exists('\AutoMarketerAI\Unsplash') || !defined('UNSPLASH_ACCESS_KEY') || UNSPLASH_ACCESS_KEY === '') { return; }
            $focus_keyword = class_exists('\AutoMarketerAI\SeoData') ? (string) SeoData::get($post_id, 'focus_keyword') : '';
            $photo = null;
            if ($focus_keyword !== '') { $photo = Unsplash::search($focus_keyword); }
            if ($photo === null) { $photo = Unsplash::search($title); }
            if ($photo !== null && !empty($photo['url']) && !empty($photo['photographer'])) {
                $attach_id = Unsplash::downloadToMedia($photo['url'], $photo['photographer'], $post_id, (string) ($photo['profile_url'] ?? ''));
                if ($attach_id > 0) {
                    set_post_thumbnail($post_id, $attach_id);
                    $attachment_id = $attach_id;
                }
            }
        };

        if ($image_source === 'ai') {
            $try_ai();
            if ($attachment_id === 0) { $try_unsplash(); }
        } else {
            $try_unsplash();
            if ($attachment_id === 0) { $try_ai(); }
        }

        wp_send_json_success([
            'post_id'   => $post_id,
            'has_image' => $attachment_id > 0,
        ]);
    }

    // --------------------------------------------------
    // AJAX -- search Unsplash and return photo grid data
    // --------------------------------------------------
    public static function handleUnsplashSearch(): void
    {
        check_ajax_referer('amai_blog_gen', 'nonce');
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Unauthorized.'], 403);
        }

        if (!class_exists('\AutoMarketerAI\Unsplash') || !defined('UNSPLASH_ACCESS_KEY') || UNSPLASH_ACCESS_KEY === '') {
            wp_send_json_error(['message' => 'Unsplash is not configured.'], 422);
        }

        $query = sanitize_text_field(wp_unslash((string) ($_POST['query'] ?? '')));
        if ($query === '') {
            wp_send_json_error(['message' => 'Missing search query.'], 400);
        }

        $photos = Unsplash::searchMultiple($query, 6);
        if (empty($photos)) {
            wp_send_json_error(['message' => 'No photos found. Try a different search term.'], 404);
        }

        $results = [];
        foreach ($photos as $photo) {
            if (empty($photo['url']) || empty($photo['photographer'])) {
                continue;
            }
            $results[] = [
                'url'         => $photo['url'],
                'thumb'       => $photo['thumb'] ?? $photo['url'],
                'photographer' => $photo['photographer'],
                'profile_url' => $photo['profile_url'] ?? '',
            ];
        }

        if (empty($results)) {
            wp_send_json_error(['message' => 'No usable photos found.'], 404);
        }

        wp_send_json_success(['photos' => $results]);
    }

    // --------------------------------------------------
    // AJAX -- download selected Unsplash photo and set as thumbnail
    // --------------------------------------------------
    public static function handleUnsplashSet(): void
    {
        check_ajax_referer('amai_blog_gen', 'nonce');
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Unauthorized.'], 403);
        }

        $post_id      = (int) ($_POST['post_id'] ?? 0);
        $url          = esc_url_raw(wp_unslash((string) ($_POST['url'] ?? '')));
        $photographer = sanitize_text_field(wp_unslash((string) ($_POST['photographer'] ?? '')));
        $profile_url  = esc_url_raw(wp_unslash((string) ($_POST['profile_url'] ?? '')));

        if ($post_id <= 0 || $url === '' || $photographer === '') {
            wp_send_json_error(['message' => 'Missing required fields.'], 400);
        }

        $post = get_post($post_id);
        if (!$post instanceof \WP_Post) {
            wp_send_json_error(['message' => 'Invalid post.'], 400);
        }

        if (!class_exists('\AutoMarketerAI\Unsplash')) {
            wp_send_json_error(['message' => 'Unsplash class not available.'], 422);
        }

        $attachment_id = Unsplash::downloadToMedia($url, $photographer, $post_id, $profile_url);
        if ($attachment_id <= 0) {
            wp_send_json_error(['message' => 'Failed to download photo.'], 500);
        }

        set_post_thumbnail($post_id, $attachment_id);

        wp_send_json_success(['attachment_id' => $attachment_id]);
    }

    // --------------------------------------------------
    // AJAX -- generate AI image and set as thumbnail
    // --------------------------------------------------
    public static function handleAiImageGenerate(): void
    {
        check_ajax_referer('amai_blog_gen', 'nonce');
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Unauthorized.'], 403);
        }

        $post_id = (int) ($_POST['post_id'] ?? 0);
        $prompt  = sanitize_textarea_field(wp_unslash((string) ($_POST['prompt'] ?? '')));

        if ($post_id <= 0) {
            wp_send_json_error(['message' => 'Missing post_id.'], 400);
        }
        if ($prompt === '') {
            wp_send_json_error(['message' => 'Missing prompt.'], 400);
        }

        $post = get_post($post_id);
        if (!$post instanceof \WP_Post) {
            wp_send_json_error(['message' => 'Invalid post.'], 400);
        }

        $active          = (array) get_option('amai_active_modules', []);
        $img_provider_id = null;
        foreach ($active as $module_id) {
            if (is_string($module_id) && str_starts_with($module_id, 'img-')) {
                $img_provider_id = $module_id;
                break;
            }
        }

        if ($img_provider_id === null) {
            wp_send_json_error(['message' => 'No AI image provider is active.'], 422);
        }

        $module_file = AMAI_PLUGIN_DIR . '/modules/' . $img_provider_id . '.php';
        if (!is_file($module_file)) {
            wp_send_json_error(['message' => 'Image provider module not found.'], 422);
        }

        require_once $module_file;
        $parts     = array_map('ucfirst', explode('-', $img_provider_id));
        $classname = 'AutoMarketerAI\\Modules\\' . implode('', $parts);
        if (!class_exists($classname)) {
            wp_send_json_error(['message' => 'Image provider class not found.'], 422);
        }

        $api_key = KeyVault::decrypt((string) get_option('amai_api_key_' . $img_provider_id, ''));
        if ($api_key === '') {
            wp_send_json_error(['message' => 'Image provider API key not configured.'], 422);
        }

        $provider = new $classname();
        $gen_result = $provider->generate_image($prompt, $api_key);
        if ($gen_result === null || $gen_result === '') {
            wp_send_json_error(['message' => 'Image generation failed. Please try again.'], 200);
        }
        // generate_image returns a URL string -- resolve to attachment ID
        $attach_id = is_numeric($gen_result) ? (int) $gen_result : attachment_url_to_postid($gen_result);
        if ($attach_id <= 0) {
            wp_send_json_error(['message' => 'Image saved but could not be attached. Please try again.'], 200);
        }
        set_post_thumbnail($post_id, $attach_id);
        wp_send_json_success(['attachment_id' => $attach_id]);
    }

    // --------------------------------------------------
    // AJAX -- remove featured image (thumbnail only, keep attachment)
    // --------------------------------------------------
    public static function handleImageRemove(): void
    {
        check_ajax_referer('amai_blog_gen', 'nonce');
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'Unauthorized.'], 403);
        }

        $post_id = (int) ($_POST['post_id'] ?? 0);
        if ($post_id <= 0) {
            wp_send_json_error(['message' => 'Missing post_id.'], 400);
        }

        $post = get_post($post_id);
        if (!$post instanceof \WP_Post) {
            wp_send_json_error(['message' => 'Invalid post.'], 400);
        }

        delete_post_thumbnail($post_id);

        wp_send_json_success(['removed' => true]);
    }

    // --------------------------------------------------
    // Call Core /api/seo/generate-blog-titles
    // --------------------------------------------------
    public static function callCoreGenerateTitles(string $business_name, string $business_category, string $context): ?array
    {
        if (!defined('AMAI_HMAC_SECRET') || AMAI_HMAC_SECRET === '') {
            return null;
        }
        if (!defined('AMAI_CORE_URL') || AMAI_CORE_URL === '') {
            return null;
        }

        $method    = 'POST';
        $path      = '/api/seo/generate-blog-titles';
        $url       = rtrim(AMAI_CORE_URL, '/') . $path;
        $timestamp = (string) time();
        $nonce     = bin2hex(random_bytes(16));
        $tenant    = amai_tenant_id();
        $key_id    = 'WP_PROXY';

        $payload  = [
            'business_name'     => $business_name,
            'business_category' => $business_category,
            'context'           => $context,
        ];
        $body      = (string) json_encode($payload);
        $raw_secret = (string) get_option('amai_tenant_hmac_secret', '');
        if ($raw_secret === '') {
            return null;
        }
        $secret    = hex2bin($raw_secret);
        $body_b64  = base64_encode(hash('sha256', $body, true));
        $canonical = implode('|', [$method, $path, $timestamp, $nonce, $tenant, $key_id, $body_b64]);
        $signature = rtrim(base64_encode(hash_hmac('sha256', $canonical, $secret, true)), "\n");

        $response = wp_remote_post($url, [
            'timeout' => 30,
            'headers' => [
                'Content-Type'       => 'application/json',
                'X-Amai-Tenant'      => $tenant,
                'X-Amai-Key-Id'      => $key_id,
                'X-Amai-Timestamp'   => $timestamp,
                'X-Amai-Nonce'       => $nonce,
                'X-Amai-Body-SHA256' => $body_b64,
                'X-Amai-Signature'   => $signature,
            ],
            'body' => $body,
        ]);

        if (is_wp_error($response)) {
            error_log('[AutoMarketer AI] BlogGenerator::callCoreGenerateTitles - wp_error: ' . $response->get_error_message());
            return null;
        }

        $code = (int) wp_remote_retrieve_response_code($response);
        $data = json_decode(wp_remote_retrieve_body($response), true);

        if ($code !== 200 || !is_array($data) || empty($data['titles'])) {
            error_log('[AutoMarketer AI] BlogGenerator::callCoreGenerateTitles - bad response ' . $code);
            return null;
        }

        return (array) $data['titles'];
    }

    // --------------------------------------------------
    // Call Core /api/seo/generate-blog-content
    // --------------------------------------------------
    public static function callCoreGenerateContent(
        string $title,
        string $business_name,
        string $business_category,
        string $context
    ): ?string {
        if (!defined('AMAI_HMAC_SECRET') || AMAI_HMAC_SECRET === '') {
            return null;
        }
        if (!defined('AMAI_CORE_URL') || AMAI_CORE_URL === '') {
            return null;
        }

        $method    = 'POST';
        $path      = '/api/seo/generate-blog-content';
        $url       = rtrim(AMAI_CORE_URL, '/') . $path;
        $timestamp = (string) time();
        $nonce     = bin2hex(random_bytes(16));
        $tenant    = amai_tenant_id();
        $key_id    = 'WP_PROXY';

        $payload  = [
            'title'             => $title,
            'business_name'     => $business_name,
            'business_category' => $business_category,
            'context'           => $context,
        ];
        $body      = (string) json_encode($payload);
        $raw_secret = (string) get_option('amai_tenant_hmac_secret', '');
        if ($raw_secret === '') {
            return null;
        }
        $secret    = hex2bin($raw_secret);
        $body_b64  = base64_encode(hash('sha256', $body, true));
        $canonical = implode('|', [$method, $path, $timestamp, $nonce, $tenant, $key_id, $body_b64]);
        $signature = rtrim(base64_encode(hash_hmac('sha256', $canonical, $secret, true)), "\n");

        $response = wp_remote_post($url, [
            'timeout' => 60,
            'headers' => [
                'Content-Type'       => 'application/json',
                'X-Amai-Tenant'      => $tenant,
                'X-Amai-Key-Id'      => $key_id,
                'X-Amai-Timestamp'   => $timestamp,
                'X-Amai-Nonce'       => $nonce,
                'X-Amai-Body-SHA256' => $body_b64,
                'X-Amai-Signature'   => $signature,
            ],
            'body' => $body,
        ]);

        if (is_wp_error($response)) {
            error_log('[AutoMarketer AI] BlogGenerator::callCoreGenerateContent - wp_error: ' . $response->get_error_message());
            return null;
        }

        $code = (int) wp_remote_retrieve_response_code($response);
        $data = json_decode(wp_remote_retrieve_body($response), true);

        if ($code !== 200 || !is_array($data) || empty($data['content'])) {
            error_log('[AutoMarketer AI] BlogGenerator::callCoreGenerateContent - bad response ' . $code);
            return null;
        }

        return (string) $data['content'];
    }

    // --------------------------------------------------
    // Static aliases for BlogScheduler
    // --------------------------------------------------
    public static function callCoreGenerateTitlesStatic(string $business_name, string $business_category, string $context): ?array
    {
        return self::callCoreGenerateTitles($business_name, $business_category, $context);
    }

    public static function callCoreGenerateContentStatic(string $title, string $business_name, string $business_category, string $context): ?string
    {
        return self::callCoreGenerateContent($title, $business_name, $business_category, $context);
    }
}