<?php

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Retrieves the cached result of a callback if available; otherwise, computes
 * the result, caches it, and returns it.
 *
 * @param string   $cache_key The cache key to store/retrieve the data.
 * @param callable $callback The callback to execute if the cached value is not found.
 * @param int      $expiration The expiration time in seconds for the cached data
 *
 * @return mixed The cached or computed result of the callback.
 */
function with_cache(callable $callback, string $cache_key, int $expiration = 0)
{
    // Try to get the cached data
    $cached_data = get_transient($cache_key);
    if ($cached_data !== false) {
        return $cached_data;
    }

    try {
        $result = $callback();

        // Don't cache if result is error
        if (is_wp_error($result)) return $result;

        // Cache the result
        set_transient($cache_key, $result, $expiration);

        return $result;
    } catch (Exception $e) {
        error_log('Erro em with_cache: ' . $e->getMessage());
        return new WP_Error('cache_error', $e->getMessage());
    }
}

function with_retry(callable $callback, $retries)
{
    if (!is_callable($callback) || $retries < 0) {
        return new WP_Error('invalid_params', 'Parâmetros inválidos para with_retry');
    }
    
    $attempt = 0;
    $last_result = null;
    
    while ($attempt <= $retries) {
        try {
            $result = $callback();
            if (!is_wp_error($result)) {
                return $result;
            }
            $last_result = $result;
        } catch (Exception $e) {
            $last_result = new WP_Error('callback_error', $e->getMessage());
        }
        $attempt++;
    }
    
    return $last_result;
}

function minify_html($html)
{
    if (empty($html)) {
        return '';
    }
    
    // Proteger conteúdo de scripts e styles da minificação
    $protected = [];
    $html = preg_replace_callback('/<(script|style)[^>]*>.*?<\/\1>/is', function($matches) use (&$protected) {
        $key = '___PROTECTED_' . count($protected) . '___';
        $content = $matches[0];
        
        // Se for CSS inline, minificar também
        if (stripos($matches[1], 'style') !== false && stripos($content, '<style') !== false) {
            // Extrair CSS do style tag
            if (preg_match('/<style[^>]*>(.*?)<\/style>/is', $content, $css_match)) {
                $css_content = $css_match[1];
                // Minificar CSS
                $css_content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css_content);
                $css_content = preg_replace('/\s+/', ' ', $css_content);
                $css_content = preg_replace('/\s*([{}:;,])\s*/', '$1', $css_content);
                $css_content = preg_replace('/;}/', '}', $css_content);
                $css_content = trim($css_content);
                // Reconstruir tag style com CSS minificado
                if (preg_match('/<style([^>]*)>/i', $content, $style_attr)) {
                    $content = '<style' . $style_attr[1] . '>' . $css_content . '</style>';
                }
            }
        }
        
        $protected[$key] = $content;
        return $key;
    }, $html);
    
    // Minificar o HTML
    $html = preg_replace('/>\s+</', '><', $html);
    $html = preg_replace('/\s+/', ' ', $html);
    $html = trim($html);
    
    // Restaurar conteúdo protegido
    foreach ($protected as $key => $content) {
        $html = str_replace($key, $content, $html);
    }
    
    return $html;
}

/**
 * Minifica JavaScript
 */
function upgram_minify_js($js) {
    if (empty($js)) {
        return '';
    }
    
    // Remover comentários de linha única
    $js = preg_replace('/\/\/.*$/m', '', $js);
    
    // Remover comentários de múltiplas linhas
    $js = preg_replace('/\/\*[^*]*\*+([^\/][^*]*\*+)*\//', '', $js);
    
    // Remover espaços em branco desnecessários
    $js = preg_replace('/\s+/', ' ', $js);
    
    // Remover espaços ao redor de operadores (cuidado com strings)
    $js = preg_replace('/\s*([=+\-*\/%<>!&|?:;,{}()\[\]])\s*/', '$1', $js);
    
    // Remover espaços antes de ponto e vírgula
    $js = preg_replace('/\s*;\s*/', ';', $js);
    
    // Remover espaços antes de vírgulas
    $js = preg_replace('/\s*,\s*/', ',', $js);
    
    // Remover espaços ao redor de chaves
    $js = preg_replace('/\s*{\s*/', '{', $js);
    $js = preg_replace('/\s*}\s*/', '}', $js);
    
    return trim($js);
}

/**
 * Minifica CSS (versão melhorada)
 */
function upgram_minify_css_advanced($css) {
    if (empty($css)) {
        return '';
    }
    
    // Remover comentários
    $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
    
    // Remover espaços em branco desnecessários
    $css = preg_replace('/\s+/', ' ', $css);
    
    // Remover espaços ao redor de operadores
    $css = preg_replace('/\s*([{}:;,])\s*/', '$1', $css);
    
    // Remover último ponto e vírgula antes de }
    $css = preg_replace('/;}/', '}', $css);
    
    // Remover espaços em branco no início e fim
    $css = trim($css);
    
    return $css;
}

