<?php

namespace AtlasAiDev\Awfah\Abilities;

use AtlasAiDev\Awfah\Service\AI_Provider_Manager;
use AtlasAiDev\Awfah\Service\Logger;
use WP_Post;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Content_Steward_Abilities {

    public static function get_abilities(): array {
        return [
            [
                'id'          => 'awfah-content/analyze-post',
                'module'      => 'content_steward',
                'label'       => __( 'Analyze Post Content', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Summarize a post and return readability and improvement suggestions.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'required'   => [ 'post_id' ],
                    'properties' => [
                        'post_id' => [
                            'type'        => 'integer',
                            'description' => __( 'Post ID to analyze.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'summary'       => [
                            'type'        => 'string',
                            'description' => __( 'Short summary of the post.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'reading_level' => [
                            'type'        => 'string',
                            'description' => __( 'Approximate reading level (e.g. Beginner, Intermediate).', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'suggestions'   => [
                            'type'        => 'string',
                            'description' => __( 'Natural language suggestions to improve the content.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/analyze/{post_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
            [
                'id'          => 'awfah-content/generate-feature-image',
                'module'      => 'content_steward',
                'label'       => __( 'Generate Featured Image', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Generate an AI-powered featured image from post context, upload it to the media library, and return the attachment details.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'required'   => [ 'post_id' ],
                    'properties' => [
                        'post_id' => [
                            'type'        => 'integer',
                            'description' => __( 'Post ID to generate featured image for.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'prompt' => [
                            'type'        => 'string',
                            'description' => __( 'Optional custom image generation prompt. If not provided, one is generated from post context.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'provider' => [
                            'type'        => 'string',
                            'description' => __( 'AI provider preference: auto, openai, google.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'style' => [
                            'type'        => 'string',
                            'description' => __( 'Image style: photo-realistic, illustration, abstract, minimalist, watercolor.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'image_id' => [
                            'type'        => 'integer',
                            'description' => __( 'WordPress attachment ID of the uploaded image.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'image_url' => [
                            'type'        => 'string',
                            'description' => __( 'URL of the uploaded image.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'prompt_used' => [
                            'type'        => 'string',
                            'description' => __( 'The prompt that was used to generate the image.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'alt_text' => [
                            'type'        => 'string',
                            'description' => __( 'Generated alt text for the image.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/feature-image/{post_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
            [
                'id'          => 'awfah-content/generate-excerpt',
                'module'      => 'content_steward',
                'label'       => __( 'Generate Excerpt', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Create a concise, SEO-friendly excerpt from the post content using AI.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'required'   => [ 'post_id' ],
                    'properties' => [
                        'post_id' => [
                            'type'        => 'integer',
                            'description' => __( 'Post ID to generate excerpt for.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'content' => [
                            'type'        => 'string',
                            'description' => __( 'Optional content override. If not provided, uses post content.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'prompt' => [
                            'type'        => 'string',
                            'description' => __( 'Optional custom system instruction for generation.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'provider' => [
                            'type'        => 'string',
                            'description' => __( 'AI provider preference: auto, openai, google, or anthropic.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'tone' => [
                            'type'        => 'string',
                            'description' => __( 'Tone modifier: professional, casual, friendly, or academic.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'excerpt' => [
                            'type'        => 'string',
                            'description' => __( 'AI-generated excerpt.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/excerpt/{post_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
            [
                'id'          => 'awfah-content/focus-keywords',
                'module'      => 'content_steward',
                'label'       => __( 'Focus Keyword Suggestions', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Extract relevant focus keywords for SEO targeting.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'required'   => [ 'post_id' ],
                    'properties' => [
                        'post_id' => [
                            'type'        => 'integer',
                            'description' => __( 'Post ID to analyze.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'keywords' => [
                            'type'        => 'array',
                            'description' => __( 'Suggested focus keywords.', 'ai-workflow-automation-ai-agent-hub' ),
                            'items'       => [ 'type' => 'string' ],
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/focus-keywords/{post_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
            [
                'id'          => 'awfah-content/lsi-keywords',
                'module'      => 'content_steward',
                'label'       => __( 'LSI Keyword Suggestions', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Generate related LSI keyword ideas to strengthen topical relevance.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'required'   => [ 'post_id' ],
                    'properties' => [
                        'post_id' => [
                            'type'        => 'integer',
                            'description' => __( 'Post ID to analyze for LSI opportunities.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'keywords' => [
                            'type'        => 'array',
                            'description' => __( 'Suggested LSI keywords.', 'ai-workflow-automation-ai-agent-hub' ),
                            'items'       => [ 'type' => 'string' ],
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/lsi-keywords/{post_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
            [
                'id'          => 'awfah-content/summarize',
                'module'      => 'content_steward',
                'label'       => __( 'Summarize Content', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Generate a concise summary of the post content.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'required'   => [ 'post_id' ],
                    'properties' => [
                        'post_id' => [
                            'type'        => 'integer',
                            'description' => __( 'Post ID to summarize.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'content' => [
                            'type'        => 'string',
                            'description' => __( 'Optional content override.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'prompt' => [
                            'type'        => 'string',
                            'description' => __( 'Optional custom system instruction.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'provider' => [
                            'type'        => 'string',
                            'description' => __( 'AI provider preference.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'length' => [
                            'type'        => 'string',
                            'description' => __( 'Summary length: short, medium, or long.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'summary' => [
                            'type'        => 'string',
                            'description' => __( 'AI-generated summary.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/summarize/{post_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
            [
                'id'          => 'awfah-content/generate-alt-text',
                'module'      => 'content_steward',
                'label'       => __( 'Generate Alt Text', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Generate accessible alt text for an image using AI vision.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'attachment_id' => [
                            'type'        => 'integer',
                            'description' => __( 'WordPress attachment ID.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'image_url' => [
                            'type'        => 'string',
                            'description' => __( 'Image URL or data URI.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'context' => [
                            'type'        => 'string',
                            'description' => __( 'Surrounding content for context.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'alt_text' => [
                            'type'        => 'string',
                            'description' => __( 'Generated alt text (max 125 characters).', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/alt-text/{attachment_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
            [
                'id'          => 'awfah-content/suggest-titles',
                'module'      => 'content_steward',
                'label'       => __( 'Suggest Post Titles', 'ai-workflow-automation-ai-agent-hub' ),
                'description' => __( 'Generate alternative title ideas based on a post or custom text.', 'ai-workflow-automation-ai-agent-hub' ),
                'category'    => 'awfah-content',
                'input_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'post_id' => [
                            'type'        => 'integer',
                            'description' => __( 'Optional post ID to derive title suggestions from.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                        'text'    => [
                            'type'        => 'string',
                            'description' => __( 'Optional raw text or description to generate titles from.', 'ai-workflow-automation-ai-agent-hub' ),
                        ],
                    ],
                ],
                'output_schema'=> [
                    'type'       => 'object',
                    'properties' => [
                        'titles' => [
                            'type'        => 'array',
                            'description' => __( 'List of suggested titles.', 'ai-workflow-automation-ai-agent-hub' ),
                            'items'       => [
                                'type' => 'string',
                            ],
                        ],
                    ],
                ],
                'meta'        => [
                    'show_in_rest' => true,
                    'mcp'          => [ 'public' => true ],
                    'uri'          => 'wordpress://ai-agent-hub/content/suggest-titles/{post_id}',
                    'mimeType'     => 'application/json',
                ],
            ],
        ];
    }

    public static function register() {
        if ( ! function_exists( 'wp_register_ability' ) ) {
            return;
        }

        $callbacks = [
            'awfah-content/analyze-post'   => [ __CLASS__, 'execute_analyze_post' ],
            'awfah-content/generate-feature-image' => [ __CLASS__, 'execute_generate_feature_image' ],
            'awfah-content/generate-excerpt' => [ __CLASS__, 'execute_generate_excerpt' ],
            'awfah-content/focus-keywords' => [ __CLASS__, 'execute_focus_keywords' ],
            'awfah-content/lsi-keywords'   => [ __CLASS__, 'execute_lsi_keywords' ],
            'awfah-content/summarize'      => [ __CLASS__, 'execute_summarize' ],
            'awfah-content/generate-alt-text' => [ __CLASS__, 'execute_generate_alt_text' ],
            'awfah-content/suggest-titles' => [ __CLASS__, 'execute_suggest_titles' ],
        ];

        foreach ( self::get_abilities() as $ability ) {
            $config = $ability;
            $id     = $ability['id'];
            unset( $config['id'], $config['module'] );

            // Workaround: MCP ResourcesHandler calls execute() with no input.
            // Adding default empty object prevents "input is not of type object" validation error.
            if ( isset( $config['meta']['uri'], $config['input_schema']['type'] ) && 'object' === $config['input_schema']['type'] ) {
                $config['input_schema']['default'] = (object) [];
            }

           wp_register_ability(
                $id,
                array_merge(
                    $config,
                    [
                        'execute_callback'    => $callbacks[ $id ] ?? [ __CLASS__, 'execute_suggest_titles' ],
                        'permission_callback' => static function () use ( $id ) {
                            return \AtlasAiDev\Awfah\Plugin::check_ability_access( $id, 'edit_posts' );
                        },
                    ]
                )
           );
        }
    }

    public static function execute_analyze_post( array $input ): array {
        $post_id  = isset( $input['post_id'] ) ? (int) $input['post_id'] : 0;
        $provider = isset( $input['provider'] ) ? (string) $input['provider'] : 'auto';
        $post     = $post_id ? get_post( $post_id ) : null;

        if ( ! $post instanceof WP_Post ) {
            return [
                'summary'       => '',
                'reading_level' => '',
                'suggestions'   => __( 'Post not found.', 'ai-workflow-automation-ai-agent-hub' ),
            ];
        }

        $content = wp_strip_all_tags( $post->post_content );
        $title   = get_the_title( $post );

        $prompt = sprintf(
            "Analyze the following WordPress post.\n\nTitle: %s\n\nContent:\n%s\n\nReturn a JSON object with keys: summary (max 3 sentences), reading_level (Beginner/Intermediate/Advanced), suggestions (short bullet-style text). Respond with JSON only.",
            $title,
            $content
        );

        // No structured output (json_schema) — not all providers/models support it (when
        // unsupported the request is silently skipped). We ask for JSON in the prompt and parse
        // it loosely instead, for cross-provider compatibility.
        $args = [
            'temperature' => 0.4,
            'provider'    => $provider,
            'model'       => isset( $input['model'] ) ? (string) $input['model'] : '',
        ];

        try {
            $result = AI_Provider_Manager::generate_text( $prompt, $args );

            if ( '' === $result ) {
                return [
                    'summary'       => '',
                    'reading_level' => '',
                    'suggestions'   => __( 'AI analysis failed. Check AI credentials (Settings → AI Credentials) or enable WP_DEBUG_LOG for details.', 'ai-workflow-automation-ai-agent-hub' ),
                ];
            }

            $data = self::decode_json_loose( $result );
            if ( ! is_array( $data ) ) {
                throw new \RuntimeException( 'Invalid JSON from AI.' );
            }

            $suggestions_raw = $data['suggestions'] ?? '';
            if ( is_array( $suggestions_raw ) ) {
                $suggestions = implode(
                    "\n\n",
                    array_filter(
                        array_map(
                            'trim',
                            array_map( 'strval', $suggestions_raw )
                        )
                    )
                );
            } else {
                $suggestions = (string) $suggestions_raw;
            }

            return [
                'summary'       => (string) ( $data['summary'] ?? '' ),
                'reading_level' => (string) ( $data['reading_level'] ?? '' ),
                'suggestions'   => $suggestions,
            ];
        } catch ( \Throwable $e ) {
            Logger::log( 'Error analyzing post', [ 'error' => $e->getMessage() ] );

            return [
                'summary'       => '',
                'reading_level' => '',
                'suggestions'   => __( 'AI analysis failed. Check AI credentials or logs.', 'ai-workflow-automation-ai-agent-hub' ),
            ];
        }
    }

    public static function execute_suggest_titles( array $input ): array {
        $post_id  = isset( $input['post_id'] ) ? (int) $input['post_id'] : 0;
        $text     = isset( $input['text'] ) ? (string) $input['text'] : '';
        $provider = isset( $input['provider'] ) ? (string) $input['provider'] : 'auto';

        if ( $post_id && '' === $text ) {
            $post = get_post( $post_id );
            if ( $post instanceof WP_Post ) {
                $text = get_the_title( $post ) . "\n\n" . wp_strip_all_tags( $post->post_content );
            }
        }

        if ( '' === trim( $text ) ) {
            return [
                'titles' => [],
            ];
        }

        $prompt_text = "You are an expert copywriter. Based on the following content, generate 5 compelling, SEO-friendly blog post titles. Return a JSON object of the form {\"titles\": [\"...\", \"...\"]} with a single \"titles\" key holding an array of strings."
            // Editorial Guidelines from the official AI plugin, when present (AI-10).
            . \AtlasAiDev\Awfah\Integrations\Wpai_Bridge::guidelines_suffix( [ 'site', 'copy' ] )
            . "\n\nContent:\n" . $text;

        // We deliberately do NOT use structured output (json_schema / as_json_response) here:
        // not every provider/model supports it, and when unsupported the request is silently
        // skipped (is_supported_for_text_generation() returns false → empty result, 0 tokens).
        // Instead we ask for JSON in the prompt and parse it loosely, which works across all
        // providers (OpenAI, Gemini, Anthropic).
        $args = [
            'temperature' => 0.7,
            'tool_slug'   => 'suggest-titles',
            'post_id'     => $post_id,
            'provider'    => $provider,
            'model'       => isset( $input['model'] ) ? (string) $input['model'] : '',
        ];

        try {
            $gen    = AI_Provider_Manager::generate_text_with_usage( $prompt_text, $args );
            $result = $gen['text'];

            if ( '' === $result ) {
                return [ 'titles' => [], 'usage' => $gen['usage'] ];
            }

            $data = self::decode_json_loose( $result );
            if ( ! is_array( $data ) ) {
                throw new \RuntimeException( 'Invalid JSON from AI.' );
            }

            // Result is an object {"titles": [...]}; fall back to a bare array for older providers.
            $list = ( isset( $data['titles'] ) && is_array( $data['titles'] ) ) ? $data['titles'] : $data;

            $titles = array_values(
                array_filter(
                    array_map( 'strval', $list ),
                    static function ( $t ) {
                        return '' !== trim( $t );
                    }
                )
            );

            return [ 'titles' => $titles, 'usage' => $gen['usage'] ];
        } catch ( \Throwable $e ) {
            Logger::log( 'Error suggesting titles', [ 'error' => $e->getMessage() ] );

            return [ 'titles' => [] ];
        }
    }

    /**
     * Decode JSON returned by an AI model that may be wrapped in markdown code fences or
     * surrounded by prose (common when structured output is not enforced).
     *
     * @param string $text Raw model output.
     * @return array|null Decoded array, or null if no valid JSON could be extracted.
     */
    private static function decode_json_loose( string $text ) {
        $text = trim( $text );

        // Strip a ```json ... ``` (or plain ``` ... ```) code fence if present.
        if ( preg_match( '/```(?:json)?\s*(.+?)\s*```/is', $text, $m ) ) {
            $text = trim( $m[1] );
        }

        $decoded = json_decode( $text, true );
        if ( is_array( $decoded ) ) {
            return $decoded;
        }

        // Fall back: pull out the first JSON object or array substring.
        if ( preg_match( '/(\{.*\}|\[.*\])/s', $text, $m ) ) {
            $decoded = json_decode( $m[1], true );
            if ( is_array( $decoded ) ) {
                return $decoded;
            }
        }

        return null;
    }

    public static function execute_generate_excerpt( array $input ): array {
        $post_id  = isset( $input['post_id'] ) ? (int) $input['post_id'] : 0;
        $provider = isset( $input['provider'] ) ? (string) $input['provider'] : 'auto';
        $tone     = isset( $input['tone'] ) ? (string) $input['tone'] : '';
        $custom_prompt = isset( $input['prompt'] ) ? (string) $input['prompt'] : '';
        $content_override = isset( $input['content'] ) ? (string) $input['content'] : '';

        $post = $post_id ? get_post( $post_id ) : null;

        if ( ! $post instanceof WP_Post ) {
            return [ 'excerpt' => '' ];
        }

        // Use content override or fall back to post content.
        $content = '' !== $content_override
            ? wp_strip_all_tags( $content_override )
            : wp_strip_all_tags( $post->post_content );

        if ( '' === trim( $content ) ) {
            return [ 'excerpt' => '' ];
        }

        // Build the system instruction.
        $default_instruction = __(
            'You are an expert copywriter. Generate a concise, SEO-friendly excerpt for the following content. '
            . 'The excerpt should be 1-2 sentences, 150-160 characters, and capture the essence of the content. '
            . 'Return only the excerpt text with no additional formatting or explanation.',
            'ai-workflow-automation-ai-agent-hub'
        );

        $system_instruction = '' !== $custom_prompt ? $custom_prompt : $default_instruction;

        // Apply tone modifier.
        $tone_modifiers = [
            'professional' => __( ' Use a professional, authoritative tone.', 'ai-workflow-automation-ai-agent-hub' ),
            'casual'       => __( ' Use a casual, conversational tone.', 'ai-workflow-automation-ai-agent-hub' ),
            'friendly'     => __( ' Use a warm, friendly, and approachable tone.', 'ai-workflow-automation-ai-agent-hub' ),
            'academic'     => __( ' Use a formal, academic tone with precise language.', 'ai-workflow-automation-ai-agent-hub' ),
        ];

        if ( '' !== $tone && isset( $tone_modifiers[ $tone ] ) ) {
            $system_instruction .= $tone_modifiers[ $tone ];
        }

        // Editorial Guidelines from the official AI plugin, when present (AI-10).
        $system_instruction .= \AtlasAiDev\Awfah\Integrations\Wpai_Bridge::guidelines_suffix( [ 'site', 'copy' ] );

        $title  = get_the_title( $post );
        $prompt = sprintf(
            "Title: %s\n\nContent:\n%s",
            $title,
            $content
        );

        $args = [
            'temperature' => 0.7,
            'provider'    => $provider,
            'model'       => isset( $input['model'] ) ? (string) $input['model'] : '',
        ];

        try {
            $args['tool_slug'] = 'generate-excerpt';
            $args['post_id']   = $post_id;
            $gen    = AI_Provider_Manager::generate_text_with_usage( $system_instruction . "\n\n" . $prompt, $args );
            $result = $gen['text'];

            if ( '' === $result ) {
                return [ 'excerpt' => wp_trim_words( $content, 40, "\u{2026}" ), 'usage' => $gen['usage'] ];
            }

            $excerpt = trim( $result, " \t\n\r\0\x0B\"'" );

            return [ 'excerpt' => sanitize_textarea_field( $excerpt ), 'usage' => $gen['usage'] ];
        } catch ( \Throwable $e ) {
            Logger::log( 'Error generating excerpt', [ 'error' => $e->getMessage() ] );

            return [ 'excerpt' => wp_trim_words( $content, 40, "\u{2026}" ) ];
        }
    }

    public static function execute_focus_keywords( array $input ): array {
        $post_id = isset( $input['post_id'] ) ? (int) $input['post_id'] : 0;
        $post    = $post_id ? get_post( $post_id ) : null;

        if ( ! $post instanceof WP_Post ) {
            return [ 'keywords' => [] ];
        }

        $content  = strtolower( wp_strip_all_tags( $post->post_content . ' ' . get_the_title( $post ) ) );
        $keywords = self::extract_keywords( $content, 6 );

        return [ 'keywords' => $keywords ];
    }

    public static function execute_lsi_keywords( array $input ): array {
        $focus = self::execute_focus_keywords( $input );
        $base  = isset( $focus['keywords'] ) && is_array( $focus['keywords'] ) ? $focus['keywords'] : [];

        $lsi = [];
        foreach ( $base as $keyword ) {
            $lsi[] = $keyword . ' tips';
            $lsi[] = 'best ' . $keyword;
            $lsi[] = $keyword . ' strategy';
        }

        $lsi = array_values( array_unique( $lsi ) );

        return [ 'keywords' => $lsi ];
    }

    /**
     * Generate a featured image using AI, upload to media library, and return attachment details.
     *
     * Pipeline: build prompt → generate image → upload → set meta → return.
     *
     * @param array $input Input parameters (post_id, prompt?, provider?, style?).
     * @return array Image data with image_id, image_url, prompt_used, alt_text.
     */
    public static function execute_generate_feature_image( array $input ): array {
        $post_id       = isset( $input['post_id'] ) ? (int) $input['post_id'] : 0;
        $custom_prompt = isset( $input['prompt'] ) ? trim( (string) $input['prompt'] ) : '';
        $style         = isset( $input['style'] ) ? (string) $input['style'] : '';
        $provider      = isset( $input['provider'] ) ? (string) $input['provider'] : '';
        $model         = isset( $input['model'] ) ? (string) $input['model'] : '';
        $post          = $post_id ? get_post( $post_id ) : null;

        $empty_result = [
            'image_id'    => 0,
            'image_url'   => '',
            'prompt_used' => '',
            'alt_text'    => '',
        ];

        if ( ! $post instanceof \WP_Post ) {
            return $empty_result;
        }

        $title   = get_the_title( $post );
        $content = $post->post_content ?? '';

        // Build plain-text content for context (strip HTML, normalise whitespace).
        $plain_content = wp_strip_all_tags( $content );
        $plain_content = preg_replace( '/\s+/', ' ', $plain_content );
        $content_brief = trim( $plain_content );

        // Build prompt — always inject post context so AI knows what the article is about.
        if ( '' !== $custom_prompt ) {
            $image_prompt = sprintf(
                "Article title: \"%s\"\nArticle content: %s\n\nImage instructions: %s",
                $title,
                $content_brief ?: 'No content available.',
                $custom_prompt
            );
        } else {
            $keywords     = self::execute_focus_keywords( [ 'post_id' => $post_id ] );
            $keyword_list = isset( $keywords['keywords'] ) ? implode( ', ', $keywords['keywords'] ) : '';

            $image_prompt = sprintf(
                'Create a vibrant feature image for the article "%s" that highlights %s. Use balanced composition and professional quality.',
                $title,
                $keyword_list ?: 'the main talking points'
            );

            if ( '' !== $content_brief ) {
                $image_prompt .= sprintf( "\n\nArticle content for context: %s", $content_brief );
            }
        }

        // Apply style modifier.
        $style_modifiers = [
            'photo-realistic' => ' Photo-realistic style with cinematic lighting and natural textures.',
            'illustration'    => ' Digital illustration style with clean lines and vivid colors.',
            'abstract'        => ' Abstract art style with geometric shapes and bold colors.',
            'minimalist'      => ' Minimalist style with simple shapes, muted palette, and ample whitespace.',
            'watercolor'      => ' Watercolor painting style with soft edges and blended colors.',
        ];

        if ( '' !== $style && isset( $style_modifiers[ $style ] ) ) {
            $image_prompt .= $style_modifiers[ $style ];
        }

        // Editorial Guidelines from the official AI plugin, when present (AI-10).
        $image_prompt .= \AtlasAiDev\Awfah\Integrations\Wpai_Bridge::guidelines_suffix( [ 'site', 'images' ] );

        // Generate image via AI, honoring the request's provider/model selection.
        $file = AI_Provider_Manager::generate_image(
            $image_prompt,
            [ 'provider' => $provider, 'model' => $model ]
        );

        if ( null === $file ) {
            Logger::log( '[feature-image] Image generation failed.', [ 'post_id' => $post_id ] );
            $empty_result['prompt_used'] = $image_prompt;
            $empty_result['error']       = __( 'Image generation failed. Please check your AI provider credentials and try again.', 'ai-workflow-automation-ai-agent-hub' );
            return $empty_result;
        }

        // Upload to media library.
        $base64_data = $file->getBase64Data();
        $alt_text    = $title;

        $upload_result = Media_Abilities::execute_upload_media( [
            'file'     => $base64_data,
            'title'    => sanitize_file_name( $title ) . '-featured',
            'alt_text' => $alt_text,
        ] );

        if ( is_wp_error( $upload_result ) ) {
            Logger::log( '[feature-image] Upload failed.', [ 'error' => $upload_result->get_error_message() ] );
            $empty_result['prompt_used'] = $image_prompt;
            $empty_result['error']       = $upload_result->get_error_message();
            return $empty_result;
        }

        $image_id = (int) ( $upload_result['id'] ?? 0 );

        // Set AI-generated meta on the attachment.
        if ( $image_id ) {
            update_post_meta( $image_id, '_ai_generated', 1 );
            update_post_meta( $image_id, '_ai_generation_prompt', $image_prompt );
        }

        $image_url = isset( $upload_result['source_url'] )
            ? $upload_result['source_url']
            : ( $image_id ? wp_get_attachment_url( $image_id ) : '' );

        return [
            'image_id'    => $image_id,
            'image_url'   => $image_url,
            'prompt_used' => $image_prompt,
            'alt_text'    => $alt_text,
        ];
    }

    /**
     * Generate a content summary.
     */
    public static function execute_summarize( array $input ): array {
        $post_id          = isset( $input['post_id'] ) ? (int) $input['post_id'] : 0;
        $provider         = isset( $input['provider'] ) ? (string) $input['provider'] : 'auto';
        $length           = isset( $input['length'] ) ? (string) $input['length'] : 'medium';
        $custom_prompt    = isset( $input['prompt'] ) ? (string) $input['prompt'] : '';
        $content_override = isset( $input['content'] ) ? (string) $input['content'] : '';

        $post = $post_id ? get_post( $post_id ) : null;

        if ( ! $post instanceof WP_Post && '' === $content_override ) {
            return [ 'summary' => '' ];
        }

        $content = '' !== $content_override
            ? wp_strip_all_tags( $content_override )
            : wp_strip_all_tags( $post->post_content );

        if ( '' === trim( $content ) ) {
            return [ 'summary' => '' ];
        }

        // Length-based system instruction.
        $length_instructions = [
            'short'  => 'Generate a 1-sentence summary (25 words or fewer).',
            'medium' => 'Generate a 2-3 sentence summary (25-80 words).',
            'long'   => 'Generate a 4-6 sentence summary (80-160 words).',
        ];

        $length_instruction = $length_instructions[ $length ] ?? $length_instructions['medium'];

        $default_instruction = __(
            'You are an expert content summarizer. Generate a concise, factual, and neutral summary of the following content. '
            . 'Use complete sentences. No markdown, bullets, or numbering — plain text only. '
            . 'Provide a high-level overview, not a list of details. No generic intros.',
            'ai-workflow-automation-ai-agent-hub'
        );

        $system_instruction = '' !== $custom_prompt ? $custom_prompt : $default_instruction;
        $system_instruction .= ' ' . $length_instruction;

        // Editorial Guidelines from the official AI plugin, when present (AI-10).
        $system_instruction .= \AtlasAiDev\Awfah\Integrations\Wpai_Bridge::guidelines_suffix( [ 'site', 'copy' ] );

        $title  = $post ? get_the_title( $post ) : '';
        $prompt = '';
        if ( $title ) {
            $prompt .= "Title: {$title}\n\n";
        }
        $prompt .= "Content:\n{$content}";

        $args = [
            'temperature' => 0.7,
            'tool_slug'   => 'summarization',
            'post_id'     => $post_id,
            'provider'    => $provider,
            'model'       => isset( $input['model'] ) ? (string) $input['model'] : '',
        ];

        try {
            $gen    = AI_Provider_Manager::generate_text_with_usage( $system_instruction . "\n\n" . $prompt, $args );
            $result = $gen['text'];

            if ( '' === $result ) {
                return [ 'summary' => wp_trim_words( $content, 40, "\u{2026}" ), 'usage' => $gen['usage'] ];
            }

            $summary = trim( $result, " \t\n\r\0\x0B\"'" );

            return [ 'summary' => sanitize_textarea_field( $summary ), 'usage' => $gen['usage'] ];
        } catch ( \Throwable $e ) {
            Logger::log( 'Error generating summary', [ 'error' => $e->getMessage() ] );
            return [ 'summary' => wp_trim_words( $content, 40, "\u{2026}" ) ];
        }
    }

    /**
     * Generate alt text for an image using AI vision.
     */
    public static function execute_generate_alt_text( array $input ): array {
        $attachment_id = isset( $input['attachment_id'] ) ? (int) $input['attachment_id'] : 0;
        $image_url     = isset( $input['image_url'] ) ? (string) $input['image_url'] : '';
        $context       = isset( $input['context'] ) ? (string) $input['context'] : '';
        $provider      = isset( $input['provider'] ) ? (string) $input['provider'] : 'auto';

        if ( ! $attachment_id && '' === $image_url ) {
            return [ 'alt_text' => '' ];
        }

        // Resolve image to a URL for the AI to analyze.
        $resolved_url = '';

        if ( $attachment_id ) {
            $url = wp_get_attachment_url( $attachment_id );
            if ( $url ) {
                $resolved_url = $url;
            }
        }

        if ( '' === $resolved_url && '' !== $image_url ) {
            $resolved_url = $image_url;
        }

        if ( '' === $resolved_url ) {
            return [ 'alt_text' => '' ];
        }

        // Resolve the image to a local file so the actual bytes can be sent to the model.
        $image_path = '';
        $temp_file  = '';

        if ( $attachment_id ) {
            $file = get_attached_file( $attachment_id );
            if ( $file && file_exists( $file ) ) {
                $image_path = $file;
            }
        }

        if ( '' === $image_path ) {
            // Fallback: download the resolved URL to a temporary file.
            if ( ! function_exists( 'download_url' ) ) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }
            $downloaded = download_url( $resolved_url );
            if ( ! is_wp_error( $downloaded ) ) {
                $temp_file  = $downloaded;
                $image_path = $downloaded;
            }
        }

        if ( '' === $image_path ) {
            return [ 'alt_text' => '' ];
        }

        // Detect the MIME type from the actual file, falling back to the filename/URL.
        $mime_type = function_exists( 'wp_get_image_mime' ) ? (string) wp_get_image_mime( $image_path ) : '';
        if ( '' === $mime_type ) {
            $filetype  = wp_check_filetype( $image_path );
            $mime_type = $filetype['type'] ? (string) $filetype['type'] : '';
        }
        if ( '' === $mime_type && $attachment_id ) {
            $mime_type = (string) get_post_mime_type( $attachment_id );
        }
        if ( '' === $mime_type ) {
            $filetype  = wp_check_filetype( $resolved_url );
            $mime_type = $filetype['type'] ? (string) $filetype['type'] : '';
        }

        // Keep article context short so it informs wording without dominating the image.
        if ( mb_strlen( $context ) > 300 ) {
            $context = mb_substr( $context, 0, 300 );
        }

        // Build the prompt. The image itself is attached as a multimodal part below.
        $prompt = 'Generate alt text for this image.';
        if ( '' !== $context ) {
            $prompt .= "\n\nContext from the article where this image appears:\n" . $context;
        }

        $system_instruction = 'You are an accessibility expert. '
            . 'Analyze the image and generate concise, descriptive alt text for screen readers. '
            . 'Requirements: Concise (under 125 characters when possible). '
            . 'Descriptive of what is visually present. Objective — no assumptions. '
            . 'Do NOT start with "Image of", "Picture of", "Photo of". '
            . 'Include relevant details: people, objects, actions, colors, context. '
            . 'Plain text only — no markdown, quotes, or formatting. '
            . 'Return only the alt text, nothing else.';

        // Editorial Guidelines from the official AI plugin, when present (AI-10).
        $system_instruction .= \AtlasAiDev\Awfah\Integrations\Wpai_Bridge::guidelines_suffix( [ 'site', 'images' ] );

        $args = [
            'temperature' => 0.3,
            'tool_slug'   => 'alt-text-generation',
            'post_id'     => $attachment_id,
            'provider'    => $provider,
            'model'       => isset( $input['model'] ) ? (string) $input['model'] : '',
        ];

        try {
            // Vision generation: the image bytes are attached as an inline multimodal part.
            $gen = AI_Provider_Manager::generate_text_with_image_usage(
                $system_instruction . "\n\n" . $prompt,
                $image_path,
                $mime_type,
                $args
            );
            $result = $gen['text'];

            if ( '' === $result ) {
                return [ 'alt_text' => '', 'usage' => $gen['usage'] ];
            }

            // Clean up and truncate to 125 chars.
            $alt_text = trim( $result, " \t\n\r\0\x0B\"'" );
            if ( mb_strlen( $alt_text ) > 125 ) {
                $alt_text = mb_substr( $alt_text, 0, 122 ) . '...';
            }

            return [ 'alt_text' => sanitize_text_field( $alt_text ), 'usage' => $gen['usage'] ];
        } catch ( \Throwable $e ) {
            Logger::log( 'Error generating alt text', [ 'error' => $e->getMessage() ] );
            return [ 'alt_text' => '' ];
        } finally {
            if ( '' !== $temp_file ) {
                wp_delete_file( $temp_file );
            }
        }
    }

    private static function extract_keywords( string $text, int $limit = 6 ): array {
        $words = preg_split( '/[^a-z0-9]+/i', strtolower( $text ) );
        $words = array_filter( $words, static function ( $word ) {
            $stop = [ 'the', 'and', 'or', 'for', 'with', 'that', 'this', 'from', 'your', 'you', 'are', 'was', 'were', 'a', 'an', 'of', 'to', 'in' ];
            return '' !== $word && ! in_array( $word, $stop, true ) && strlen( $word ) > 3;
        } );

        $counts = [];
        foreach ( $words as $word ) {
            if ( ! isset( $counts[ $word ] ) ) {
                $counts[ $word ] = 0;
            }
            $counts[ $word ]++;
        }

        arsort( $counts );

        return array_slice( array_keys( $counts ), 0, $limit );
    }
}
