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

class AIIO_Optimizer {

    public static function init() {
        add_action('add_attachment', [__CLASS__, 'maybe_auto_optimize'], 30);
    }

    public static function maybe_auto_optimize($attachment_id) {
        $s = aiio_get_settings();
        if (empty($s['auto_optimize_upload'])) {
            return;
        }
        if (!self::is_optimizable($attachment_id, $reason)) {
            return;
        }
        AIIO_Optimizer::apply($attachment_id, [
            'webp' => !empty($s['webp_enabled']),
            'avif' => !empty($s['avif_enabled']),
        ]);
    }

    public static function supported_mimes() {
        return ['image/jpeg', 'image/png'];
    }

    public static function is_optimizable($attachment_id, &$reason = '') {
        $attachment_id = intval($attachment_id);
        if (!$attachment_id || get_post_type($attachment_id) !== 'attachment') {
            $reason = __('Invalid attachment.', 'pewit-ai-image-optimizer');
            return false;
        }

        $mime = get_post_mime_type($attachment_id);
        if (!in_array($mime, self::supported_mimes(), true)) {
            $reason = __('Only JPEG and PNG can be compressed.', 'pewit-ai-image-optimizer');
            return false;
        }

        $file = get_attached_file($attachment_id);
        if (!$file || !is_file($file)) {
            $reason = __('Image file not found on disk.', 'pewit-ai-image-optimizer');
            return false;
        }

        return true;
    }

    public static function supports_avif() {
        if (function_exists('imageavif')) {
            return true;
        }
        if (class_exists('Imagick')) {
            $formats = Imagick::queryFormats('AVIF');
            if (!empty($formats)) {
                return true;
            }
        }
        return false;
    }

    public static function avif_quality() {
        return max(1, min(100, (int) (aiio_get_settings()['avif_quality'] ?? 50)));
    }

    public static function supports_webp() {
        if (function_exists('imagewebp')) {
            return true;
        }
        if (class_exists('Imagick')) {
            $formats = Imagick::queryFormats('WEBP');
            if (!empty($formats)) {
                return true;
            }
        }
        return false;
    }

    /**
     * WebP encoding quality presets (1–100). Balanced ≈ best size/quality ratio for most photos.
     */
    public static function webp_quality_map() {
        return [
            'balanced' => 82,
            'size'     => 68,
            'quality'  => 92,
        ];
    }

    public static function webp_priority() {
        $priority = aiio_get_settings()['webp_priority'] ?? 'balanced';
        return array_key_exists($priority, self::webp_quality_map()) ? $priority : 'balanced';
    }

    public static function webp_quality($priority = null) {
        $map = self::webp_quality_map();
        $key = $priority ?? self::webp_priority();
        return max(1, min(100, (int) ($map[$key] ?? $map['balanced'])));
    }

    public static function webp_priority_labels() {
        return [
            'balanced' => __('Balanced — best size/quality ratio (recommended)', 'pewit-ai-image-optimizer'),
            'size'     => __('Smaller files — prioritize size', 'pewit-ai-image-optimizer'),
            'quality'  => __('Higher quality — prioritize visual fidelity', 'pewit-ai-image-optimizer'),
        ];
    }

    private static function prepare_webp_editor($editor) {
        if (is_wp_error($editor)) {
            return $editor;
        }
        $editor->set_quality(self::webp_quality());
        return $editor;
    }

    public static function quality_for_mime($mime) {
        $settings = aiio_get_settings();
        if ($mime === 'image/png') {
            return max(0, min(9, intval($settings['png_compression'] ?? 6)));
        }
        return max(1, min(100, intval($settings['jpeg_quality'] ?? 82)));
    }