/**
 * Cria a pasta cache se não existir
 */
function upgram_ensure_cache_dir() {
    $cache_dir = UPGRAM_PATH . 'cache';
    if (!file_exists($cache_dir)) {
        wp_mkdir_p($cache_dir);
        // Criar arquivo .htaccess para proteger a pasta
        $htaccess_content = "Order Deny,Allow\nDeny from all\n";
        file_put_contents($cache_dir . '/.htaccess', $htaccess_content);
        // Criar arquivo index.php vazio para segurança
        file_put_contents($cache_dir . '/index.php', '<?php // Silence is golden');
    }
    return $cache_dir;
}

/**
 * Gera e salva arquivos minificados
 */
function upgram_generate_minified_files() {
    $cache_dir = upgram_ensure_cache_dir();
    $generated = array();
    
    // 1. Minificar shortcodes.php (HTML/CSS/JS inline)
    $shortcodes_file = UPGRAM_PATH . 'public/shortcodes.php';
    if (file_exists($shortcodes_file)) {
        $content = file_get_contents($shortcodes_file);
        
        // Extrair e minificar CSS inline
        $content = preg_replace_callback('/<style[^>]*>(.*?)<\/style>/is', function($matches) {
            $css = $matches[1];
            $minified_css = upgram_minify_css_advanced($css);
            return '<style>' . $minified_css . '</style>';
        }, $content);
        
        // Extrair e minificar JavaScript inline
        $content = preg_replace_callback('/<script[^>]*>(.*?)<\/script>/is', function($matches) {
            // Não minificar se contiver dados PHP ou Alpine.js
            if (strpos($matches[0], '<?php') !== false || strpos($matches[0], 'x-data') !== false) {
                return $matches[0];
            }
            $js = $matches[1];
            $minified_js = upgram_minify_js($js);
            return '<script>' . $minified_js . '</script>';
        }, $content);
        
        // Minificar HTML (já existe função minify_html)
        $minified_content = minify_html($content);
        
        // Salvar arquivo minificado
        $minified_file = $cache_dir . '/shortcodes.min.php';
        file_put_contents($minified_file, $minified_content);
        $generated[] = 'shortcodes.min.php';
    }
    
    // 2. Minificar arquivos JS
    $js_files = array(
        'assets/js/script.js',
        'assets/js/free-likes.js',
        'assets/js/free-views.js',
        'assets/js/instagram-free-followers.js',
        'assets/js/icon-selector.js',
        'assets/js/instagram-download.js'
    );
    
    foreach ($js_files as $js_file) {
        $full_path = UPGRAM_PATH . $js_file;
        if (file_exists($full_path)) {
            $js_content = file_get_contents($full_path);
            $minified_js = upgram_minify_js($js_content);
            
            $filename = basename($js_file, '.js');
            $minified_file = $cache_dir . '/' . $filename . '.min.js';
            file_put_contents($minified_file, $minified_js);
            $generated[] = basename($minified_file);
        }
    }
    
    // 3. Minificar arquivos CSS
    $css_files = array(
        'assets/css/style.css',
        'assets/css/orders.style.css'
    );
    
    foreach ($css_files as $css_file) {
        $full_path = UPGRAM_PATH . $css_file;
        if (file_exists($full_path)) {
            $css_content = file_get_contents($full_path);
            $minified_css = upgram_minify_css_advanced($css_content);
            
            $filename = basename($css_file, '.css');
            $minified_file = $cache_dir . '/' . $filename . '.min.css';
            file_put_contents($minified_file, $minified_css);
            $generated[] = basename($minified_file);
        }
    }
    
    return $generated;
}

/**
 * Limpa todos os arquivos minificados
 */
function upgram_clear_minified_files() {
    $cache_dir = UPGRAM_PATH . 'cache';
    if (!file_exists($cache_dir)) {
        return true;
    }
    
    $files = glob($cache_dir . '/*.{min.js,min.css,min.php}', GLOB_BRACE);
    foreach ($files as $file) {
        if (is_file($file)) {
            unlink($file);
        }
    }
    
    return true;
}

/**
 * Verifica se deve usar arquivos minificados
 */
function upgram_use_minified_files() {
    return (bool) get_option('upgram_use_minified_files', false);
}

