<?php

namespace Miruni\DraftManager;

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


use Miruni\Breakdance\Miruni_Breakdance_Service;
use Miruni\UpdateUtils;
use Miruni\Miruni_Post_Meta_Utils;
use Miruni\Miruni_Preview_Meta_Keys;
use Miruni\Miruni_Draft_Manager; // Import the main draft manager
use \Exception;




/**
 * Manages Breakdance-specific draft operations.
 */
class Miruni_Breakdance_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;
    }

    /**
     * Process Breakdance 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
     * @param int $parent_id ID of the main post being previewed (original post ID)
     * @return array<MiruniChangeResult> Array of change results
     */
    public function process_breakdance_updates(array $updates, int $draft_id, int $parent_id): array
    {
        error_log("process_breakdance_updates: draft_id: {$draft_id}, parent_id: {$parent_id}");
        // Get the current data *from the draft* which should have been copied correctly
        $original_breakdance_data_for_parent = Miruni_Breakdance_Service::get_page_data($draft_id);
        error_log("process_breakdance_updates: original_breakdance_data_for_parent type " . gettype($original_breakdance_data_for_parent));

        // @phpstan-ignore function.impossibleType
        $original_content_for_change_entry = is_array($original_breakdance_data_for_parent) || is_object($original_breakdance_data_for_parent)
            ? json_encode($original_breakdance_data_for_parent)
            : ''; // Use empty string if no data exists

        error_log("process_breakdance_updates: original_content_for_change_entry type " . $original_content_for_change_entry);

        if (!is_string($original_content_for_change_entry)) {
            do_action('miruni_plugin_error', new Exception(esc_html("Invalid original Breakdance data on draft")), [
                'context' => 'Breakdance Draft Manager',
                'operation' => 'Processing Breakdance updates - getting original data',
                'draft_id' => $draft_id,
                'parent_id' => $parent_id,
                'user_id' => get_current_user_id()
            ]);
            // Attempt to continue, but original content in change entry might be inaccurate
            $original_content_for_change_entry = '';
        }
        $changes = [];
        $other_breakdance_changes = []; // Store changes for other posts [target_post_id => data]

        foreach ($updates as $update) {
            $update_summary = $update['updateSummary'];
            error_log("process_breakdance_updates: update_summary: {$update_summary}");
            $file_identifier = $update['fileIdentifier']; // e.g., "breakdance_data_123"

            // Extract target post ID from identifier
            $target_post_id = 0;
            if ($file_identifier === "breakdance_json") {
                $target_post_id = $draft_id;
            }
            if (preg_match('/_(\d+)$/', $file_identifier, $matches)) {
                $target_post_id = (int) $matches[1];
            }

            error_log("process_breakdance_updates: target_post_id: {$target_post_id}, file_identifier: {$file_identifier}");

            if ($target_post_id <= 0) {
                do_action('miruni_plugin_error', new Exception(esc_html("Could not parse target post ID from Breakdance fileIdentifier: " . $file_identifier)), [
                    'context' => 'Breakdance Draft Manager',
                    'operation' => 'Processing Breakdance update - parse identifier',
                    'draft_id' => $draft_id,
                    'suggestion_id' => $update['id'],
                    'user_id' => get_current_user_id()
                ]);
                continue; // Skip this update if identifier is invalid
            }

            // Decode the updated content
            $decoded_data = json_decode($update['updatedFileContent'], true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                do_action('miruni_plugin_error', new Exception(esc_html("Invalid JSON in updatedFileContent for Breakdance data")), [
                    'context' => 'Breakdance Draft Manager',
                    'operation' => 'Processing Breakdance update - decode JSON',
                    'draft_id' => $draft_id,
                    'target_post_id' => $target_post_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
            }


            // Determine where to store the data
            if ($target_post_id === $parent_id) {
                // This update targets the main post being previewed
                $change_file_name = "Breakdance Page Data (Current Page)";
                $change_original_content = $original_content_for_change_entry;
                Miruni_Breakdance_Service::update_page_data(
                    $draft_id,
                    $decoded_data,
                );
            } else {
                // This update targets a different post
                $other_breakdance_changes[$target_post_id] = $update;
                $change_file_name = "Breakdance Page Data (Post ID: {$target_post_id})";

                // For other posts, we don't easily have the original content here, use placeholder
                // TODO: Potentially fetch original data for other posts if needed for diff view
                $change_original_content = Miruni_Breakdance_Service::get_page_data($target_post_id);
                if (!$change_original_content) {
                    $change_original_content = '';
                }
                // @phpstan-ignore function.impossibleType
                if (is_array($change_original_content) || is_object($change_original_content)) {
                    $change_original_content = json_encode($change_original_content);
                } else {
                    $change_original_content = ''; // Use empty string if no data exists
                }
            }

            // Create a change entry for this specific update suggestion
            $change = $this->draft_manager->create_change_entry( // Use main draft manager's method
                $change_file_name,
                $update_summary,
                (string) $change_original_content,
                $file_identifier, // Use the original identifier
                UpdateUtils\MiruniFileType::BREAKDANCE_DATA,
                ['referenced_post_id' => $target_post_id] // Add referenced post ID
            );
            $change["suggestion_id"] = $update["id"];
            $changes[] = $change;
        }

        // Apply changes for other posts to the draft's meta field
        if (!empty($other_breakdance_changes)) {
            foreach ($other_breakdance_changes as $post_id => $data) {
                error_log("process_breakdance_updates: Storing other Breakdance changes in meta - post_id: {$post_id}");
                try {
                    $original_content = Miruni_Breakdance_Service::get_page_data($post_id);
                    if (!$original_content) {
                        $original_content = [];
                    }
                    // sending the decoded version to update_meta_array_item since the stringifying is done in the function
                    $decoded_data = json_decode($data['updatedFileContent'], true);
                    if (json_last_error() !== JSON_ERROR_NONE) {
                        do_action('miruni_plugin_error', new Exception(esc_html("Invalid JSON in updatedFileContent for Breakdance data")), [
                            'context' => 'Breakdance Draft Manager',
                            'operation' => 'Processing Breakdance update - decode JSON',
                            'draft_id' => $draft_id,
                            'target_post_id' => $post_id,
                            'suggestion_id' => $data['id'],
                            'json_error' => json_last_error_msg(),
                            'user_id' => get_current_user_id()
                        ]);
                        continue; // Skip this update if JSON is invalid
                    }
                    $success = Miruni_Post_Meta_Utils::update_meta_array_item(
                        $draft_id,
                        Miruni_Preview_Meta_Keys::BREAKDANCE_DATA,
                        $post_id,
                        $decoded_data,
                        "Storing Breakdance Data change: {$post_id}"
                    );
                    if (!$success) {
                        throw new Exception("Failed to store Breakdance data for post ID: {$post_id}");
                    }
                    $changes[] = [
                        "file_name" => "Breakdance Page Data (Post ID: {$post_id})",
                        "changes_made" => $data['updateSummary'],
                        "original_content" => (string) json_encode($original_content),
                        "file_identifier" => $data['fileIdentifier'],
                        "file_type" => UpdateUtils\MiruniFileType::BREAKDANCE_DATA->value,
                        "suggestion_id" => $data['id'],
                        "referenced_post_id" => $post_id,
                    ];

                } catch (Exception $e) {
                    error_log("process_breakdance_updates: Exception while storing other Breakdance changes in meta: " . $e->getMessage());
                    do_action('miruni_plugin_error', $e, [
                        'context' => 'Breakdance Draft Manager',
                        'operation' => 'Storing Other Breakdance data changes in meta',
                        'draft_id' => $draft_id,
                        'user_id' => get_current_user_id()
                    ]);
                    // Decide if this is critical enough to return empty changes
                }

            }
        }

        $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;
    }
}