    /**
     * @return array|WP_Error
     */
    public static function preview($attachment_id) {
        if (!self::is_optimizable($attachment_id, $reason)) {
            return new WP_Error('aiio_not_optimizable', $reason);
        }

        $file = get_attached_file($attachment_id);
        $mime = get_post_mime_type($attachment_id);
        $before = filesize($file);

        $editor = wp_get_image_editor($file);
        if (is_wp_error($editor)) {
            return $editor;
        }

        $editor->set_quality(self::quality_for_mime($mime));
        $saved = $editor->save(null, $mime);
        if (is_wp_error($saved)) {
            return $saved;
        }

        $temp_path = $saved['path'] ?? '';
        if (!$temp_path || !is_file($temp_path)) {
            return new WP_Error('aiio_preview_save', __('Could not create optimization preview.', 'pewit-ai-image-optimizer'));
        }

        $after = filesize($temp_path);
        $saved_bytes = max(0, $before - $after);
        $saved_pct = $before > 0 ? round(($saved_bytes / $before) * 100, 1) : 0;

        $can_auto = true;

        $result = [
            'attachment_id' => intval($attachment_id),
            'before_bytes' => $before,
            'after_bytes' => $after,
            'saved_bytes' => $saved_bytes,
            'saved_percent' => $saved_pct,
            'mime' => $mime,
            'filename' => basename($file),
            'preview_path' => $temp_path,
            'can_webp' => $can_auto && !empty(aiio_get_settings()['webp_enabled']) && self::supports_webp(),
            'can_avif' => $can_auto && !empty(aiio_get_settings()['avif_enabled']) && self::supports_avif(),
        ];

        if ($result['can_webp']) {
            $webp_preview = self::preview_webp($file, $temp_path);
            if (!is_wp_error($webp_preview)) {
                $result['webp'] = $webp_preview;
            }
        }

        if ($result['can_avif']) {
            $avif_preview = self::preview_avif($file, $temp_path);
            if (!is_wp_error($avif_preview)) {
                $result['avif'] = $avif_preview;
            }
        }

        set_transient('aiio_preview_' . $attachment_id, [
            'path' => $temp_path,
            'webp_path' => $result['webp']['path'] ?? '',
            'avif_path' => $result['avif']['path'] ?? '',
            'time' => time(),
        ], 15 * MINUTE_IN_SECONDS);

        return $result;
    }

    /**
     * @return array|WP_Error
     */
    public static function apply($attachment_id, $args = []) {
        if (!self::is_optimizable($attachment_id, $reason)) {
            return new WP_Error('aiio_not_optimizable', $reason);
        }

        $file = get_attached_file($attachment_id);
        $mime = get_post_mime_type($attachment_id);
        $before = filesize($file);
        $can_auto = true;
        $create_webp = !empty($args['webp']) && $can_auto && !empty(aiio_get_settings()['webp_enabled']) && self::supports_webp();
        $create_avif = !empty($args['avif']) && $can_auto && !empty(aiio_get_settings()['avif_enabled']) && self::supports_avif();

        if ($can_auto && class_exists('AIIO_Backup')) {
            $backup = AIIO_Backup::backup($attachment_id);
            if (is_wp_error($backup)) {
                return $backup;
            }
        }

        $preview = get_transient('aiio_preview_' . $attachment_id);
        $preview_path = is_array($preview) ? ($preview['path'] ?? '') : '';
        $applied_from_preview = false;

        if ($preview_path && is_file($preview_path) && (time() - intval($preview['time'] ?? 0)) < 900) {
            if (!@copy($preview_path, $file)) {
                return new WP_Error('aiio_apply_copy', __('Could not apply optimized image.', 'pewit-ai-image-optimizer'));
            }
            $applied_from_preview = true;
        } else {
            $editor = wp_get_image_editor($file);
            if (is_wp_error($editor)) {
                return $editor;
            }
            $editor->set_quality(self::quality_for_mime($mime));
            $saved = $editor->save($file, $mime);
            if (is_wp_error($saved)) {
                return $saved;
            }
        }

        clearstatcache(true, $file);
        $after = filesize($file);

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

        $webp_result = null;
        if ($create_webp) {
            $webp_result = self::create_webp($attachment_id, $file);
        }

        $avif_result = null;
        if ($create_avif) {
            $avif_result = self::create_avif($attachment_id, $file);
        }

        self::cleanup_preview($attachment_id);

        update_post_meta($attachment_id, '_aiio_last_optimized', current_time('mysql'));
        update_post_meta($attachment_id, '_aiio_saved_bytes', max(0, $before - $after));

        return [
            'attachment_id' => intval($attachment_id),
            'before_bytes' => $before,
            'after_bytes' => $after,
            'saved_bytes' => max(0, $before - $after),
            'saved_percent' => $before > 0 ? round((max(0, $before - $after) / $before) * 100, 1) : 0,
            'applied_from_preview' => $applied_from_preview,
            'webp' => is_wp_error($webp_result) ? ['error' => $webp_result->get_error_message()] : $webp_result,
            'avif' => is_wp_error($avif_result) ? ['error' => $avif_result->get_error_message()] : $avif_result,
        ];
    }

