<?php
/**
 * Writing REST Controller
 *
 * Handles article writing and formatting operations.
 *
 * @package WP_Agentic_Writer
 */

/**
 * Class WP_Agentic_Writer_Controller_Writing
 *
 * REST controller for writing operations including article execution and block formatting.
 *
 * @since 0.3.0
 */
class WP_Agentic_Writer_Controller_Writing
{
    /**
     * Sidebar instance for dependency access.
     *
     * @var WP_Agentic_Writer_Gutenberg_Sidebar
     */
    private $sidebar;

    /**
     * Constructor.
     *
     * @since 0.3.0
     * @param WP_Agentic_Writer_Gutenberg_Sidebar $sidebar Sidebar instance.
     */
    public function __construct($sidebar)
    {
        $this->sidebar = $sidebar;
    }

    /**
     * Handle execute article request.
     *
     * @since 0.1.0
     * @param WP_REST_Request $request REST request.
     * @return WP_REST_Response|WP_Error Response.
     */
    public function handle_execute_article($request)
    {
        // Check rate limit.
        $rate_limit = WPAW_Rate_Limiter::check("execute_article");
        if (is_wp_error($rate_limit)) {
            return $rate_limit;
        }

        $params = $request->get_json_params();
        $post_id = $params["postId"] ?? 0;
        $session_id = $this->sidebar->resolve_or_create_session_id(
            $params["sessionId"] ?? "",
            $post_id,
        );
        $stream = $params["stream"] ?? false;
        $recommended_title = "";
        $chat_history = $params["chatHistory"] ?? [];
        $post_config = $this->sidebar->resolve_post_config_from_request(
            $params,
            $post_id,
        );
        $post_config_context = $this->sidebar->build_post_config_context($post_config);
        $stored_language = get_post_meta(
            $post_id,
            "_wpaw_detected_language",
            true,
        );
        $detected_language = $params["detectedLanguage"] ?? $stored_language;
        $effective_language = $this->sidebar->resolve_language_preference(
            $post_config,
            $detected_language,
        );

        // Auto-save post and link conversation if needed (only for post_id = 0)
        if (empty($post_id) && !empty($session_id)) {
            $post_id = $this->sidebar->ensure_conversation_linked_to_post(
                $session_id,
                $post_id,
            );
        }

        // Check post permission if post_id is provided.
        if ($post_id > 0 && !$this->sidebar->check_post_permission($post_id)) {
            return new WP_Error(
                "forbidden",
                __(
                    "You do not have permission to edit this post.",
                    "wp-agentic-writer",
                ),
                ["status" => 403],
            );
        }

        // Get plan from post meta.
        $plan = get_post_meta($post_id, "_wpaw_plan", true);

        if (empty($plan)) {
            return new WP_Error(
                "no_plan",
                __(
                    "No plan found. Please generate a plan first.",
                    "wp-agentic-writer",
                ),
                ["status" => 400],
            );
        }

        if ($stream) {
            // For streaming, link conversation to post BEFORE getting plan from meta
            if (empty($post_id) && !empty($session_id)) {
                $post_id = $this->sidebar->ensure_conversation_linked_to_post(
                    $session_id,
                    $post_id,
                );
            }

            // Now get plan after potentially having a valid post_id
            $plan = get_post_meta($post_id, "_wpaw_plan", true);
            if (empty($plan)) {
                echo "data: " .
                    wp_json_encode([
                        "type" => "error",
                        "message" =>
                            "No plan found. Please generate a plan first.",
                    ]) .
                    "\n\n";
                flush();
                return;
            }

            $this->sidebar->stream_execute_article(
                $plan,
                $post_id,
                $post_config,
                $effective_language,
                $session_id,
            );
            exit();
        }

        $plan = $this->sidebar->ensure_plan_sections_with_tasks($plan);

        // MEMANTO: Plan execution implies approval.
        do_action("wpaw_memanto_plan_approved", $post_id, $plan);

        // Update post title from the plan title when available.
        if (!empty($plan["title"])) {
            $recommended_title = sanitize_text_field($plan["title"]);
            if ($post_id > 0) {
                $post = get_post($post_id);
                if ($post && current_user_can("edit_post", $post_id)) {
                    if (empty($post->post_title)) {
                        wp_update_post([
                            "ID" => $post_id,
                            "post_title" => $recommended_title,
                        ]);
                    }
                }
            }
        }

        // Get provider for writing task.
        $provider_result = WP_Agentic_Writer_Provider_Manager::get_provider_for_task(
            "writing",
        );
        $provider = $provider_result->provider;

        $image_instruction = "IMAGE SUGGESTIONS:
- Suggest where images would enhance understanding
- Place image suggestions on their own line using this format: [IMAGE: descriptive alt text]
- Be strategic: only suggest images where they add real value (diagrams, screenshots, visual examples)
- Good places for images: after introductions, before complex explanations, to show examples
- Maximum 1-2 image suggestions per section
- Example: [IMAGE: Screenshot of the plugin settings panel showing the API key field]";
        if (empty($post_config["include_images"])) {
            $image_instruction = "IMAGE SUGGESTIONS:
- Do NOT include any image suggestions or [IMAGE: ...] placeholders.";
        }

        $language_instruction = $this->sidebar->build_language_instruction(
            $effective_language,
            "article content",
        );

        // Build chat history context for continuity
        $chat_history_context = "";
        if (!empty($chat_history) && is_array($chat_history)) {
            $chat_history_context = "\n\n--- CONVERSATION CONTEXT ---\n";
            foreach ($chat_history as $msg) {
                $role = isset($msg["role"]) ? ucfirst($msg["role"]) : "Unknown";
                $content = isset($msg["content"]) ? $msg["content"] : "";
                if (
                    !empty($content) &&
                    "system" !== strtolower($msg["role"] ?? "")
                ) {
                    $chat_history_context .= "{$role}: {$content}\n\n";
                }
            }
            $chat_history_context .= "--- END CONVERSATION CONTEXT ---\n";
            $chat_history_context .=
                "Use the above conversation to understand the user's intent and preferences for this article.";
        }

        // Build SEO instructions if SEO is enabled
        $seo_instruction = "";
        $internal_links_instruction = "";
        if (
            !empty($post_config["seo_enabled"]) &&
            !empty($post_config["seo_focus_keyword"])
        ) {
            $focus_keyword = $post_config["seo_focus_keyword"];
            $seo_instruction = "\n\nSEO OPTIMIZATION REQUIREMENTS (CRITICAL - MUST FOLLOW):
- Focus Keyword: \"{$focus_keyword}\"
- MANDATORY: Include the exact focus keyword \"{$focus_keyword}\" in the article title (preferably at the beginning)
- MANDATORY: Use the focus keyword in the FIRST paragraph (within the first 100 words)
- Use the focus keyword 5-8 times naturally throughout the article
- Include the focus keyword in:
  * At least 2 H2 or H3 subheadings
  * The conclusion paragraph
- Include 2-3 authoritative outbound links to reputable sources (Wikipedia, official documentation, industry leaders)
- When suggesting images, include the focus keyword or related terms in the alt text
- Keep the article title under 60 characters";

            // Get internal link suggestions
            $internal_links = $this->sidebar->suggest_internal_links(
                $post_id,
                $focus_keyword,
                3,
            );
            if (!empty($internal_links)) {
                $internal_links_instruction =
                    "\n\nINTERNAL LINKS (optional - use where contextually relevant):\n";
                foreach ($internal_links as $link) {
                    $internal_links_instruction .= "- [{$link["title"]}]({$link["url"]})\n";
                }
                $internal_links_instruction .=
                    "Naturally incorporate 1-2 of these internal links where they add value to the reader. Use descriptive anchor text, not 'click here'.";
            }
        }

        // Build system prompt for article generation.
        $system_prompt = "You are an industry practitioner sharing insights with a colleague. Write engaging, high-information-density content based on the provided article plan.

ANTI-ROBOT RULES:
- BANNED WORDS: delve, furthermore, moreover, crucial, paramount, landscape, testament, in today's digital world, in conclusion.
- BANNED PATTERNS: Do not use transition words to start paragraphs. Do not summarize what you are about to say. Do not summarize what you just said.
- BURSTINESS: Mix very short, punchy sentences (3-5 words) with longer, descriptive ones. Avoid uniform sentence length.
- TONE: Conversational, direct, pragmatic. Do not sound like an academic 'expert' or textbook.

GEO/SEO STRATEGY:
- Answer the implicit user intent directly and immediately in the first paragraph.
- Maximize information density: high ratio of facts/insights to total word count. Remove filler adjectives.
- Use bullet points or numbered lists where they make data easier to scan.

CRITICAL LANGUAGE REQUIREMENT:
{$language_instruction}
{$post_config_context}
{$chat_history_context}

Follow these guidelines:
- Use the tone specified in POST CONFIG if provided; otherwise be conversational but professional
- Embed secondary keywords naturally as concepts, without forcing exact matches
- For code blocks, use proper syntax highlighting (e.g., ```php)
- Code typography: Use plain ASCII quotes inside code. Do NOT use smart quotes.
- Write for the specified difficulty level
{$seo_instruction}
{$internal_links_instruction}

IMAGE SUGGESTIONS:
- Suggest where images would enhance understanding (diagrams, screenshots)
- Place image suggestions on their own line: [IMAGE: descriptive alt text]
- Maximum 1 image per section
{$image_instruction}";

        // Generate content for each section.
        $blocks = [];
        $total_cost = 0;

        $sections_to_write = [];
        foreach ($plan["sections"] as $index => $section) {
            $status = $section["status"] ?? "pending";
            if ("done" === $status) {
                continue;
            }
            $sections_to_write[$index] = $section;
        }

        foreach ($sections_to_write as $section) {
            $heading = $section["heading"] ?? ($section["title"] ?? "");
            $section_prompt = $heading
                ? "Write the \"{$heading}\" section.\n\n"
                : "Write the next section.\n\n";
            $section_prompt .= "Content requirements:\n";

            if (!empty($section["content"]) && is_array($section["content"])) {
                foreach ($section["content"] as $item) {
                    if (!empty($item["content"])) {
                        $section_prompt .= "- {$item["content"]}\n";
                    }
                }
            }

            $messages = [
                [
                    "role" => "system",
                    "content" => $system_prompt,
                ],
                [
                    "role" => "user",
                    "content" => $section_prompt,
                ],
            ];

            $response = $provider->chat(
                $messages,
                ["temperature" => 0.8],
                "execution",
            );

            if (is_wp_error($response)) {
                return new WP_Error(
                    "execution_error",
                    $response->get_error_message(),
                    ["status" => 500],
                );
            }

            // Add section blocks.
            if ($heading) {
                $blocks[] = [
                    "type" => "heading",
                    "content" => $heading,
                    "level" => 2,
                ];
            }

            $section_blocks = WP_Agentic_Writer_Markdown_Parser::parse(
                $response["content"],
            );
            if (!empty($section_blocks)) {
                $first_block = $section_blocks[0];
                if (
                    isset($first_block["blockName"]) &&
                    "core/heading" === $first_block["blockName"]
                ) {
                    $first_heading = $first_block["attrs"]["content"] ?? "";
                    if (
                        $heading &&
                        $first_heading &&
                        0 === strcasecmp(trim($first_heading), trim($heading))
                    ) {
                        array_shift($section_blocks);
                    }
                }
                foreach ($section_blocks as $block) {
                    $blocks[] = $block;
                }
            } else {
                $blocks[] = [
                    "type" => "paragraph",
                    "content" => $response["content"],
                ];
            }

            $total_cost += $response["cost"];

            // MEMANTO: Remember section written.
            $section_id = $section["id"] ?? sanitize_title($heading);
            do_action(
                "wpaw_memanto_section_written",
                $post_id,
                $section_id,
                $heading,
            );
        }

        if (!empty($sections_to_write)) {
            foreach (array_keys($sections_to_write) as $section_index) {
                $plan["sections"][$section_index]["status"] = "done";
            }
            if ($post_id > 0) {
                update_post_meta($post_id, "_wpaw_plan", $plan);
            }
        }

        // Track total cost.
        $this->sidebar->track_ai_cost(
            $post_id,
            $this->sidebar->get_provider_execution_model($provider, "execution"),
            "execution",
            0,
            0,
            $total_cost,
            $provider_result,
            "",
            "success",
        );

        return new WP_REST_Response(
            [
                "blocks" => $blocks,
                "cost" => $total_cost,
                "recommended_title" => $recommended_title,
                "provider_metadata" => $this->sidebar->build_provider_metadata(
                    $provider_result,
                    $this->sidebar->get_provider_execution_model($provider, "execution"),
                ),
            ],
            200,
        );
    }

    /**
     * Handle reformat blocks request.
     *
     * @since 0.1.0
     * @param WP_REST_Request $request REST request.
     * @return WP_REST_Response|WP_Error Response.
     */
    public function handle_reformat_blocks($request)
    {
        $params = $request->get_json_params();
        $blocks = $params["blocks"] ?? [];
        $post_id = $params["postId"] ?? 0;
        $recommended_title = "";
        $title_updated = false;

        if (empty($blocks) || !is_array($blocks)) {
            return new WP_Error(
                "no_blocks",
                __("Blocks are required to reformat.", "wp-agentic-writer"),
                ["status" => 400],
            );
        }

        // Check post permission if post_id is provided.
        if ($post_id > 0 && !$this->sidebar->check_post_permission($post_id)) {
            return new WP_Error(
                "forbidden",
                __(
                    "You do not have permission to edit this post.",
                    "wp-agentic-writer",
                ),
                ["status" => 403],
            );
        }

        $results = [];

        if ($post_id > 0) {
            $plan = get_post_meta($post_id, "_wpaw_plan", true);
            if (is_array($plan) && !empty($plan["title"])) {
                $recommended_title = sanitize_text_field($plan["title"]);
            }
        }

        foreach ($blocks as $block) {
            $client_id =
                $block["clientId"] ?? ($block["attrs"]["clientId"] ?? "");
            $block_type =
                $block["name"] ?? ($block["blockName"] ?? "core/paragraph");
            $block_attrs = $block["attributes"] ?? ($block["attrs"] ?? []);

            if (empty($client_id)) {
                continue;
            }

            if ("core/paragraph" !== $block_type) {
                continue;
            }

            $content = $this->sidebar->extract_block_content_from_attrs(
                $block_type,
                $block_attrs,
            );
            if ("" === trim((string) $content)) {
                continue;
            }

            $parsed_blocks = WP_Agentic_Writer_Markdown_Parser::parse($content);
            if (empty($parsed_blocks)) {
                continue;
            }

            $results[] = [
                "clientId" => $client_id,
                "blocks" => $parsed_blocks,
            ];
        }

        if ($post_id > 0 && "" !== $recommended_title) {
            $post = get_post($post_id);
            if ($post && current_user_can("edit_post", $post_id)) {
                if (empty($post->post_title)) {
                    wp_update_post([
                        "ID" => $post_id,
                        "post_title" => $recommended_title,
                    ]);
                    $title_updated = true;
                }
            }
        }

        return new WP_REST_Response(
            [
                "results" => $results,
                "recommended_title" => $recommended_title,
                "title_updated" => $title_updated,
            ],
            200,
        );
    }

    /**
     * Handle save section blocks request.
     *
     * @since 0.1.0
     * @param WP_REST_Request $request REST request.
     * @return WP_REST_Response|WP_Error Response.
     */
    public function handle_save_section_blocks($request)
    {
        $params = $request->get_json_params();
        $post_id = intval($params["postId"] ?? 0);
        $section_id = sanitize_text_field($params["sectionId"] ?? "");
        $block_ids = $params["blockIds"] ?? [];

        if ($post_id <= 0 || empty($section_id) || !is_array($block_ids)) {
            return new WP_Error(
                "invalid_section_blocks",
                __(
                    "Invalid section block mapping request.",
                    "wp-agentic-writer",
                ),
                ["status" => 400],
            );
        }

        if (!$this->sidebar->check_post_permission($post_id)) {
            return new WP_Error(
                "forbidden",
                __(
                    "You do not have permission to edit this post.",
                    "wp-agentic-writer",
                ),
                ["status" => 403],
            );
        }

        $block_ids = array_values(
            array_filter(array_map("sanitize_text_field", $block_ids)),
        );

        $mapping = get_post_meta($post_id, "_wpaw_section_blocks", true);
        if (!is_array($mapping)) {
            $mapping = [];
        }

        $mapping[$section_id] = $block_ids;
        update_post_meta($post_id, "_wpaw_section_blocks", $mapping);

        return new WP_REST_Response(
            [
                "success" => true,
                "sectionId" => $section_id,
                "blockCount" => count($block_ids),
            ],
            200,
        );
    }

    /**
     * Handle get section blocks request.
     *
     * @since 0.1.0
     * @param WP_REST_Request $request REST request.
     * @return WP_REST_Response|WP_Error Response.
     */
    public function handle_get_section_blocks($request)
    {
        $post_id = intval($request["post_id"] ?? 0);
        if ($post_id <= 0) {
            return new WP_Error(
                "invalid_post",
                __("Invalid post ID.", "wp-agentic-writer"),
                ["status" => 400],
            );
        }

        if (!$this->sidebar->check_post_permission($post_id)) {
            return new WP_Error(
                "forbidden",
                __(
                    "You do not have permission to access this post.",
                    "wp-agentic-writer",
                ),
                ["status" => 403],
            );
        }

        $mapping = get_post_meta($post_id, "_wpaw_section_blocks", true);
        if (!is_array($mapping)) {
            $mapping = [];
        }

        return new WP_REST_Response(
            [
                "sectionBlocks" => $mapping,
            ],
            200,
        );
    }
}
