<?php

namespace Miruni\BlockWidget;
use Miruni\Miruni_Preview_Meta_Keys;
use Exception;

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

class Miruni_Block_Widget_Manager
{
    /**
     * Summary of get_active_sidebar_locations
     * @param string $widget_id_full
     * @param array<mixed> $all_sidebars_data
     * @return array<string> Array of active sidebar locations where the widget is present.
     */
    public static function get_active_sidebar_locations(string $widget_id_full, array $all_sidebars_data): array
    {
        $locations = [];
        foreach ($all_sidebars_data as $sidebar_id => $widgets_in_sidebar) {
            // Skip inactive widgets and the internal array_version key
            if ($sidebar_id === 'wp_inactive_widgets' || $sidebar_id === 'array_version') {
                continue;
            }

            if (is_array($widgets_in_sidebar) && in_array($widget_id_full, $widgets_in_sidebar, true)) {
                $locations[] = $sidebar_id;
            }
        }
        return $locations;

    }
    /**
     * Get all widget data (custom HTML and block widgets).
     *
     * @return Miruni_Block_Widget[] Array of Miruni_Block_Widget objects.
     */
    public static function get_all_widgets_data(): array
    {
        $widgets_output = [];
        $custom_html_widgets = get_option('widget_custom_html', []);
        $block_widgets = get_option('widget_block', []);
        $sidebars_widgets = get_option('sidebars_widgets', []);


        // Process custom HTML widgets
        if (is_array($custom_html_widgets)) {
            foreach ($custom_html_widgets as $widget_instance_id => $widget_data) {
                if ($widget_instance_id === '_multiwidget' || !is_array($widget_data)) {
                    continue;
                }

                // WordPress stores custom HTML widget IDs in sidebars_widgets as "custom_html-X"
                $widget_id_full = "custom_html-{$widget_instance_id}";
                $sidebar_locations = Miruni_Block_Widget_Manager::get_active_sidebar_locations($widget_id_full, $sidebars_widgets);

                // Only include the widget if it's in at least one active sidebar
                if (!empty($sidebar_locations)) {
                    $widgets_output[] = new Miruni_Block_Widget(
                        $widget_id_full,
                        'custom_html',
                        $widget_data['title'] ?? '(No Title)',
                        $widget_data['content'] ?? '',
                        $sidebar_locations,
                        $widget_data
                    );
                }
            }
        }

        // Process block widgets
        if (is_array($block_widgets)) {
            foreach ($block_widgets as $widget_instance_id => $widget_data) {
                if ($widget_instance_id === '_multiwidget' || !is_array($widget_data)) {
                    continue;
                }

                $widget_id_full = "block-{$widget_instance_id}";
                $sidebar_locations = Miruni_Block_Widget_Manager::get_active_sidebar_locations($widget_id_full, $sidebars_widgets);

                // Only include the widget if it's in at least one active sidebar
                if (!empty($sidebar_locations)) {
                    $title = '(No Title)';
                    if (!empty($widget_data['content'])) {
                        // Attempt to get title from block comment attributes for heading blocks
                        if (preg_match('/<!-- wp:heading(?:[^}]*?)?{(?:[^}]*?)?"content":"([^"]*)"(?:[^}]*?)?} -->/s', $widget_data['content'], $matches_block_attr)) {
                            $title = wp_strip_all_tags($matches_block_attr[1]);
                        }
                        // Fallback: Basic title extraction from first H tag if block attribute not found or not a heading block
                        elseif (preg_match('/<h[1-6][^>]*>(.*?)<\/h[1-6]>/is', $widget_data['content'], $matches_html_tag)) {
                            $title = wp_strip_all_tags($matches_html_tag[1]);
                        }
                    }

                    $widgets_output[] = new Miruni_Block_Widget(
                        $widget_id_full,
                        'block',
                        $title,
                        $widget_data['content'] ?? '',
                        $sidebar_locations,
                        $widget_data
                    );
                }
            }
        }

        return $widgets_output;
    }


