<?php

namespace Miruni\DraftManager;

if (!defined('ABSPATH'))
    exit; // Exit if accessed directly

use Miruni\Elementor\Miruni_Elementor_Service;
use Miruni\UpdateUtils;
use Miruni\Miruni_Draft_Manager; // Import the main draft manager
use \Exception;
use Miruni\DraftManager\MiruniChangeResult;

/**
 * Manages Elementor-specific draft operations.
 */
class Miruni_Elementor_Draft_Manager
{
    private Miruni_Draft_Manager $draft_manager; // Reference to the main draft manager

    public function __construct(Miruni_Draft_Manager $draft_manager)
    {
        $this->draft_manager = $draft_manager;
    }

    /**
     * Store Elementor JSON changes
     *
     * @param int $draft_id ID of the draft post
     * @param array<string,mixed> $content The content to store
     * @return bool Success status
     */
    public function store_elementor_json_change(int $draft_id, array $content): bool
    {
        error_log("store_elementor_json_change typeof content: " . gettype($content));
        try {
            Miruni_Elementor_Service::update_page_data($draft_id, $content);
            return true;
        } catch (Exception $e) {
            do_action('miruni_plugin_error', $e, [
                'context' => 'Elementor Draft Manager',
                'operation' => 'Storing Elementor JSON changes',
                'draft_id' => $draft_id,
                'user_id' => get_current_user_id()
            ]);
            return false;
        }
    }

