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

/**
 * Safely read/write Classic Editor (TinyMCE) HTML content.
 *
 * Extracts and updates text content while preserving HTML structure.
 *
 * @since 2.1.3
 */
class AI_Magic_Classic_Processor
{

    /**
     * HTML tags that contain editable text content.
     *
     * @var array
     */
    private $text_tags = array(
        'h1',
        'h2',
        'h3',
        'h4',
        'h5',
        'h6',
        'p',
        'li',
        'td',
        'th',
        'figcaption',
        'blockquote',
        'dt',
        'dd',
    );

    /**
     * Get raw post_content.
     *
     * @param int $post_id
     * @return string
     */
    public function get_content($post_id)
    {
        return get_post_field('post_content', $post_id);
    }

    /**
     * Save updated content back to post.
     *
     * Uses wp_kses_post to sanitize HTML content.
     *
     * @param int    $post_id
     * @param string $content
     * @return int|WP_Error
     */
    public function save_content($post_id, $content)
    {
        return wp_update_post(array(
            'ID' => $post_id,
            'post_content' => wp_kses_post($content),
        ));
    }

    /**
     * Extract text content from HTML.
     *
     * @param string $content HTML content
     * @return array Array of text items
     */
    public function extract_texts($content)
    {
        $texts = array();

        if (empty($content) || !is_string($content)) {
            return $texts;
        }

        // Extract headings
        foreach (array('h1', 'h2', 'h3', 'h4', 'h5', 'h6') as $tag) {
            $pattern = '/<' . $tag . '([^>]*)>(.*?)<\/' . $tag . '>/is';
            if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) {
                foreach ($matches as $match) {
                    $plain_text = wp_strip_all_tags($match[2]);
                    if (strlen(trim($plain_text)) > 2) {
                        $texts[] = array(
                            'tag' => $tag,
                            'attrs' => $match[1],
                            'full' => $match[0],
                            'original' => $match[2],
                            'value' => $plain_text,
                            'type' => 'heading',
                        );
                    }
                }
            }
        }

        // Extract paragraphs
        $pattern = '/<p([^>]*)>(.*?)<\/p>/is';
        if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $plain_text = wp_strip_all_tags($match[2]);
                // Only include paragraphs with meaningful content
                if (strlen(trim($plain_text)) > 10) {
                    $texts[] = array(
                        'tag' => 'p',
                        'attrs' => $match[1],
                        'full' => $match[0],
                        'original' => $match[2],
                        'value' => $plain_text,
                        'type' => 'paragraph',
                    );
                }
            }
        }

        // Extract list items
        $pattern = '/<li([^>]*)>(.*?)<\/li>/is';
        if (preg_match_all($pattern, $content, $matches, PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                $plain_text = wp_strip_all_tags($match[2]);
                if (strlen(trim($plain_text)) > 5) {
                    $texts[] = array(
                        'tag' => 'li',
                        'attrs' => $match[1],
                        'full' => $match[0],
                        'original' => $match[2],
                        'value' => $plain_text,
                        'type' => 'list-item',
                    );
                }
            }
        }

        return $texts;
    }

    /**
     * Apply new text values back to HTML content.
     *
     * @param string $content    Original content
     * @param array  $texts      Items from extract_texts()
     * @param array  $new_values New text values
     * @return string Updated content
     */
    public function apply_new_texts($content, array $texts, array $new_values)
    {
        // Process from end to preserve offsets
        for ($i = count($texts) - 1; $i >= 0; $i--) {
            if (!isset($new_values[$i])) {
                continue;
            }

            $item = $texts[$i];
            $new_text = $new_values[$i];

            // Determine if we should preserve inline HTML or replace entirely
            $original = $item['original'];
            $old_text = $item['value'];

            // If original has HTML tags, try to preserve structure
            if ($original !== $old_text) {
                // Original had HTML - do simple text replacement within
                $new_inner = str_replace($old_text, esc_html($new_text), $original);
            } else {
                // Original was plain text
                $new_inner = esc_html($new_text);
            }

            // Build new full tag
            $new_full = '<' . $item['tag'] . $item['attrs'] . '>' . $new_inner . '</' . $item['tag'] . '>';

            // Replace in content
            $content = str_replace($item['full'], $new_full, $content);
        }

        return $content;
    }

    /**
     * Get supported text tags.
     *
     * @return array
     */
    public function get_text_tags()
    {
        return $this->text_tags;
    }

    /**
     * Add custom tag(s) to process.
     *
     * @param string|array $tags Tag name(s)
     * @return void
     */
    public function add_text_tags($tags)
    {
        if (is_string($tags)) {
            $tags = array($tags);
        }

        $this->text_tags = array_unique(array_merge($this->text_tags, $tags));
    }

}
