<?php
/**
 * Image Boost — Format Converter
 * Handles WebP conversion.
 */

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

class ImgBoost_Converter {

    public static function init() {
        if (!is_admin() && get_option('imgboost_webp_enabled', 1)) {
            add_filter('wp_content_img_tag', [self::class, 'replace_single_img_tag']);
            add_filter('post_thumbnail_html', [self::class, 'replace_single_img_tag']);
        }
    }

    /**
     * Convert an image to WebP format.
     */
    public static function to_webp($source_path, $level = 'pro') {
        if (!imgboost_supports_webp()) {
            return new WP_Error('no_webp', __('WebP is not supported by your server.', 'image-boost'));
        }

        $quality = imgboost_get_quality($level);
        $webp_path = preg_replace('/\.(jpe?g|png|gif)$/i', '.webp', $source_path);

        if ($webp_path === $source_path) {
            $webp_path = $source_path . '.webp';
        }

        $engine = imgboost_get_engine();
        $mime = imgboost_get_mime_type($source_path);

        if ($engine === 'imagick') {
            $result = self::imagick_to_webp($source_path, $webp_path, $quality['webp_quality'], $mime);
        } else {
            $result = self::gd_to_webp($source_path, $webp_path, $quality['webp_quality'], $mime);
        }

        if (is_wp_error($result)) {
            return $result;
        }

        if (!file_exists($webp_path)) {
            return new WP_Error('webp_failed', __('WebP conversion failed.', 'image-boost'));
        }

        if (filesize($webp_path) >= filesize($source_path)) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            wp_delete_file($webp_path);
            return new WP_Error('webp_larger', __('WebP version is larger than original, skipped.', 'image-boost'));
        }

        return ['path' => $webp_path, 'size' => filesize($webp_path)];
    }

    // ─── Imagick Conversions ──────────────────────────────────

    private static function imagick_to_webp($source_path, $dest_path, $quality, $mime) {
        if (!class_exists('Imagick')) return false;
        try {
            $img = new Imagick($source_path);
            $img->setImageFormat('webp');
            $img->setImageCompressionQuality($quality);
            if (method_exists($img, 'setOption')) {
                $img->setOption('webp:method', '6');
                $img->setOption('webp:lossless', 'false');
            }
            $img->stripImage();
            $result = $img->writeImage($dest_path);
            $img->clear();
            $img->destroy();
            return $result ? true : new WP_Error('imagick_webp_error', __('Imagick WebP writing failed.', 'image-boost'));
        } catch (Exception $e) {
            return new WP_Error('imagick_webp_exception', $e->getMessage());
        }
    }

    // ─── GD Conversions ───────────────────────────────────────

    private static function gd_to_webp($source_path, $dest_path, $quality, $mime) {
        if (!function_exists('imagewebp')) return false;
        $img = self::gd_load($source_path, $mime);
        if (!$img) return new WP_Error('gd_webp_load_error', __('GD failed to load image.', 'image-boost'));

        if (function_exists('imagepalettetotruecolor')) {
            imagepalettetotruecolor($img);
        }
        imagealphablending($img, false);
        imagesavealpha($img, true);

        $result = imagewebp($img, $dest_path, $quality);
        imagedestroy($img);
        return $result ? true : new WP_Error('gd_webp_error', __('GD WebP conversion failed.', 'image-boost'));
    }

    private static function gd_load($path, $mime) {
        switch ($mime) {
            case 'image/jpeg':
                return function_exists('imagecreatefromjpeg') ? imagecreatefromjpeg($path) : false;
            case 'image/png':
                return function_exists('imagecreatefrompng') ? imagecreatefrompng($path) : false;
            case 'image/gif':
                return function_exists('imagecreatefromgif') ? imagecreatefromgif($path) : false;
            case 'image/webp':
                return function_exists('imagecreatefromwebp') ? imagecreatefromwebp($path) : false;
            default:
                return false;
        }
    }

    /**
     * Serve WebP via <picture> tag by filtering single img tags.
     */
    public static function replace_single_img_tag($html) {
        if (empty($html) || strpos($html, '<picture') !== false) {
            return $html;
        }

        $upload_dir = wp_get_upload_dir();
        $upload_url = preg_replace('/^https?:\/\//i', '', $upload_dir['baseurl']);
        $webp_enabled = get_option('imgboost_webp_enabled', 1);

        if (!$webp_enabled) {
            return $html;
        }

        if (!preg_match('/src=[\'"]([^\'"]+)[\'"]/i', $html, $matches)) {
            return $html;
        }

        $original_src = $matches[1];
        $src = preg_replace('/\?.*/', '', $original_src);
        $clean_url_no_scheme = preg_replace('/^https?:\/\//i', '', $src);

        if (strpos($clean_url_no_scheme, $upload_url) === false) {
            return $html;
        }

        $relative_path = urldecode(substr($clean_url_no_scheme, strpos($clean_url_no_scheme, $upload_url) + strlen($upload_url)));
        if (strpos($relative_path, '..') !== false) {
            return $html;
        }

        $file_path = wp_normalize_path($upload_dir['basedir'] . $relative_path);
        $webp_path = preg_replace('/\.(jpe?g|png|gif)$/i', '.webp', $file_path);
        $webp_url  = preg_replace('/\.(jpe?g|png|gif)$/i', '.webp', $original_src);

        if (!file_exists($webp_path)) {
            return $html;
        }

        if (get_option('imgboost_lazy_loading', 0)) {
            if (strpos($html, 'loading=') === false) {
                $html = preg_replace('/<img /i', '<img loading="lazy" decoding="async" ', $html, 1);
            }
        }

        return '<picture>'
            . '<source type="image/webp" srcset="' . esc_url($webp_url) . '">'
            . $html
            . '</picture>';
    }
}