function image_url_to_base64($image_url)
{
    if (empty($image_url)) {
        return '';
    }
    
    $response = wp_remote_get($image_url, [
        'timeout' => 30,
        'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    ]);
    
    if (is_wp_error($response)) {
        error_log('Erro ao buscar imagem: ' . $response->get_error_message());
        return '';
    }
    
    $image_data = wp_remote_retrieve_body($response);
    $content_type = wp_remote_retrieve_header($response, 'content-type');
    
    if (empty($image_data)) {
        return '';
    }
    
    return 'data:' . $content_type . ';base64,' . base64_encode($image_data);
}

function image_urls_to_base64_parallel($urls)
{
    if (!is_array($urls) || empty($urls)) {
        return [];
    }
    
    $multiHandle = curl_multi_init();
    if (!$multiHandle) {
        return [];
    }
    
    $curlHandles = [];
    $base64Images = [];

    foreach ($urls as $key => $url) {
        $curlHandles[$key] = curl_init();
        if ($curlHandles[$key]) {
            curl_setopt($curlHandles[$key], CURLOPT_URL, $url);
            curl_setopt($curlHandles[$key], CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curlHandles[$key], CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($curlHandles[$key], CURLOPT_TIMEOUT, 30);
            curl_multi_add_handle($multiHandle, $curlHandles[$key]);
        }
    }

    do {
        curl_multi_exec($multiHandle, $running);
        curl_multi_select($multiHandle);
    } while ($running > 0);

    foreach ($curlHandles as $key => $handle) {
        if ($handle) {
            $imageData = curl_multi_getcontent($handle);
            $contentType = curl_getinfo($handle, CURLINFO_CONTENT_TYPE);
            $base64Images[$key] = $imageData ? 'data:' . $contentType . ';base64,' . base64_encode($imageData) : '';
            curl_multi_remove_handle($multiHandle, $handle);
        }
    }

    curl_multi_close($multiHandle);

    return $base64Images;
}

/**
 * Verifica se uma feature específica é necessária na página atual
 * 
 * @param string $feature Nome da feature (free_likes, free_followers, instagram_download, etc.)
 * @return bool True se a feature é necessária, false caso contrário
 */
function upgram_is_feature_needed($feature) {
    global $post;
    
    // Cache por request para evitar múltiplas verificações
    static $cache = array();
    if (isset($cache[$feature])) {
        return $cache[$feature];
    }
    
    $is_needed = false;
    
    // Mapeamento de features para shortcodes/identificadores
    $feature_map = array(
        'free_likes' => array(
            'shortcodes' => array('free_likes', 'upgram_free_likes'),
            'classes' => array('freeLikesForm', 'free-likes'),
            'ids' => array('freeLikesForm')
        ),
        'free_followers' => array(
            'shortcodes' => array('free_followers', 'upgram_free_followers', 'instagram_free_followers'),
            'classes' => array('free-followers', 'instagram-free-followers'),
            'ids' => array('freeFollowersForm')
        ),
        'instagram_download' => array(
            'shortcodes' => array('download_instagram_video', 'download_instagram_audio', 'download_instagram_image'),
            'classes' => array('instagram-download', 'download-instagram'),
            'ids' => array('instagramDownloadForm')
        )
    );
    
    if (!isset($feature_map[$feature])) {
        $cache[$feature] = false;
        return false;
    }
    
    $identifiers = $feature_map[$feature];
    
    // Verificar se estamos em uma página de produto (pode usar qualquer feature)
    if (is_product() || is_singular('product')) {
        // Verificar se o shortcode [upgram_product] está sendo usado
        if ($post && has_shortcode($post->post_content, 'upgram_product')) {
            // Em páginas de produto, verificar se há elementos específicos no conteúdo
            $content = $post->post_content;
            
            // Verificar por classes/IDs
            foreach ($identifiers['classes'] as $class) {
                if (strpos($content, $class) !== false || strpos($content, 'class="' . $class) !== false) {
                    $is_needed = true;
                    break;
                }
            }
            
            if (!$is_needed) {
                foreach ($identifiers['ids'] as $id) {
                    if (strpos($content, $id) !== false || strpos($content, 'id="' . $id) !== false) {
                        $is_needed = true;
                        break;
                    }
                }
            }
        }
    }
    
    // Verificar shortcodes no conteúdo
    if (!$is_needed && $post) {
        foreach ($identifiers['shortcodes'] as $shortcode) {
            if (has_shortcode($post->post_content, $shortcode)) {
                $is_needed = true;
                break;
            }
        }
    }
    
    // Verificar em widgets/sidebars
    if (!$is_needed) {
        // Verificar se há widgets ativos que usam essas features
        $widgets = wp_get_sidebars_widgets();
        foreach ($widgets as $sidebar => $widget_list) {
            if (is_array($widget_list)) {
                foreach ($widget_list as $widget_id) {
                    // Verificar se widget contém identificadores
                    $widget_data = get_option('widget_' . str_replace('_', '-', explode('-', $widget_id)[0]));
                    if (is_array($widget_data)) {
                        foreach ($widget_data as $widget_instance) {
                            if (is_array($widget_instance)) {
                                $widget_text = serialize($widget_instance);
                                foreach ($identifiers['classes'] as $class) {
                                    if (strpos($widget_text, $class) !== false) {
                                        $is_needed = true;
                                        break 3;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    $cache[$feature] = $is_needed;
    return $is_needed;
}