    /**
     * @return array|WP_Error
     */
    public static function create_webp($attachment_id, $source_file = '') {
        if (!self::supports_webp()) {
            return new WP_Error('aiio_webp_unsupported', __('WebP is not supported on this server.', 'pewit-ai-image-optimizer'));
        }

        $source_file = $source_file ?: get_attached_file($attachment_id);
        if (!$source_file || !is_file($source_file)) {
            return new WP_Error('aiio_webp_missing', __('Source image not found.', 'pewit-ai-image-optimizer'));
        }

        $editor = wp_get_image_editor($source_file);
        if (is_wp_error($editor)) {
            return $editor;
        }
        $editor = self::prepare_webp_editor($editor);
        if (is_wp_error($editor)) {
            return $editor;
        }

        $webp_path = preg_replace('/\.(jpe?g|png)$/i', '.webp', $source_file);
        if ($webp_path === $source_file) {
            $webp_path = $source_file . '.webp';
        }

        $saved = $editor->save($webp_path, 'image/webp');
        if (is_wp_error($saved)) {
            return $saved;
        }

        $path = $saved['path'] ?? $webp_path;
        update_post_meta($attachment_id, '_aiio_webp_file', wp_normalize_path($path));

        $upload = wp_get_upload_dir();
        $webp_url = '';
        if (!empty($upload['basedir']) && !empty($upload['baseurl'])) {
            $rel = str_replace(wp_normalize_path($upload['basedir']), '', wp_normalize_path($path));
            $webp_url = $upload['baseurl'] . str_replace('\\', '/', $rel);
        }

        update_post_meta($attachment_id, '_aiio_webp_url', $webp_url);

        return [
            'path' => $path,
            'bytes' => filesize($path),
            'url' => $webp_url,
            'quality' => self::webp_quality(),
            'priority' => self::webp_priority(),
        ];
    }

    /**
     * @return array|WP_Error
     */
    public static function create_avif($attachment_id, $source_file = '') {
        if (!self::supports_avif()) {
            return new WP_Error('aiio_avif_unsupported', __('AVIF is not supported on this server (imageavif / Imagick with libavif required).', 'pewit-ai-image-optimizer'));
        }

        $source_file = $source_file ?: get_attached_file($attachment_id);
        if (!$source_file || !is_file($source_file)) {
            return new WP_Error('aiio_avif_missing', __('Source image not found.', 'pewit-ai-image-optimizer'));
        }

        $avif_path = preg_replace('/\.(jpe?g|png)$/i', '.avif', $source_file);
        if ($avif_path === $source_file) {
            $avif_path = $source_file . '.avif';
        }

        $editor = wp_get_image_editor($source_file);
        if (!is_wp_error($editor)) {
            $saved = $editor->save($avif_path, 'image/avif');
            if (!is_wp_error($saved) && !empty($saved['path']) && is_file($saved['path'])) {
                return self::finalize_avif_sidecar($attachment_id, $saved['path']);
            }
        }

        $gd = self::create_avif_gd($source_file, $avif_path);
        if (is_wp_error($gd)) {
            return $gd;
        }

        return self::finalize_avif_sidecar($attachment_id, $avif_path);
    }

    private static function finalize_avif_sidecar($attachment_id, $path) {
        update_post_meta($attachment_id, '_aiio_avif_file', wp_normalize_path($path));
        $url = self::path_to_upload_url($path);
        update_post_meta($attachment_id, '_aiio_avif_url', $url);

        return [
            'path'  => $path,
            'bytes' => is_file($path) ? filesize($path) : 0,
            'url'   => $url,
        ];
    }

