<?php
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Safely read/write Elementor content without breaking layout.
 *
 * Uses Elementor Document API when available (recommended approach),
 * falls back to direct meta updates when Elementor is not active.
 *
 * @since 2.1.0
 * @since 2.1.3 Added Document API support and extended text field types
 */
class AI_Magic_Elementor_Processor
{

    /**
     * Text field keys that contain user-editable content.
     * These are the only fields that should be modified by AI.
     *
     * @var array
     */
    private $text_fields = array(
        // Core text fields
        'title',              // Heading widget
        'editor',             // Text Editor widget (WYSIWYG)
        'text',               // Button/text widgets
        'content',            // Various widgets
        'html',               // HTML widget

        // Description fields
        'description',        // Image/Icon Box descriptions
        'description_text',   // Icon List descriptions
        'item_description',   // Price Table items

        // Animated headline
        'highlighted_text',   // Animated headline highlighted
        'before_text',        // Animated headline prefix
        'after_text',         // Animated headline suffix
        'rotating_text',      // Animated headline rotating words

        // Testimonial widget
        'testimonial_content', // Testimonial text
        'testimonial_name',    // Testimonial author name
        'testimonial_job',     // Testimonial job title

        // Alert widget
        'alert_title',        // Alert title
        'alert_description',  // Alert description

        // Call to Action widget
        'ribbon_title',       // CTA ribbon text

        // Blockquote
        'blockquote_content', // Quote content

        // Tabs/Accordion/Toggle
        'tab_title',          // Tab title
        'tab_content',        // Tab content
        'accordion_title',    // Accordion title
        'accordion_content',  // Accordion content

        // Counter widget
        'counter_title',      // Counter title

        // Progress bar
        'progress_title',     // Progress bar title

        // Price Table
        'price_table_heading',       // Price table heading
        'price_table_sub_heading',   // Price table subheading
        'price_table_description',   // Price table description
        'price_table_footer_additional_info', // Footer info

        // Form fields (labels only, not placeholders)
        'field_label',        // Form field label
    );

    /**
     * Get decoded _elementor_data structure.
     *
     * Uses Elementor Document API when available for proper data handling.
     *
     * @param int $post_id
     * @return array
     */
    public function get_raw_data($post_id)
    {
        // Try Elementor Document API first (handles data correctly)
        if ($this->is_elementor_available()) {
            $document = \Elementor\Plugin::$instance->documents->get($post_id);
            if ($document) {
                $elements = $document->get_elements_raw_data(null, true);
                if (is_array($elements) && !empty($elements)) {
                    return $elements;
                }
            }
        }

        // Fallback: Direct meta read
        $data = get_post_meta($post_id, '_elementor_data', true);
        if (empty($data)) {
            return array();
        }

        // Handle slashed data
        $data = wp_unslash($data);
        $decoded = json_decode($data, true);

        return is_array($decoded) ? $decoded : array();
    }

    /**
     * Save updated element structure.
     *
     * Uses Elementor Document API when available (recommended).
     * This ensures proper cache clearing and post_content sync.
     *
     * @param int   $post_id
     * @param array $elements
     * @return bool Success status
     */
    public function save_raw_data($post_id, $elements)
    {
        // Try Elementor Document API first (official, safe method)
        if ($this->is_elementor_available()) {
            $document = \Elementor\Plugin::$instance->documents->get($post_id);
            if ($document) {
                // Document save handles:
                // - JSON encoding
                // - Meta update with proper slashing
                // - post_content sync
                // - Cache clearing
                $document->save(array('elements' => $elements));
                return true;
            }
        }

        // Fallback: Direct meta update (when Elementor not active)
        $json = wp_json_encode($elements);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return false;
        }

        // wp_slash is required for update_post_meta with JSON
        update_post_meta($post_id, '_elementor_data', wp_slash($json));

        return true;
    }

    /**
     * Check if Elementor is available and usable.
     *
     * @return bool
     */
    private function is_elementor_available()
    {
        return class_exists('\Elementor\Plugin')
            && isset(\Elementor\Plugin::$instance->documents)
            && \Elementor\Plugin::$instance->documents;
    }

    /**
     * Walk Elementor elements tree and collect text nodes.
     *
     * Layout structure is left intact; only text values are exposed.
     *
     * Each collected item:
     *  - 'ref'   => reference to settings value (by reference)
     *  - 'type'  => field type (heading, editor, text, etc.)
     *  - 'value' => original text (plain for display)
     *  - 'html'  => original HTML content (for WYSIWYG fields)
     *
     * @param array $elements
     * @param array $texts
     * @return array
     */
    public function extract_texts(array &$elements, array &$texts = array())
    {

        foreach ($elements as &$el) {
            if (isset($el['settings']) && is_array($el['settings'])) {

                foreach ($el['settings'] as $key => &$val) {
                    // Only process known text fields
                    if (!in_array($key, $this->text_fields, true)) {
                        continue;
                    }

                    // Must be a non-empty string
                    if (!is_string($val) || trim($val) === '') {
                        continue;
                    }

                    // Determine if this is HTML content (WYSIWYG) or plain text
                    $is_html = in_array($key, array('editor', 'content', 'html', 'tab_content', 'accordion_content', 'testimonial_content', 'blockquote_content'), true);

                    $texts[] = array(
                        'ref' => &$val,
                        'type' => $key,
                        'value' => wp_strip_all_tags($val),
                        'html' => $is_html ? $val : null,
                    );
                }
            }

            // Nested inner elements (sections, columns, widgets)
            if (!empty($el['elements']) && is_array($el['elements'])) {
                $this->extract_texts($el['elements'], $texts);
            }
        }

        return $texts;
    }

    /**
     * Write AI-generated values back into referenced settings.
     *
     * @param array $texts      Items returned by extract_texts()
     * @param array $new_values Plain strings, same index order as $texts
     * @return void
     */
    public function apply_new_texts(array $texts, array $new_values)
    {
        foreach ($texts as $index => $item) {
            if (!isset($new_values[$index]) || !isset($item['ref'])) {
                continue;
            }

            $new_value = $new_values[$index];

            // For WYSIWYG fields, wrap plain text in paragraph if needed
            if (!empty($item['html']) && strpos($new_value, '<') === false) {
                // AI returned plain text for HTML field - wrap it
                $new_value = '<p>' . esc_html($new_value) . '</p>';
            }

            // Because 'ref' is a reference, this updates the element settings directly
            $item['ref'] = $new_value;
        }
    }

    /**
     * Get the list of supported text fields.
     *
     * @return array
     */
    public function get_text_fields()
    {
        return $this->text_fields;
    }

    /**
     * Add custom text field(s) to the processor.
     *
     * Useful for third-party Elementor widgets.
     *
     * @param string|array $fields Field name(s) to add
     * @return void
     */
    public function add_text_fields($fields)
    {
        if (is_string($fields)) {
            $fields = array($fields);
        }

        $this->text_fields = array_unique(array_merge($this->text_fields, $fields));
    }

}