    /**
     * Process Elementor JSON update operations
     *
     * @param list<array{id: int, fileType: UpdateUtils\MiruniFileType, updatedFileContent: string, fileIdentifier: string, updateSummary: string}> $updates The update operations to process
     * @param int $draft_id ID of the draft post
     * @return array<MiruniChangeResult> Array of change results
     */
    public function process_elementor_json_updates(array $updates, int $draft_id): array
    {
        $existing_elementor_json = Miruni_Elementor_Service::get_page_data($draft_id);
        error_log("Miruni_Elementor_Service::get_page_data() returned type: " . gettype($existing_elementor_json));

        // Fix: Check if result is a string and decode it
        if (is_string($existing_elementor_json)) {
            error_log("Decoding Elementor JSON for draft ID {$draft_id}");
            $existing_elementor_json = json_decode($existing_elementor_json, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                error_log("Failed to decode Elementor JSON for draft ID {$draft_id}: " . json_last_error_msg());
                do_action('miruni_plugin_error', new Exception(esc_html("Invalid JSON in Elementor data")), [
                    'context' => 'Elementor Draft Manager',
                    'operation' => 'Processing Elementor JSON updates',
                    'draft_id' => $draft_id,
                    'user_id' => get_current_user_id(),
                    'json_error' => json_last_error_msg()
                ]);
                return []; // Return empty changes as we can't process them
            }
        }

        // Handle invalid or empty data
        if (!is_array($existing_elementor_json)) {
            error_log("Invalid Elementor JSON data for draft ID {$draft_id}");
            $existing_elementor_json = [];
            do_action('miruni_plugin_error', new Exception(esc_html("Invalid Elementor JSON data")), [
                'context' => 'Elementor Draft Manager',
                'operation' => 'Processing Elementor JSON updates',
                'draft_id' => $draft_id,
                'user_id' => get_current_user_id()
            ]);
            return []; // Return empty changes as we can't process them
        }

        $updated_content_flag = false; // Flag to track if any update was processed
        $changes = [];
        $current_data = $existing_elementor_json; // Work with a copy

        foreach ($updates as $update) {
            error_log("Miruni_Elementor_Service::process_elementor_json_updates() processing update ID: " . $update['id']);
            $element_id = $update['fileIdentifier'];
            $update_summary = $update['updateSummary'];
            $updated_content_json = $update['updatedFileContent'];
            $suggestion_id = $update['id'];
            $file_name = $element_id;

            // Decode the updated content for this specific block
            $updated_block_data = json_decode($updated_content_json, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                error_log("Failed to decode updatedFileContent for Elementor block ID {$element_id}: " . json_last_error_msg());
                do_action('miruni_plugin_error', new Exception(esc_html("Invalid JSON in updatedFileContent for Elementor block")), [
                    'context' => 'Elementor Draft Manager',
                    'operation' => 'Processing Elementor JSON update - decode block JSON',
                    'draft_id' => $draft_id,
                    'element_id' => $element_id,
                    'suggestion_id' => $update['id'],
                    'json_error' => json_last_error_msg(),
                    'user_id' => get_current_user_id()
                ]);
                continue; // Skip this update if JSON is invalid
            }

            // Find the block in the current data structure
            $block_found = false;
            $original_block_content = null;
            $block_name = 'unknown';

            // Recursive function to find and update the element
            $update_recursive = function (&$elements) use ($element_id, $updated_block_data, &$block_found, &$original_block_content, &$block_name) {
                foreach ($elements as $index => &$element) {
                    if (isset($element['id']) && $element['id'] === $element_id) {
                        error_log("Updating Elementor block ID {$element_id}");
                        $original_block_content = json_encode($element); // Store original before replacing
                        $block_name = $element['elType'] ?? 'element';
                        $elements[$index] = $updated_block_data; // Replace the block
                        $block_found = true;
                        return true; // Stop searching this branch
                    } else {
                        error_log("Elementor block ID {$element_id} not found in current data. Looking for ID {$element_id}");
                    }
                }
                return false; // Not found in this branch
            };

            $update_recursive($current_data);


            if ($block_found) {
                $change = $this->draft_manager->create_change_entry( // Use main draft manager's method
                    "Elementor {$block_name} element ({$element_id})",
                    $update_summary,
                    $original_block_content ?? '[Original block data not found]', // Use stored original content
                    $file_name, // Use element_id as file_identifier
                    UpdateUtils\MiruniFileType::ELEMENTOR_JSON
                );
                $change["suggestion_id"] = $update["id"];
                $changes[] = $change;
                $updated_content_flag = true; // Mark that we processed an update
            } else {
                do_action('miruni_plugin_warning', new Exception(esc_html("Elementor block with ID {$element_id} not found in draft data.")), [
                    'context' => 'Elementor Draft Manager',
                    'operation' => 'Processing Elementor JSON update - block not found',
                    'draft_id' => $draft_id,
                    'element_id' => $element_id,
                    'suggestion_id' => $update['id'],
                    'user_id' => get_current_user_id()
                ]);
            }
        }

        // Only store changes if at least one update was successfully processed
        if ($updated_content_flag) {
            if (!$this->store_elementor_json_change($draft_id, $current_data)) {
                do_action('miruni_plugin_error', new Exception(esc_html("Error storing updated Elementor JSON")), [
                    'context' => 'Elementor Draft Manager',
                    'operation' => "Storing combined Elementor JSON updates",
                    'draft_id' => $draft_id,
                    'user_id' => get_current_user_id()
                ]);
                // Depending on requirements, you might want to clear $changes here if storing failed
            }
        } else if (!empty($updates)) {
            // Log if updates were provided but none were processed (e.g., all IDs not found)
            do_action('miruni_plugin_warning', new Exception(esc_html("No Elementor updates were applied to draft ID {$draft_id}.")), [
                'context' => 'Elementor Draft Manager',
                'operation' => "Processing Elementor JSON updates - no updates applied",
                'draft_id' => $draft_id,
                'user_id' => get_current_user_id()
            ]);
        }
        $change_results = [];
        foreach ($changes as $change) {
            $change_results[] = new MiruniChangeResult(
                $change['file_name'],
                $change['changes_made'],
                $change['original_content'],
                $change['file_identifier'],
                $change['file_type'],
                $change['suggestion_id'],
                $change["referenced_post_id"] ?? null,
                null
            );
        }

        return $change_results;
    }
}