    /**
     * Get all sidebars data.
     *
     * @return array<string, array{
     *  name: string,
     *  widget_count: int<0,max>,
     *  widgets: array<string>
     * }> Associative array of sidebar data, keyed by sidebar ID.
     */
    public static function get_all_sidebars_data(): array
    {
        $sidebars_output = [];
        $sidebars_widgets = get_option('sidebars_widgets', []);
        global $wp_registered_sidebars;

        foreach ($sidebars_widgets as $sidebar_id => $widgets) {
            if ($sidebar_id === 'wp_inactive_widgets' || $sidebar_id === 'array_version') {
                continue;
            }

            $sidebars_output[$sidebar_id] = [
                'name' => $wp_registered_sidebars[$sidebar_id]['name'] ?? $sidebar_id,
                'widget_count' => is_array($widgets) ? count($widgets) : (int) 0,
                'widgets' => is_array($widgets) ? $widgets : [],
            ];
        }
        return $sidebars_output;
    }
    /**
     * Update the widget data for a specific preview ID.
     *
     * @param array<mixed> $existing_widget_data The existing widget data.
     * @param int $preview_id The preview ID.
     * @param string $option The option to update.
     * @return array<mixed>|null The updated widget data or null if no changes were made.
     */
    public static function update_widget_data(array $existing_widget_data, int $preview_id, string $option): array|null
    {
        $stored_widget_options = get_post_meta($preview_id, Miruni_Preview_Meta_Keys::BLOCK_WIDGET, true);

        // Add type checking and debugging
        if (!is_array($stored_widget_options)) {
            // If it's a string, try to parse it as JSON
            if (is_string($stored_widget_options)) {
                error_log("Stored widget options is a string, attempting JSON decode: " . $stored_widget_options);
                $parsed_options = json_decode($stored_widget_options, true);
                if (json_last_error() === JSON_ERROR_NONE && is_array($parsed_options)) {
                    $stored_widget_options = $parsed_options;
                    error_log("Successfully parsed JSON to array");
                } else {
                    error_log("Failed to parse JSON. Error: " . json_last_error_msg());
                    return null;
                }
            } else {
                error_log("Stored widget options is not an array or string. Type: " . gettype($stored_widget_options) . ", Value: " . var_export($stored_widget_options, true));
                return null;
            }
        }

        if (empty($stored_widget_options)) {
            error_log("Stored widget options is empty array.");
            return null;
        }

        $stored_widget_keys = array_keys($stored_widget_options);
        error_log("Stored widget keys: " . implode(', ', $stored_widget_keys));

        // @phpstan-ignore function.alreadyNarrowedType
        if (!is_array($existing_widget_data)) {
            error_log("Existing widget data is not an array or is empty. Returning existing data.");
            return $existing_widget_data;
        }

        foreach ($existing_widget_data as $widget_id => $widget_data) {
            $id_to_check = "{$option}-{$widget_id}";
            // get stored key ending with $id_to_check
            $stored_key = array_filter($stored_widget_keys, function ($key) use ($id_to_check) {
                return str_ends_with((string) $key, $id_to_check);
            });
            if (empty($stored_key)) {
                continue;
            }
            $stored_key = array_shift($stored_key);
            error_log("Updating widget ID: {$widget_id} with stored key: {$stored_key}");
            $existing_widget_data[$widget_id]['content'] = $stored_widget_options[$stored_key];
        }
        return $existing_widget_data;
    }

    public static function get_widget_data_by_id(string $widget_id): Miruni_Block_Widget|null
    {
        $all_widgets = self::get_all_widgets_data();
        error_log("Searching for widget ID: {$widget_id}");
        foreach ($all_widgets as $widget) {
            if (str_ends_with($widget_id, $widget->id)) {
                error_log("Found matching widget: {$widget->id}");
                return $widget;
            } else {
                error_log("No match for widget ID: {$widget->id} - Target ID: {$widget_id}");
            }
        }
        return null;
    }

}