<?php
/**
 * Comment Image Boost
 * Permite anexo de imagens nos comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rios do WordPress
 *
 * @package CommentImageBoost
 * @author AuditySEO
 * @link https://www.audityseo.com/
 * @version 1.0.16
 */

if (!defined('ABSPATH')) {
    die('You are not allowed to call this page directly.');
}

/**
 * Classe principal para gerenciar imagens em comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rios
 */
class CIBOOST_Comment_Images {

    /**
     * Meta key para armazenar ID da imagem
     */
    const META_KEY = 'ciboost_comment_image_id';

    /**
     * Meta key para armazenar legendas por imagem
     */
    const CAPTIONS_META_KEY = 'ciboost_comment_image_captions';

    /**
     * Meta key para armazenar status de moderaÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â§ÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â£o por imagem
     */
    const STATUS_META_KEY = 'ciboost_comment_image_status';

    /**
     * Meta key para armazenar IDs de anexos da Media Library por imagem
     */
    const ATTACHMENTS_META_KEY = 'ciboost_comment_image_attachments';

    /**
     * Nome do campo de upload
     */
    const FIELD_NAME = 'ciboost_comment_image';

    /**
     * OpÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âµes do plugin
     */
    private $options = array();

    /**
     * Construtor
     */
    public function __construct() {
        try {
            add_action('init', array($this, 'init_hooks'));
        } catch (Exception $e) {
            ciboost_log('Error in CIBOOST_Comment_Images constructor: ' . $e->getMessage());
        }
    }

    /**
     * Inicializa hooks
     */
    public function init_hooks() {
        try {
            $this->load_options();

            if (!$this->is_enabled()) {
                return;
            }

            // Frontend
            add_action('comment_form_submit_field', array($this, 'add_image_field'));
            add_filter('preprocess_comment', array($this, 'validate_image'));
            add_action('comment_post', array($this, 'save_image'), 10, 3);
            add_filter('comment_text', array($this, 'display_image'), 10, 2);
            add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));

            // Admin
            add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_styles'));
            add_filter('comment_text', array($this, 'display_image_admin'), 10, 2);
            add_action('add_meta_boxes_comment', array($this, 'add_comment_meta_box'));
            add_action('edit_comment', array($this, 'save_comment_images_moderation'));