    private static function path_to_upload_url($path) {
        $upload = wp_get_upload_dir();
        if (empty($upload['basedir']) || empty($upload['baseurl'])) {
            return '';
        }
        $rel = str_replace(wp_normalize_path($upload['basedir']), '', wp_normalize_path($path));
        return $upload['baseurl'] . str_replace('\\', '/', $rel);
    }

    /**
     * @return true|WP_Error
     */
    private static function create_avif_gd($source_file, $avif_path) {
        if (!function_exists('imageavif')) {
            return new WP_Error('aiio_avif_gd', __('GD imageavif() is not available.', 'pewit-ai-image-optimizer'));
        }

        $mime = wp_check_filetype($source_file)['type'] ?? '';
        if ($mime === 'image/jpeg' && function_exists('imagecreatefromjpeg')) {
            $img = @imagecreatefromjpeg($source_file);
        } elseif ($mime === 'image/png' && function_exists('imagecreatefrompng')) {
            $img = @imagecreatefrompng($source_file);
        } else {
            return new WP_Error('aiio_avif_gd', __('Unsupported source type for AVIF encoding.', 'pewit-ai-image-optimizer'));
        }

        if (!$img) {
            return new WP_Error('aiio_avif_gd', __('Could not load source image for AVIF.', 'pewit-ai-image-optimizer'));
        }

        $quality = self::avif_quality();
        $ok = @imageavif($img, $avif_path, $quality, 6);
        imagedestroy($img);

        if (!$ok || !is_file($avif_path)) {
            return new WP_Error('aiio_avif_gd', __('AVIF encoding failed.', 'pewit-ai-image-optimizer'));
        }

        return true;
    }

    private static function preview_avif($source_file, $optimized_file = '') {
        $editor = wp_get_image_editor($optimized_file ?: $source_file);
        if (!is_wp_error($editor)) {
            $saved = $editor->save(null, 'image/avif');
            if (!is_wp_error($saved) && !empty($saved['path']) && is_file($saved['path'])) {
                return [
                    'path'  => $saved['path'],
                    'bytes' => filesize($saved['path']),
                ];
            }
        }

        $tmp = wp_tempnam('aiio-avif-preview');
        if (!$tmp) {
            return new WP_Error('aiio_avif_preview', __('AVIF preview failed.', 'pewit-ai-image-optimizer'));
        }
        $result = self::create_avif_gd($optimized_file ?: $source_file, $tmp);
        if (is_wp_error($result)) {
            wp_delete_file($tmp);
            return $result;
        }

        return [
            'path'  => $tmp,
            'bytes' => filesize($tmp),
        ];
    }

    private static function preview_webp($source_file, $optimized_file = '') {
        $editor = wp_get_image_editor($optimized_file ?: $source_file);
        if (is_wp_error($editor)) {
            return $editor;
        }
        $editor = self::prepare_webp_editor($editor);
        if (is_wp_error($editor)) {
            return $editor;
        }

        $saved = $editor->save(null, 'image/webp');
        if (is_wp_error($saved)) {
            return $saved;
        }

        $path = $saved['path'] ?? '';
        if (!$path || !is_file($path)) {
            return new WP_Error('aiio_webp_preview', __('WebP preview failed.', 'pewit-ai-image-optimizer'));
        }

        return [
            'path' => $path,
            'bytes' => filesize($path),
            'quality' => self::webp_quality(),
            'priority' => self::webp_priority(),
        ];
    }

    public static function cleanup_preview($attachment_id) {
        $preview = get_transient('aiio_preview_' . $attachment_id);
        if (!is_array($preview)) {
            delete_transient('aiio_preview_' . $attachment_id);
            return;
        }
        foreach (['path', 'webp_path', 'avif_path'] as $key) {
            if (!empty($preview[$key]) && is_file($preview[$key])) {
                wp_delete_file($preview[$key]);
            }
        }
        delete_transient('aiio_preview_' . $attachment_id);
    }

    public static function format_bytes($bytes) {
        $bytes = max(0, intval($bytes));
        if ($bytes >= 1048576) {
            return round($bytes / 1048576, 2) . ' MB';
        }
        if ($bytes >= 1024) {
            return round($bytes / 1024, 1) . ' KB';
        }
        return $bytes . ' B';
    }
}