            // Deletar imagens quando comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio for deletado
            add_action('delete_comment', array($this, 'delete_image_on_comment_delete'));

        } catch (Exception $e) {
            ciboost_log('Error in init_hooks: ' . $e->getMessage());
        }
    }

    /**
     * Carrega opÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âµes do banco de dados
     */
    private function load_options() {
        try {
            $defaults = array(
                'enabled' => true,
                'max_size_mb' => 2,
                'image_size' => 'medium',
                'required' => false,
                'allow_multiple' => false,
                'preview_size' => 120,
                'display_layout' => 'vertical',
                'allowed_formats' => array('jpg', 'jpeg', 'png', 'webp', 'avif'),
                'lazy_loading' => true,
                'enable_captions' => false,
                'enable_lightbox' => true,
                'image_position' => 'after',
                'gallery_columns' => 4,
                'enabled_post_types' => array(),
                'enabled_categories' => array(),
                'soft_moderation' => true,
                'save_to_media_library' => false,
                'strip_metadata' => true,
                'show_badge' => true,
                'gallery_layout' => 'grid',
            );

            $saved_options = get_option('ciboost_comment_images', array());
            $this->options = wp_parse_args($saved_options, $defaults);

            if (!ciboost_can_use_premium_features()) {
                $this->options['required'] = false;
                $this->options['allow_multiple'] = false;
                $this->options['enable_captions'] = false;
                $this->options['enabled_categories'] = array();
                $this->options['max_size_mb'] = min(absint($this->options['max_size_mb']), 2);
                $this->options['display_layout'] = 'vertical';
                $this->options['gallery_layout'] = 'grid';
                $this->options['allowed_formats'] = array_values(array_intersect(
                    (array) $this->options['allowed_formats'],
                    array('jpg', 'jpeg', 'png')
                ));

                if (empty($this->options['allowed_formats'])) {
                    $this->options['allowed_formats'] = array('jpg', 'jpeg', 'png');
                }
            }

        } catch (Exception $e) {
            ciboost_log('Error loading options: ' . $e->getMessage());
            $this->options = array();
        }
    }

    /**
     * Verifica se uploads devem aparecer no post atual.
     */
    private function should_enable_for_post($post_id = 0) {
        try {
            $post = $post_id ? get_post($post_id) : get_post();

            if (!$post) {
                return true;
            }

            $enabled_post_types = (array) $this->get_option('enabled_post_types', array());
            if (!empty($enabled_post_types) && !in_array($post->post_type, $enabled_post_types, true)) {
                return false;
            }

            $enabled_categories = array_filter(array_map('absint', (array) $this->get_option('enabled_categories', array())));
            if (!empty($enabled_categories) && $post->post_type === 'post') {
                $post_categories = wp_get_post_categories($post->ID);
                if (empty(array_intersect($enabled_categories, $post_categories))) {
                    return false;
                }
            }

            return true;

        } catch (Exception $e) {
            ciboost_log('Error checking post scope: ' . $e->getMessage());
            return true;
        }
    }

    /**
     * Enfileira assets compartilhados do frontend.
     */
    private function enqueue_assets() {
        $assets_url = defined('CIBOOST_PLUGIN_URL') ? CIBOOST_PLUGIN_URL : plugin_dir_url(dirname(__FILE__));
        $version = defined('CIBOOST_VERSION') ? CIBOOST_VERSION : '1.0.16';

        wp_enqueue_style(
            'ciboost-comment-images',
            $assets_url . 'assets/css/comment-images.css',
            array(),
            $version
        );

        wp_enqueue_script(
            'ciboost-comment-images',
            $assets_url . 'assets/js/comment-images.js',
            array('jquery'),
            $version,
            true
        );

        $allowed_formats = $this->get_option('allowed_formats', array('jpg', 'jpeg', 'png', 'webp', 'avif'));

        wp_localize_script('ciboost-comment-images', 'ciboostCommentImages', array(
            'formNotFound' => __('Comment form not found.', 'comment-image-boost'),
            'previewSize' => $this->get_option('preview_size', 120),
            'allowedFormats' => $allowed_formats,
            'allowMultiple' => (bool) $this->get_option('allow_multiple', false),
            'captionsEnabled' => (bool) $this->get_option('enable_captions', false),
            'captionPlaceholder' => __('Add a short caption', 'comment-image-boost'),
            'lightboxEnabled' => (bool) $this->get_option('enable_lightbox', true),
            'invalidFormatMsg' => sprintf(
                /* translators: %s: comma-separated list of allowed image formats. */
                __('Please select only these image formats: %s.', 'comment-image-boost'),
                $this->get_formats_text($allowed_formats)
            )
        ));
    }

    /**
     * Verifica se a funcionalidade estÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡ habilitada
     */
    private function is_enabled() {
        try {
            return !empty($this->options['enabled']);
        } catch (Exception $e) {
            ciboost_log('Error checking if enabled: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m uma opÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o especÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fica
     */
    private function get_option($key, $default = null) {
        try {
            return isset($this->options[$key]) ? $this->options[$key] : $default;
        } catch (Exception $e) {
            ciboost_log('Error getting option: ' . $e->getMessage());
            return $default;
        }
    }

    /**
     * Enfileira scripts e estilos
     */
    public function enqueue_scripts() {
        try {
            if (!is_singular() || !comments_open() || !$this->should_enable_for_post(get_the_ID())) {
                return;
            }

            $this->enqueue_assets();

        } catch (Exception $e) {
            ciboost_log('Error enqueuing scripts: ' . $e->getMessage());
        }
    }

    /**
     * Adiciona campo de imagem ao formulÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio de comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rios
     */
    public function add_image_field($submit_field) {
        try {
            if (!$this->should_enable_for_post(get_the_ID())) {
                return $submit_field;
            }

            $allowed_formats = $this->get_option('allowed_formats', array('jpg', 'jpeg', 'png', 'webp', 'avif'));
            $accept_types = $this->get_accept_types($allowed_formats);
            $formats_text = $this->get_formats_text($allowed_formats);

            ob_start();
            wp_nonce_field('ciboost_comment_image_upload', 'ciboost_comment_image_nonce');
            ?>
            <p class="ciboost-comment-form-image">
                <label for="ciboost_comment_image">
                    <?php
                    if ($this->get_option('allow_multiple')) {
                        esc_html_e('Images', 'comment-image-boost');
                    } else {
                        esc_html_e('Image', 'comment-image-boost');
                    }
                    ?>
                    <?php if ($this->get_option('required')): ?>
                        <span class="required">*</span>
                    <?php endif; ?>
                </label>
                <input
                    class="ciboost-comment-image-input"
                    id="ciboost_comment_image"
                    name="<?php echo esc_attr(self::FIELD_NAME . ($this->get_option('allow_multiple') ? '[]' : '')); ?>"
                    type="file"
                    accept="<?php echo esc_attr($accept_types); ?>"
                    <?php if ($this->get_option('allow_multiple')): ?>
                        multiple
                    <?php endif; ?>
                />
                <span class="ciboost-image-size-notice">
                    <?php
                    $max_size = $this->get_max_upload_size_formatted();
                    /* translators: %s: maximum upload size. */
                    printf(esc_html__('Maximum file size: %s.', 'comment-image-boost'), esc_html($max_size));
                    ?>
                    <br>
                    <?php
                    /* translators: %s: comma-separated list of allowed image formats. */
                    printf(esc_html__('Allowed formats: %s.', 'comment-image-boost'), esc_html($formats_text));
                    ?>
                </span>
                <span class="ciboost-drop-area">
                    <span class="ciboost-drop-area-inner">
                        <?php
                        if ($this->get_option('allow_multiple')) {
                            esc_html_e('Drop images here', 'comment-image-boost');
                        } else {
                            esc_html_e('Drop image here', 'comment-image-boost');
                        }
                        ?>
                    </span>
                </span>
                <?php if ($this->get_option('enable_captions')): ?>
                    <span class="ciboost-caption-template" hidden>
                        <input type="text" name="ciboost_comment_image_caption[]" maxlength="160" placeholder="<?php esc_attr_e('Add a short caption', 'comment-image-boost'); ?>">
                    </span>
                <?php endif; ?>
            </p>
            <?php
            $image_field = ob_get_clean();
            return $image_field . $submit_field;

        } catch (Exception $e) {
            ciboost_log('Error adding image field: ' . $e->getMessage());
            return $submit_field;
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m tipos MIME para o atributo accept
     */
    private function get_accept_types($formats) {
        try {
            $mime_types = array(
                'jpg' => 'image/jpeg',
                'jpeg' => 'image/jpeg',
                'png' => 'image/png',
                'webp' => 'image/webp',
                'avif' => 'image/avif'
            );

            $accept = array();
            foreach ($formats as $format) {
                if (isset($mime_types[$format]) && !in_array($mime_types[$format], $accept)) {
                    $accept[] = $mime_types[$format];
                }
            }

            return implode(',', $accept);
        } catch (Exception $e) {
            ciboost_log('Error getting accept types: ' . $e->getMessage());
            return 'image/jpeg,image/png,image/webp,image/avif';
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m texto formatado dos formatos permitidos
     */
    private function get_formats_text($formats) {
        try {
            $labels = array(
                'jpg' => 'JPG',
                'jpeg' => 'JPEG',
                'png' => 'PNG',
                'webp' => 'WebP',
                'avif' => 'AVIF'
            );

            $text = array();
            foreach ($formats as $format) {
                if (isset($labels[$format])) {
                    $text[] = $labels[$format];
                }
            }

            return implode(', ', array_unique($text));
        } catch (Exception $e) {
            ciboost_log('Error getting formats text: ' . $e->getMessage());
            return 'JPG, PNG, WebP, AVIF';
        }
    }

    /**
     * Normalizes a single or multiple upload field into sanitized file entries.
     *
     * @param string $field_name File input name.
     * @return array
     */
    private function get_uploaded_files($field_name) {
        // phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // This helper is called only after nonce verification. Do not unslash tmp_name paths.
        if (!isset($_FILES[$field_name]) || !is_array($_FILES[$field_name])) {
            return array();
        }

        $raw_names = isset($_FILES[$field_name]['name']) ? $_FILES[$field_name]['name'] : array();
        $raw_tmp_names = isset($_FILES[$field_name]['tmp_name']) ? $_FILES[$field_name]['tmp_name'] : array();
        $raw_errors = isset($_FILES[$field_name]['error']) ? $_FILES[$field_name]['error'] : array();
        $raw_types = isset($_FILES[$field_name]['type']) ? $_FILES[$field_name]['type'] : array();
        $raw_sizes = isset($_FILES[$field_name]['size']) ? $_FILES[$field_name]['size'] : array();
        // phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

        $file_names = is_array($raw_names) ? $raw_names : array($raw_names);
        $file_tmp_names = is_array($raw_tmp_names) ? $raw_tmp_names : array($raw_tmp_names);
        $file_errors = is_array($raw_errors) ? $raw_errors : array($raw_errors);
        $file_types = is_array($raw_types) ? $raw_types : array($raw_types);
        $file_sizes = is_array($raw_sizes) ? $raw_sizes : array($raw_sizes);

        $uploaded_files = array();
        $file_count = max(count($file_names), count($file_tmp_names), count($file_errors), count($file_types), count($file_sizes));

        for ($key = 0; $key < $file_count; $key++) {
            $name = (isset($file_names[$key]) && is_scalar($file_names[$key])) ? sanitize_file_name((string) $file_names[$key]) : '';
            $error = (isset($file_errors[$key]) && is_numeric($file_errors[$key])) ? absint($file_errors[$key]) : UPLOAD_ERR_NO_FILE;
            $type = (isset($file_types[$key]) && is_scalar($file_types[$key])) ? sanitize_mime_type((string) $file_types[$key]) : '';
            $tmp_name = (isset($file_tmp_names[$key]) && is_scalar($file_tmp_names[$key])) ? sanitize_text_field((string) $file_tmp_names[$key]) : '';
            $size = (isset($file_sizes[$key]) && is_numeric($file_sizes[$key])) ? absint($file_sizes[$key]) : 0;

            if ($name === '' && $error === UPLOAD_ERR_NO_FILE) {
                continue;
            }

            $uploaded_files[] = array(
                'name' => $name,
                'type' => $type,
                'tmp_name' => $tmp_name,
                'error' => $error,
                'size' => $size,
            );
        }

        return $uploaded_files;
    }

    /**
     * Valida a imagem antes de processar o comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio
     */
    public function validate_image($commentdata) {
        try {
            $field_name = self::FIELD_NAME;
            $post_id = !empty($commentdata['comment_post_ID']) ? absint($commentdata['comment_post_ID']) : 0;

            if (!$this->should_enable_for_post($post_id)) {
                return $commentdata;
            }

            $has_valid_nonce = isset($_POST['ciboost_comment_image_nonce']) &&
                wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['ciboost_comment_image_nonce'])), 'ciboost_comment_image_upload');

            if (!$has_valid_nonce) {
                if ($this->get_option('required')) {
                    wp_die(
                        '<p><strong>' . esc_html__('ERROR', 'comment-image-boost') . '</strong>: ' .
                        esc_html__('Invalid image submission.', 'comment-image-boost') . '</p>',
                        esc_html__('Comment Submission Failure', 'comment-image-boost'),
                        array('back_link' => true)
                    );
                }
                return $commentdata;
            }

            $uploaded_files = $this->get_uploaded_files($field_name);

            // Verifica se o arquivo foi enviado
            if (empty($uploaded_files)) {
                if ($this->get_option('required')) {
                    wp_die(
                        '<p><strong>' . esc_html__('ERROR', 'comment-image-boost') . '</strong>: ' .
                        esc_html__('Image is required.', 'comment-image-boost') . '</p>',
                        esc_html__('Comment Submission Failure', 'comment-image-boost'),
                        array('back_link' => true)
                    );
                }
                return $commentdata;
            }



            // Valida cada arquivo
            $allowed_formats = $this->get_option('allowed_formats', array('jpg', 'jpeg', 'png', 'webp', 'avif'));
            $max_size = $this->get_max_upload_size();
            $formats_text = $this->get_formats_text($allowed_formats);

            foreach ($uploaded_files as $file) {
                // Pula arquivos vazios
                if (empty($file['name'])) {
                    continue;
                }

                // Verifica erros de upload
                if ($file['error'] !== UPLOAD_ERR_OK) {
                    $error_msg = $this->get_upload_error_message($file['error']);
                    wp_die(
                        '<p><strong>' . esc_html__('ERROR', 'comment-image-boost') . '</strong>: ' . esc_html($error_msg) . '</p>',
                        esc_html__('Comment Submission Failure', 'comment-image-boost'),
                        array('back_link' => true)
                    );
                }

                if (empty($file['tmp_name']) || !is_uploaded_file($file['tmp_name'])) {
                    wp_die(
                        '<p><strong>' . esc_html__('ERROR', 'comment-image-boost') . '</strong>: ' .
                        esc_html__('Invalid image upload.', 'comment-image-boost') . '</p>',
                        esc_html__('Comment Submission Failure', 'comment-image-boost'),
                        array('back_link' => true)
                    );
                }

                // Valida tamanho
                if ($file['size'] > $max_size) {
                    $error_msg = sprintf(
                        /* translators: %s: maximum file size */
                        esc_html__('The file is too large. Maximum allowed size is %s.', 'comment-image-boost'),
                        esc_html($this->get_max_upload_size_formatted())
                    );
                    wp_die(
                        '<p><strong>' . esc_html__('ERROR', 'comment-image-boost') . '</strong>: ' . esc_html($error_msg) . '</p>',
                        esc_html__('Comment Submission Failure', 'comment-image-boost'),
                        array('back_link' => true)
                    );
                }

                // Valida tipo real e extensao do arquivo.
                $filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name']);
                if (empty($filetype['ext']) || !in_array($filetype['ext'], $allowed_formats, true)) {
                    $error_msg = sprintf(
                        /* translators: %s: list of allowed formats */
                        esc_html__('Only these image formats are allowed: %s.', 'comment-image-boost'),
                        esc_html($formats_text)
                    );
                    wp_die(
                        '<p><strong>' . esc_html__('ERROR', 'comment-image-boost') . '</strong>: ' . esc_html($error_msg) . '</p>',
                        esc_html__('Comment Submission Failure', 'comment-image-boost'),
                        array('back_link' => true)
                    );
                }
            }

            return $commentdata;

        } catch (Exception $e) {
            ciboost_log('Error validating image: ' . $e->getMessage());
            return $commentdata;
        }
    }

    /**
     * Normaliza texto para usar em nome de arquivo
     * Remove caracteres especiais, converte para lowercase, substitui espaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§os por hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fens
     *
     * @param string $text Texto para normalizar
     * @return string Texto normalizado
     */
    private function normalize_filename_text($text) {
        try {
            if ($text === null) {
                $text = '';
            }

            // Remove tags HTML
            $text = wp_strip_all_tags((string) $text);

            // Remove acentos e caracteres especiais
            $text = remove_accents($text);

            // Converte para minÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºsculas
            $text = strtolower($text);

            // Remove caracteres que nÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o sÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o letras, nÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºmeros, espaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§os ou hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fens
            $text = preg_replace('/[^a-z0-9\s\-]/', '', $text);

            // Substitui mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºltiplos espaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§os por um ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºnico espaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§o
            $text = preg_replace('/\s+/', ' ', $text);

            // Substitui espaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§os por hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fens
            $text = str_replace(' ', '-', $text);

            // Remove hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fens mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºltiplos
            $text = preg_replace('/-+/', '-', $text);

            // Remove hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fens do inÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­cio e fim
            $text = trim($text, '-');

            return $text;

        } catch (Exception $e) {
            ciboost_log('Error normalizing filename text: ' . $e->getMessage());
            return 'image';
        }
    }

    /**
     * Gets the related post title for generic filename and alt text generation.
     *
     * @param int $post_id Post ID.
     * @return string Normalized post title or empty string.
     */
    private function get_post_title($post_id) {
        try {
            $post = get_post($post_id);

            if (!$post || empty($post->post_title)) {
                return '';
            }

            return $this->normalize_filename_text($post->post_title);

        } catch (Exception $e) {
            ciboost_log('Error extracting post title: ' . $e->getMessage());
            return '';
        }
    }

    /**
     * Gera nome de arquivo personalizado baseado no post + autor
     *
     * @param object $comment Objeto do comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio
     * @param int $index ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Ândice do arquivo (para mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºltiplos uploads)
     * @param string $extension ExtensÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o do arquivo
     * @return string Nome do arquivo gerado
     */
    private function generate_custom_filename($comment, $index, $extension) {
        try {
            // ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m o nome do autor do comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio
            $author_name = '';
            if (!empty($comment->comment_author)) {
                $author_name = $this->normalize_filename_text($comment->comment_author);
            }

            // ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m o tÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­tulo do post
            $post_title = '';
            if (!empty($comment->comment_post_ID)) {
                $post_title = $this->get_post_title($comment->comment_post_ID);
            }

            // Monta o nome do arquivo
            $filename_parts = array();

            if (!empty($post_title)) {
                $filename_parts[] = $post_title;
            }

            if (!empty($author_name)) {
                $filename_parts[] = $author_name;
            }

            // Se nÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o conseguiu montar nome personalizado, usa fallback
            if (empty($filename_parts)) {
                $filename_parts[] = 'comment-image';
                $filename_parts[] = $comment->comment_ID;
            }

            // Junta as partes com hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fen
            $base_name = implode('-', $filename_parts);

            // Adiciona apenas o ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­ndice (sem timestamp)
            // Nome final: post-title-author-name-index.ext
            $final_name = $base_name . '-' . $index . '.' . $extension;

            return $final_name;

        } catch (Exception $e) {
            ciboost_log('Error generating custom filename: ' . $e->getMessage());
            // Fallback para nome genÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©rico
            return 'image-' . time() . '-' . $index . '.' . $extension;
        }
    }

    /**
     * Salva a imagem apÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â³s o comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio ser postado
     */
    public function save_image($comment_id, $comment_approved, $commentdata) {
        try {
            $field_name = self::FIELD_NAME;
            $post_id = !empty($commentdata['comment_post_ID']) ? absint($commentdata['comment_post_ID']) : 0;

            if (!$this->should_enable_for_post($post_id)) {
                return;
            }

            if (!isset($_POST['ciboost_comment_image_nonce']) ||
                !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['ciboost_comment_image_nonce'])), 'ciboost_comment_image_upload')) {
                return;
            }

            $uploaded_files = $this->get_uploaded_files($field_name);
            if (empty($uploaded_files)) {
                return;
            }

            // ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m o objeto do comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio completo
            $comment = get_comment($comment_id);
            if (!$comment) {
                // Cria objeto fake com dados bÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡sicos para nÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o quebrar
                $comment = (object) array(
                    'comment_ID' => $comment_id,
                    'comment_post_ID' => !empty($commentdata['comment_post_ID']) ? $commentdata['comment_post_ID'] : 0,
                    'comment_author' => !empty($commentdata['comment_author']) ? $commentdata['comment_author'] : '',
                );
            }

            // Define diretÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â³rio de upload
            $upload_dir = ciboost_get_comment_images_upload_dir();

            // Garante que o diretÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â³rio existe
            if (!file_exists($upload_dir)) {
                wp_mkdir_p($upload_dir);
            }

            $caption_input = isset($_POST['ciboost_comment_image_caption']) ? array_map('sanitize_text_field', (array) wp_unslash($_POST['ciboost_comment_image_caption'])) : array();

            $saved_files = array();
            $saved_captions = array();
            $saved_statuses = array();
            $saved_attachments = array();

            // Ensure wp_handle_upload is available (may not be loaded on frontend)
            if (!function_exists('wp_handle_upload')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }

            // Processa cada arquivo
            foreach ($uploaded_files as $key => $file) {
                // Pula arquivos vazios
                if (empty($file['name'])) {
                    continue;
                }

                // Verifica erros
                if ($file['error'] !== UPLOAD_ERR_OK) {
                    continue;
                }

                if (empty($file['tmp_name']) || !is_uploaded_file($file['tmp_name'])) {
                    continue;
                }

                // ObtÃƒÆ’Ã†'Ãƒâ€šÃ‚Â©m extensÃƒÆ’Ã†'Ãƒâ€šÃ‚Â£o do arquivo
                $filetype = wp_check_filetype_and_ext($file['tmp_name'], $file['name']);
                if (empty($filetype['ext'])) {
                    continue;
                }
                $file_ext = sanitize_key($filetype['ext']);

                // Gera nome personalizado baseado no post + autor
                $desired_name = sanitize_file_name($this->generate_custom_filename($comment, $key, $file_ext));

                // Build single-file array for wp_handle_upload
                $single_file = array(
                    'name'     => $desired_name,
                    'type'     => $file['type'],
                    'tmp_name' => $file['tmp_name'],
                    'error'    => $file['error'],
                    'size'     => $file['size'],
                );

                $upload_url = ciboost_get_comment_images_upload_url();

                // Temporarily redirect uploads to the plugin custom directory.
                // Keep wp_upload_dir() calls outside this filter to avoid recursive upload_dir hooks.
                $ciboost_upload_dir_override = function($uploads) use ($upload_dir, $upload_url) {
                    $uploads['path']   = untrailingslashit($upload_dir);
                    $uploads['url']    = untrailingslashit($upload_url);
                    $uploads['subdir'] = '';
                    return $uploads;
                };
                add_filter('upload_dir', $ciboost_upload_dir_override);

                $result = wp_handle_upload($single_file, array(
                    'test_form' => false,
                    'action'    => 'wp_handle_upload',
                ));

                remove_filter('upload_dir', $ciboost_upload_dir_override);

                if (!empty($result['file']) && empty($result['error'])) {
                    $file_path = $result['file'];
                    $unique_name = sanitize_file_name(basename($file_path));

                    if ($this->get_option('strip_metadata', true) && function_exists('ciboost_strip_image_metadata')) {
                        ciboost_strip_image_metadata($file_path);
                    }

                    $saved_files[] = $unique_name;

                    if ($this->get_option('enable_captions') && isset($caption_input[$key])) {
                        $caption = $caption_input[$key]; // Already sanitized at access
                        if ($caption !== '') {
                            $saved_captions[$unique_name] = sanitize_text_field(function_exists('mb_substr') ? mb_substr($caption, 0, 160) : substr($caption, 0, 160));
                        }
                    }

                    $saved_statuses[$unique_name] = 'approved';

                    if ($this->get_option('save_to_media_library', false)) {
                        $attachment_id = $this->insert_media_attachment($file_path, $unique_name, $comment);
                        if ($attachment_id) {
                            $saved_attachments[$unique_name] = $attachment_id;
                        }
                    }
                }
            }

            // Salva os nomes dos arquivos como comment meta
            if (!empty($saved_files)) {
                // Se apenas 1 arquivo, salva como string; se mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºltiplos, salva como array
                $meta_value = (count($saved_files) === 1) ? $saved_files[0] : $saved_files;
                update_comment_meta($comment_id, self::META_KEY, $meta_value);
                if (!empty($saved_captions)) {
                    update_comment_meta($comment_id, self::CAPTIONS_META_KEY, $saved_captions);
                }

                if (!empty($saved_statuses)) {
                    update_comment_meta($comment_id, self::STATUS_META_KEY, $saved_statuses);
                }

                if (!empty($saved_attachments)) {
                    update_comment_meta($comment_id, self::ATTACHMENTS_META_KEY, $saved_attachments);
                }
            }

        } catch (Exception $e) {
            ciboost_log('Error saving image: ' . $e->getMessage());
        }
    }

    /**
     * Gera texto alt personalizado para a imagem
     *
     * @param object $comment Objeto do comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio
     * @return string Texto alt formatado
     */
    private function generate_image_alt($comment) {
        try {
            // ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m o tÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­tulo do post
            $post_title = '';
            if (!empty($comment->comment_post_ID)) {
                $post_title = $this->get_post_title($comment->comment_post_ID);
            }

            // ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m o nome do autor
            $author_name = '';
            if (!empty($comment->comment_author)) {
                $author_name = $this->normalize_filename_text($comment->comment_author);
            }

            // Monta o alt text
            $alt_parts = array();

            if (!empty($post_title)) {
                // Converte hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fens de volta para espaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§os e capitaliza primeira letra de cada palavra
                $post_title_readable = ucwords(str_replace('-', ' ', $post_title));
                $alt_parts[] = $post_title_readable;
            }

            if (!empty($author_name)) {
                // Converte hÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­fens de volta para espaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§os e capitaliza primeira letra de cada palavra
                $author_name_readable = ucwords(str_replace('-', ' ', $author_name));
                $alt_parts[] = $author_name_readable;
            }

            if (empty($alt_parts)) {
                return 'Comment image';
            }

            return implode(' - ', $alt_parts);

        } catch (Exception $e) {
            ciboost_log('Error generating image alt: ' . $e->getMessage());
            return 'Comment image';
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â©m legendas salvas para imagens do comentÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¡rio.
     */
    private function get_image_captions($comment_id) {
        $captions = get_comment_meta($comment_id, self::CAPTIONS_META_KEY, true);
        if (!is_array($captions)) {
            return array();
        }

        $sanitized = array();
        foreach ($captions as $filename => $caption) {
            $filename = sanitize_file_name($filename);
            if ($filename !== '' && is_scalar($caption)) {
                $sanitized[$filename] = sanitize_text_field((string) $caption);
            }
        }

        return $sanitized;
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â©m status salvos para imagens do comentÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¡rio.
     */
    private function get_image_statuses($comment_id) {
        $statuses = get_comment_meta($comment_id, self::STATUS_META_KEY, true);
        if (!is_array($statuses)) {
            return array();
        }

        $sanitized = array();
        foreach ($statuses as $filename => $status) {
            $filename = sanitize_file_name($filename);
            $status = is_scalar($status) ? sanitize_key((string) $status) : 'approved';
            if ($filename !== '' && in_array($status, array('approved', 'pending', 'rejected'), true)) {
                $sanitized[$filename] = $status;
            }
        }

        return $sanitized;
    }

    /**
     * Obtem anexos salvos para imagens do comentario.
     */
    private function get_image_attachments($comment_id) {
        $attachments = get_comment_meta($comment_id, self::ATTACHMENTS_META_KEY, true);
        if (!is_array($attachments)) {
            return array();
        }

        $sanitized = array();
        foreach ($attachments as $filename => $attachment_id) {
            $filename = sanitize_file_name($filename);
            $attachment_id = absint($attachment_id);
            if ($filename !== '' && $attachment_id > 0) {
                $sanitized[$filename] = $attachment_id;
            }
        }

        return $sanitized;
    }

    /**
     * Sanitizes a space-separated HTML class list.
     *
     * @param string $classes Class list.
     * @return string
     */
    private function sanitize_html_class_list($classes) {
        $classes = preg_split('/\s+/', (string) $classes);
        $classes = array_filter(array_map('sanitize_html_class', $classes));

        return implode(' ', $classes);
    }

    /**
     * Registra uma imagem salva como anexo da Media Library e gera thumbnails do WordPress.
     */
    private function insert_media_attachment($file_path, $filename, $comment) {
        if (!file_exists($file_path)) {
            return 0;
        }

        $filetype = wp_check_filetype($filename);
        if (empty($filetype['type'])) {
            return 0;
        }

        $post_parent = !empty($comment->comment_post_ID) ? absint($comment->comment_post_ID) : 0;
        $title = preg_replace('/\.[^.]+$/', '', $filename);
        $title = ucwords(str_replace('-', ' ', sanitize_title($title)));

        $attachment = array(
            'post_mime_type' => $filetype['type'],
            'post_title' => $title,
            'post_content' => '',
            'post_status' => 'inherit',
            'post_parent' => $post_parent,
        );

        $attachment_id = wp_insert_attachment($attachment, $file_path, $post_parent, true);
        if (is_wp_error($attachment_id) || !$attachment_id) {
            ciboost_log('Error inserting Media Library attachment: ' . (is_wp_error($attachment_id) ? $attachment_id->get_error_message() : $filename));
            return 0;
        }

        update_post_meta($attachment_id, '_ciboost_comment_id', absint($comment->comment_ID));
        update_post_meta($attachment_id, '_ciboost_comment_image_filename', sanitize_file_name($filename));

        if (!function_exists('wp_generate_attachment_metadata')) {
            require_once ABSPATH . 'wp-admin/includes/image.php';
        }

        $metadata = wp_generate_attachment_metadata($attachment_id, $file_path);
        if (!is_wp_error($metadata) && !empty($metadata)) {
            wp_update_attachment_metadata($attachment_id, $metadata);
        }

        return absint($attachment_id);
    }

    /**
     * Verifica se uma imagem pode ser exibida publicamente.
     */
    private function is_image_public($comment_id, $filename) {
        $statuses = $this->get_image_statuses($comment_id);
        $status = isset($statuses[$filename]) ? $statuses[$filename] : 'approved';
        return $status === 'approved';
    }

    /**
     * Renderiza uma imagem compartilhada por comentÃƒÆ’Ã†â€™Ãƒâ€ Ã¢â‚¬â„¢ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚Â¡rios e shortcodes.
     */
    private function render_image_item($comment, $filename, $args = array()) {
        $filename = sanitize_file_name($filename);
        if ($filename === '') {
            return '';
        }

        $defaults = array(
            'max_width' => 300,
            'lazy_loading' => true,
            'caption' => '',
            'alt' => '',
            'class' => '',
            'attachment_id' => 0,
            'image_size' => 'medium',
            'show_badge' => false,
        );
        $args = wp_parse_args($args, $defaults);

        $upload_url = ciboost_get_comment_images_upload_url();
        $upload_dir = ciboost_get_comment_images_upload_dir();
        $image_url = $upload_url . $filename;
        $image_path = $upload_dir . $filename;
        $display_url = $image_url;

        if (!file_exists($image_path)) {
            return '';
        }

        $attachment_id = absint($args['attachment_id']);
        if ($attachment_id > 0) {
            $full_src = wp_get_attachment_image_src($attachment_id, 'full');
            $thumb_src = wp_get_attachment_image_src($attachment_id, $args['image_size']);

            if (!empty($full_src[0])) {
                $image_url = $full_src[0];
            }

            if (!empty($thumb_src[0])) {
                $display_url = $thumb_src[0];
            }
        }

        $caption = trim((string) $args['caption']);
        $alt = !empty($args['alt']) ? $args['alt'] : $this->generate_image_alt($comment);
        if (!empty($caption)) {
            $alt = $caption;
        }

        $classes = trim('ciboost-comment-image-wrapper ' . $this->sanitize_html_class_list($args['class']));
        $html = '<figure class="' . esc_attr($classes) . '">';
        $html .= '<a href="' . esc_url($image_url) . '" class="ciboost-comment-image-link ciboost-lightbox-trigger" data-ciboost-caption="' . esc_attr($caption) . '" target="_blank" style="max-width: ' . absint($args['max_width']) . 'px;">';
        $html .= '<img src="' . esc_url($display_url) . '" alt="' . esc_attr($alt) . '" class="ciboost-comment-image"' . (!empty($args['lazy_loading']) ? ' loading="lazy"' : '') . '>';
        $html .= '</a>';

        if (!empty($args['show_badge'])) {
            $html .= '<span class="ciboost-photo-comment-badge">' . esc_html__('Photo comment', 'comment-image-boost') . '</span>';
        }

        if (!empty($caption)) {
            $html .= '<figcaption class="ciboost-comment-image-caption">' . esc_html($caption) . '</figcaption>';
        }

        $html .= '</figure>';

        return $html;
    }

    /**
     * Exibe a imagem no comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio (frontend)
     */
    public function display_image($comment_text, $comment) {
        try {
            // NÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o exibe no admin (usa display_image_admin)
            if (is_admin()) {
                return $comment_text;
            }

            if (!$comment instanceof WP_Comment) {
                return $comment_text;
            }

            $image_data = get_comment_meta($comment->comment_ID, self::META_KEY, true);

            if (empty($image_data)) {
                return $comment_text;
            }

            // Normaliza para array (pode ser string ou array)
            $image_filenames = is_array($image_data) ? $image_data : array($image_data);

            $upload_url = ciboost_get_comment_images_upload_url();
            $upload_dir = ciboost_get_comment_images_upload_dir();
            $captions = $this->get_image_captions($comment->comment_ID);
            $attachments = $this->get_image_attachments($comment->comment_ID);
            $image_size = $this->get_option('image_size', 'medium');
            $max_width = $this->get_image_max_width($image_size);
            $layout = $this->get_option('display_layout', 'vertical');
            $lazy_loading = $this->get_option('lazy_loading', true);
            $show_badge = $this->get_option('show_badge', true);

            // Gera alt text personalizado
            $alt_text = $this->generate_image_alt($comment);

            $img_html = '';

            // Se mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºltiplas imagens, cria galeria com layout
            if (count($image_filenames) > 1) {
                $layout_class = 'ciboost-layout-' . esc_attr($layout);
                $img_html .= '<div class="ciboost-comment-images-gallery ' . $layout_class . '">';
            }

            // Processa cada imagem
            $image_index = 0;
            $rendered_count = 0;
            foreach ($image_filenames as $filename) {
                $filename = sanitize_file_name($filename);
                if ($filename === '') {
                    continue;
                }

                $image_url = $upload_url . $filename;
                $image_path = $upload_dir . $filename;

                // Verifica se o arquivo existe
                if (!file_exists($image_path) || !$this->is_image_public($comment->comment_ID, $filename)) {
                    continue;
                }

                // Se houver mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºltiplas imagens, adiciona ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­ndice ao alt
                $current_alt = $alt_text;
                if (count($image_filenames) > 1) {
                    $current_alt .= ' (' . ($image_index + 1) . ')';
                }

                $img_html .= $this->render_image_item($comment, $filename, array(
                    'max_width' => $max_width,
                    'lazy_loading' => $lazy_loading,
                    'caption' => isset($captions[$filename]) ? $captions[$filename] : '',
                    'alt' => $current_alt,
                    'attachment_id' => isset($attachments[$filename]) ? absint($attachments[$filename]) : 0,
                    'image_size' => $image_size,
                    'show_badge' => $show_badge,
                ));
                $rendered_count++;

                $image_index++;
            }

            if (count($image_filenames) > 1) {
                $img_html .= '</div>';
            }

            if ($rendered_count === 0) {
                return $comment_text;
            }

            return $this->get_option('image_position', 'after') === 'before' ? $img_html . $comment_text : $comment_text . $img_html;

        } catch (Exception $e) {
            ciboost_log('Error displaying image: ' . $e->getMessage());
            return $comment_text;
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m largura mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡xima baseada no tamanho de imagem configurado
     */
    private function get_image_max_width($size) {
        try {
            $widths = array(
                'thumbnail' => 150,
                'medium' => 300,
                'medium_large' => 768,
                'large' => 1024,
                'full' => 9999
            );

            return isset($widths[$size]) ? $widths[$size] : 300;

        } catch (Exception $e) {
            ciboost_log('Error getting image max width: ' . $e->getMessage());
            return 300;
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m o tamanho mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡ximo de upload em bytes
     */
    private function get_max_upload_size() {
        try {
            $max_size_mb = $this->get_option('max_size_mb', 2);
            return $max_size_mb * 1024 * 1024; // Converte MB para bytes
        } catch (Exception $e) {
            ciboost_log('Error getting max upload size: ' . $e->getMessage());
            return 2 * 1024 * 1024; // 2MB padrÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m o tamanho mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡ximo formatado
     */
    private function get_max_upload_size_formatted() {
        try {
            return size_format($this->get_max_upload_size());
        } catch (Exception $e) {
            ciboost_log('Error formatting max upload size: ' . $e->getMessage());
            return '2 MB';
        }
    }

    /**
     * ObtÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â©m mensagem de erro de upload
     */
    private function get_upload_error_message($error_code) {
        try {
            $errors = array(
                UPLOAD_ERR_INI_SIZE => sprintf(
                    /* translators: %s: maximum upload size. */
                    __('The file is too large. Maximum allowed size is %s.', 'comment-image-boost'),
                    $this->get_max_upload_size_formatted()
                ),
                UPLOAD_ERR_FORM_SIZE => __('The uploaded file exceeds the MAX_FILE_SIZE directive.', 'comment-image-boost'),
                UPLOAD_ERR_PARTIAL => __('The uploaded file was only partially uploaded.', 'comment-image-boost'),
                UPLOAD_ERR_NO_TMP_DIR => __('Missing a temporary folder.', 'comment-image-boost'),
                UPLOAD_ERR_CANT_WRITE => __('Failed to write file to disk.', 'comment-image-boost'),
                UPLOAD_ERR_EXTENSION => __('A PHP extension stopped the file upload.', 'comment-image-boost'),
            );

            return isset($errors[$error_code]) ? $errors[$error_code] : __('Unknown upload error.', 'comment-image-boost');

        } catch (Exception $e) {
            ciboost_log('Error getting upload error message: ' . $e->getMessage());
            return __('Upload error occurred.', 'comment-image-boost');
        }
    }

    /**
     * Enfileira estilos para ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rea admin
     */
    public function enqueue_admin_styles($hook) {
        try {
            // Apenas nas pÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡ginas de comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rios do admin
            if ($hook !== 'edit-comments.php' && $hook !== 'comment.php') {
                return;
            }

            $assets_url = defined('CIBOOST_PLUGIN_URL') ? CIBOOST_PLUGIN_URL : plugin_dir_url(dirname(__FILE__));
            $version = defined('CIBOOST_VERSION') ? CIBOOST_VERSION : '1.0.16';

            wp_enqueue_style(
                'ciboost-comment-images',
                $assets_url . 'assets/css/comment-images.css',
                array(),
                $version
            );

            wp_enqueue_script(
                'ciboost-comment-images',
                $assets_url . 'assets/js/comment-images.js',
                array('jquery'),
                $version,
                true
            );

            wp_localize_script('ciboost-comment-images', 'ciboostCommentImages', array(
                'formNotFound' => __('Comment form not found.', 'comment-image-boost'),
                'previewSize' => $this->get_option('preview_size', 120),
                'allowedFormats' => $this->get_option('allowed_formats', array('jpg', 'jpeg', 'png', 'webp', 'avif')),
                'allowMultiple' => (bool) $this->get_option('allow_multiple', false),
                'captionsEnabled' => false,
                'captionPlaceholder' => __('Add a short caption', 'comment-image-boost'),
                'lightboxEnabled' => true,
                'invalidFormatMsg' => __('Invalid file format.', 'comment-image-boost'),
            ));

        } catch (Exception $e) {
            ciboost_log('Error enqueuing admin styles: ' . $e->getMessage());
        }
    }

    /**
     * Exibe imagem no admin com tamanho reduzido
     */
    public function display_image_admin($comment_text, $comment) {
        try {
            // SÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â³ aplica no admin
            if (!is_admin()) {
                return $comment_text;
            }

            if (!$comment instanceof WP_Comment) {
                return $comment_text;
            }

            $image_data = get_comment_meta($comment->comment_ID, self::META_KEY, true);

            if (empty($image_data)) {
                return $comment_text;
            }

            // Normaliza para array
            $image_filenames = is_array($image_data) ? $image_data : array($image_data);

            $upload_url = ciboost_get_comment_images_upload_url();
            $upload_dir = ciboost_get_comment_images_upload_dir();
            $captions = $this->get_image_captions($comment->comment_ID);
            $statuses = $this->get_image_statuses($comment->comment_ID);
            $attachments = $this->get_image_attachments($comment->comment_ID);
            // Gera alt text personalizado
            $alt_text = $this->generate_image_alt($comment);

            $img_html = '<div class="ciboost-admin-images">';

            // Processa cada imagem
            $image_index = 0;
            foreach ($image_filenames as $filename) {
                $filename = sanitize_file_name($filename);
                if ($filename === '') {
                    continue;
                }

                $image_url = $upload_url . $filename;
                $thumb_url = $image_url;
                $image_path = $upload_dir . $filename;

                // Verifica se o arquivo existe
                if (!file_exists($image_path)) {
                    continue;
                }

                // Se houver mÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Âºltiplas imagens, adiciona ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â­ndice ao alt
                $current_alt = $alt_text;
                if (count($image_filenames) > 1) {
                    $current_alt .= ' (' . ($image_index + 1) . ')';
                }

                $status = isset($statuses[$filename]) ? $statuses[$filename] : 'approved';
                $caption = isset($captions[$filename]) ? $captions[$filename] : '';
                $attachment_id = isset($attachments[$filename]) ? absint($attachments[$filename]) : 0;
                if ($attachment_id > 0) {
                    $full_src = wp_get_attachment_image_src($attachment_id, 'full');
                    $thumb_src = wp_get_attachment_image_src($attachment_id, 'thumbnail');

                    if (!empty($full_src[0])) {
                        $image_url = $full_src[0];
                    }

                    if (!empty($thumb_src[0])) {
                        $thumb_url = $thumb_src[0];
                    }
                }

                $img_html .= '<a href="' . esc_url($image_url) . '" target="_blank" class="ciboost-admin-image-link ciboost-lightbox-trigger ciboost-status-' . esc_attr($status) . '" data-ciboost-caption="' . esc_attr($caption) . '">';
                $img_html .= '<img src="' . esc_url($thumb_url) . '" alt="' . esc_attr($current_alt) . '" class="ciboost-admin-image">';
                $img_html .= '</a>';

                $image_index++;
            }

            $img_html .= '</div>';

            return $comment_text . $img_html;

        } catch (Exception $e) {
            ciboost_log('Error displaying admin image: ' . $e->getMessage());
            return $comment_text;
        }
    }

    /**
     * Renderiza galerias de imagens via shortcode.
     */
    public function render_gallery_shortcode($atts) {
        try {
            $this->load_options();
            $this->enqueue_assets();

            $atts = shortcode_atts(array(
                'post_id' => 0,
                'limit' => 24,
                'columns' => $this->get_option('gallery_columns', 4),
                'layout' => $this->get_option('gallery_layout', 'grid'),
                'class' => '',
            ), $atts, 'ciboost_gallery');

            $limit = max(1, min(100, absint($atts['limit'])));
            $post_id = absint($atts['post_id']);
            $columns = max(1, min(6, absint($atts['columns'])));
            $layout = sanitize_key($atts['layout']);
            if (!in_array($layout, array('grid', 'carousel'), true)) {
                $layout = 'grid';
            }

            $query_args = array(
                'status' => 'approve',
                'number' => $limit,
                'orderby' => 'comment_date_gmt',
                'order' => 'DESC',
                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Gallery needs comments that have image metadata.
                'meta_key' => self::META_KEY,
            );

            if ($post_id > 0) {
                $query_args['post_id'] = $post_id;
            }

            $comments = get_comments($query_args);

            if (empty($comments)) {
                return '';
            }

            $items = '';
            $count = 0;

            foreach ($comments as $comment) {
                $image_data = get_comment_meta($comment->comment_ID, self::META_KEY, true);
                if (empty($image_data)) {
                    continue;
                }

                $captions = $this->get_image_captions($comment->comment_ID);
                $attachments = $this->get_image_attachments($comment->comment_ID);
                $filenames = is_array($image_data) ? $image_data : array($image_data);

                foreach ($filenames as $filename) {
                    $filename = sanitize_file_name($filename);
                    if ($filename === '') {
                        continue;
                    }

                    if (!$this->is_image_public($comment->comment_ID, $filename)) {
                        continue;
                    }

                    $items .= $this->render_image_item($comment, $filename, array(
                        'max_width' => 9999,
                        'lazy_loading' => true,
                        'caption' => isset($captions[$filename]) ? $captions[$filename] : '',
                        'class' => 'ciboost-gallery-item',
                        'attachment_id' => isset($attachments[$filename]) ? absint($attachments[$filename]) : 0,
                        'image_size' => 'medium_large',
                        'show_badge' => $this->get_option('show_badge', true),
                    ));
                    $count++;

                    if ($count >= $limit) {
                        break 2;
                    }
                }
            }

            if ($items === '') {
                return '';
            }

            $extra_class = $this->sanitize_html_class_list($atts['class']);
            $gallery_classes = trim('ciboost-global-gallery ciboost-gallery-layout-' . $layout . ' ' . $extra_class);
            $gallery_html = '<div class="' . esc_attr($gallery_classes) . '" style="--ciboost-gallery-columns: ' . esc_attr($columns) . ';">' . $items . '</div>';

            if ($layout === 'carousel') {
                $gallery_html = '<div class="ciboost-carousel-wrapper">'
                    . '<button type="button" class="ciboost-carousel-prev" aria-label="' . esc_attr__('Previous', 'comment-image-boost') . '">&#8249;</button>'
                    . $gallery_html
                    . '<button type="button" class="ciboost-carousel-next" aria-label="' . esc_attr__('Next', 'comment-image-boost') . '">&#8250;</button>'
                    . '</div>';
            }

            return $gallery_html;

        } catch (Exception $e) {
            ciboost_log('Error rendering gallery shortcode: ' . $e->getMessage());
            return '';
        }
    }

    /**
     * Adiciona meta box na tela de ediÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o de comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio
     */
    public function add_comment_meta_box() {
        try {
            add_meta_box(
                'ciboost_comment_images_moderation',
                __('Comment Images - Moderation', 'comment-image-boost'),
                array($this, 'render_comment_meta_box'),
                'comment',
                'normal',
                'high'
            );
        } catch (Exception $e) {
            ciboost_log('Error adding comment meta box: ' . $e->getMessage());
        }
    }

    /**
     * Renderiza meta box de moderaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o de imagens
     */
    public function render_comment_meta_box($comment) {
        try {
            $image_data = get_comment_meta($comment->comment_ID, self::META_KEY, true);

            if (empty($image_data)) {
                echo '<p>' . esc_html__('No images attached to this comment.', 'comment-image-boost') . '</p>';
                return;
            }

            // Normaliza para array
            $image_filenames = is_array($image_data) ? $image_data : array($image_data);

            $upload_url = ciboost_get_comment_images_upload_url();
            $upload_dir = ciboost_get_comment_images_upload_dir();
            $captions = $this->get_image_captions($comment->comment_ID);
            $statuses = $this->get_image_statuses($comment->comment_ID);

            wp_nonce_field('ciboost_moderate_images', 'ciboost_moderate_images_nonce');

            echo '<div class="ciboost-moderation-images" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 15px; margin-top: 15px;">';

            foreach ($image_filenames as $index => $filename) {
                $filename = sanitize_file_name($filename);
                if ($filename === '') {
                    continue;
                }

                $image_url = $upload_url . $filename;
                $image_path = $upload_dir . $filename;

                if (!file_exists($image_path)) {
                    continue;
                }

                $image_id = 'ciboost_image_' . $index;
                ?>
                <div style="border: 2px solid #ddd; border-radius: 8px; padding: 10px; background: #f9f9f9;">
                    <a href="<?php echo esc_url($image_url); ?>" target="_blank" style="display: block; margin-bottom: 10px;">
                        <img src="<?php echo esc_url($image_url); ?>"
                             alt="<?php echo esc_attr($filename); ?>"
                             style="width: 100%; height: 150px; object-fit: cover; border-radius: 4px; display: block;">
                    </a>
                    <label for="<?php echo esc_attr($image_id); ?>" style="display: block; margin-bottom: 6px; font-size: 12px; font-weight: 600; color: #2c3338;">
                        <?php esc_html_e('Moderation status', 'comment-image-boost'); ?>
                    </label>
                    <select
                        name="ciboost_image_status[<?php echo esc_attr($filename); ?>]"
                        id="<?php echo esc_attr($image_id); ?>"
                        style="width: 100%; margin-bottom: 8px;">
                        <?php $status = isset($statuses[$filename]) ? $statuses[$filename] : 'approved'; ?>
                        <option value="approved" <?php selected($status, 'approved'); ?>><?php esc_html_e('Approved', 'comment-image-boost'); ?></option>
                        <option value="pending" <?php selected($status, 'pending'); ?>><?php esc_html_e('Pending', 'comment-image-boost'); ?></option>
                        <option value="rejected" <?php selected($status, 'rejected'); ?>><?php esc_html_e('Rejected', 'comment-image-boost'); ?></option>
                    </select>
                    <label style="display: block; margin-bottom: 6px; font-size: 12px; font-weight: 600; color: #2c3338;">
                        <?php esc_html_e('Caption', 'comment-image-boost'); ?>
                    </label>
                    <input type="text"
                           name="ciboost_image_caption[<?php echo esc_attr($filename); ?>]"
                           value="<?php echo esc_attr(isset($captions[$filename]) ? $captions[$filename] : ''); ?>"
                           maxlength="160"
                           style="width: 100%; margin-bottom: 8px;">
                    <label style="display: flex; align-items: center; gap: 8px; cursor: pointer; padding: 8px; background: #fff; border-radius: 4px; border: 1px solid #ddd;">
                        <input type="checkbox"
                               name="ciboost_delete_images[]"
                               value="<?php echo esc_attr($filename); ?>"
                               style="margin: 0;">
                        <span style="font-size: 13px; font-weight: 600; color: #b32d2e;">
                            <?php esc_html_e('Delete permanently', 'comment-image-boost'); ?>
                        </span>
                    </label>
                    <p style="margin: 8px 0 0 0; font-size: 11px; color: #646970; word-break: break-all;">
                        <?php echo esc_html($filename); ?>
                    </p>
                </div>
                <?php
            }

            echo '</div>';

            echo '<p style="margin-top: 15px; padding: 12px; background: #fff3cd; border: 1px solid #ffc107; border-radius: 4px; font-size: 13px;">';
            echo '<strong>' . esc_html__('Note:', 'comment-image-boost') . '</strong> ';
            echo esc_html__('Rejected images are hidden from public galleries. Use permanent delete only when you want to remove the file from the server.', 'comment-image-boost');
            echo '</p>';

        } catch (Exception $e) {
            ciboost_log('Error rendering comment meta box: ' . $e->getMessage());
        }
    }

    /**
     * Salva moderaÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â§ÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â£o de imagens ao editar comentÃƒÆ’Ã†â€™Ãƒâ€šÃ‚Â¡rio
     */
    public function save_comment_images_moderation($comment_id) {
        try {
            if (!isset($_POST['ciboost_moderate_images_nonce']) ||
                !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['ciboost_moderate_images_nonce'])), 'ciboost_moderate_images')) {
                return;
            }

            if (!current_user_can('moderate_comments')) {
                return;
            }

            $image_data = get_comment_meta($comment_id, self::META_KEY, true);

            if (empty($image_data)) {
                return;
            }

            $current_images = is_array($image_data) ? $image_data : array($image_data);
            $posted_statuses = isset($_POST['ciboost_image_status']) ? array_map('sanitize_key', (array) wp_unslash($_POST['ciboost_image_status'])) : array();
            $posted_captions = isset($_POST['ciboost_image_caption']) ? array_map('sanitize_text_field', (array) wp_unslash($_POST['ciboost_image_caption'])) : array();
            $delete_images = isset($_POST['ciboost_delete_images']) ? array_map('sanitize_file_name', (array) wp_unslash($_POST['ciboost_delete_images'])) : array();
            $upload_dir = ciboost_get_comment_images_upload_dir();
            $current_attachments = $this->get_image_attachments($comment_id);
            $kept_images = array();
            $new_statuses = array();
            $new_captions = array();
            $new_attachments = array();

            foreach ($current_images as $filename) {
                $filename = sanitize_file_name($filename);

                if (in_array($filename, $delete_images, true)) {
                    if (!empty($current_attachments[$filename])) {
                        wp_delete_attachment(absint($current_attachments[$filename]), true);
                    }

                    $file_path = $upload_dir . $filename;

                    if (file_exists($file_path)) {
                        wp_delete_file($file_path);
                        if (!file_exists($file_path)) {
                            ciboost_log('Image permanently deleted: ' . $filename . ' for comment ID: ' . $comment_id);
                        } else {
                            ciboost_log('Error deleting image: ' . $filename . ' for comment ID: ' . $comment_id);
                        }
                    }

                    continue;
                }

                $kept_images[] = $filename;

                if (!empty($current_attachments[$filename])) {
                    $new_attachments[$filename] = absint($current_attachments[$filename]);
                }

                $status = isset($posted_statuses[$filename]) ? $posted_statuses[$filename] : 'approved';
                if (!in_array($status, array('approved', 'pending', 'rejected'), true)) {
                    $status = 'approved';
                }
                $new_statuses[$filename] = $status;

                if (isset($posted_captions[$filename])) {
                    $caption = $posted_captions[$filename];
                    if ($caption !== '') {
                        $new_captions[$filename] = function_exists('mb_substr') ? mb_substr($caption, 0, 160) : substr($caption, 0, 160);
                    }
                }
            }

            if (!empty($kept_images)) {
                $meta_value = (count($kept_images) === 1) ? $kept_images[0] : $kept_images;
                update_comment_meta($comment_id, self::META_KEY, $meta_value);
            } else {
                delete_comment_meta($comment_id, self::META_KEY);
            }

            if (!empty($new_statuses)) {
                update_comment_meta($comment_id, self::STATUS_META_KEY, $new_statuses);
            } else {
                delete_comment_meta($comment_id, self::STATUS_META_KEY);
            }

            if (!empty($new_captions)) {
                update_comment_meta($comment_id, self::CAPTIONS_META_KEY, $new_captions);
            } else {
                delete_comment_meta($comment_id, self::CAPTIONS_META_KEY);
            }

            if (!empty($new_attachments)) {
                update_comment_meta($comment_id, self::ATTACHMENTS_META_KEY, $new_attachments);
            } else {
                delete_comment_meta($comment_id, self::ATTACHMENTS_META_KEY);
            }

        } catch (Exception $e) {
            ciboost_log('Error saving comment images moderation: ' . $e->getMessage());
        }
    }

    /**
     * Deleta imagens quando comentario e deletado.
     */
    public function delete_image_on_comment_delete($comment_id) {
        try {
            $image_data = get_comment_meta($comment_id, self::META_KEY, true);

            if (empty($image_data)) {
                return;
            }

            $image_filenames = is_array($image_data) ? $image_data : array($image_data);
            $upload_dir = ciboost_get_comment_images_upload_dir();
            $attachments = $this->get_image_attachments($comment_id);

            foreach ($image_filenames as $filename) {
                $filename = sanitize_file_name($filename);

                if (!empty($attachments[$filename])) {
                    wp_delete_attachment(absint($attachments[$filename]), true);
                }

                $file_path = $upload_dir . sanitize_file_name($filename);

                if (file_exists($file_path)) {
                    wp_delete_file($file_path);
                    if (!file_exists($file_path)) {
                        ciboost_log('Image deleted successfully: ' . $filename . ' for comment ID: ' . $comment_id);
                    } else {
                        ciboost_log('Error deleting image: ' . $filename . ' for comment ID: ' . $comment_id);
                    }
                }
            }

            delete_comment_meta($comment_id, self::META_KEY);
            delete_comment_meta($comment_id, self::CAPTIONS_META_KEY);
            delete_comment_meta($comment_id, self::STATUS_META_KEY);
            delete_comment_meta($comment_id, self::ATTACHMENTS_META_KEY);

        } catch (Exception $e) {
            ciboost_log('Error deleting images on comment delete: ' . $e->getMessage());
        }
    }
}

// Inicializa a classe
$GLOBALS['ciboost_comment_images'] = new CIBOOST_Comment_Images();
