<?php
namespace Mamba\Modules\Media\Services;

use Mamba\Support\Logger;
use Mamba\Support\SavingsTracker;

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

final class AvifConverter {
    
    private const AVIF_META_KEY = '_mamba_avif_conversion';
    
    public function register(): void {
        // Feature Gating: AVIF Conversion is a Premium feature
        if (!get_option('mamba_enable_avif_conversion', 0) || !function_exists('mamba_fs') || !mamba_fs()->can_use_premium_code__premium_only()) {
            return;
        }
        
        add_filter('wp_generate_attachment_metadata', [$this, 'processNewUpload'], 10, 2);
        add_filter('wp_get_attachment_image_attributes', [$this, 'addAvifInfo'], 10, 3);
        
        // Process images when they're linked to products
        add_action('added_post_meta', [$this, 'processLinkedImage'], 10, 4);
        add_action('updated_post_meta', [$this, 'processLinkedImage'], 10, 4);
    }
    
    public function processNewUpload(array $metadata, int $attachmentId): array {
        if (!$this->shouldProcessAttachment($attachmentId)) {
            return $metadata;
        }
        
        $quality = (int) get_option('mamba_avif_quality', 65); // AVIF quality is usually lower than WebP for same visual result
        
        foreach ($metadata['sizes'] ?? [] as $sizeName => $sizeData) {
            $this->processImageSize($attachmentId, $sizeName, $sizeData, $quality);
        }
        
        if (get_option('mamba_convert_full_size_avif', 0)) {
            $this->processImageSize($attachmentId, 'full', $metadata, $quality);
        }
        
        return $metadata;
    }
    
    public function processImageSize(int $attachmentId, string $sizeName, array $_sizeData, int $quality): bool {
        $filePath = $this->getImagePath($attachmentId, $sizeName);
        if (!$filePath || !file_exists($filePath)) {
            return false;
        }
        
        $avifPath = $this->getAvifPath($filePath);
        if (!$avifPath || !is_string($avifPath)) {
            return false;
        }
        
        // Check if already converted and has backup
        $avifData = get_post_meta($attachmentId, self::AVIF_META_KEY, true) ?: [];
        $existingBackup = $avifData[$sizeName]['backup_path'] ?? null;
        
        // Only create backup if we don't have one
        if (!$existingBackup || !file_exists($existingBackup)) {
            $backupPath = $this->createBackup($filePath, $attachmentId, $sizeName);
            if (!$backupPath) {
                return false;
            }
        } else {
            $backupPath = $existingBackup;
        }
        
        // Get original file size before conversion
        $originalSize = @filesize($filePath);
        
        // Convert to AVIF
        $success = $this->convertToAvif($filePath, $avifPath, $quality);
        
        if ($success) {
            $this->storeAvifInfo($attachmentId, $sizeName, $quality, $avifPath, $backupPath);
            
            // Track savings if we have valid sizes
            $avifSize = @filesize($avifPath);
            if ($originalSize > 0 && $avifSize > 0) {
                SavingsTracker::trackImageSavings($originalSize, $avifSize, 'avif');
            }
        }
        
        return $success;
    }
    
    private function convertToAvif(string $sourcePath, string $avifPath, int $quality): bool {
        if (!function_exists('wp_image_editor_supports') ||
            !wp_image_editor_supports(['mime_type' => 'image/avif'])) {
            return false;
        }
        
        // Validate and normalize paths
        $sourcePath = wp_normalize_path($sourcePath);
        $avifPath = wp_normalize_path($avifPath);
        
        if (empty($sourcePath) || empty($avifPath) || 
            !is_string($sourcePath) || !is_string($avifPath)) {
            return false;
        }
        
        if (!file_exists($sourcePath) || !is_readable($sourcePath)) {
            return false;
        }
        
        $editor = wp_get_image_editor($sourcePath);
        
        if (is_wp_error($editor)) {
            return false;
        }
        
        // Set quality and save as AVIF
        $editor->set_quality($quality);
        $result = $editor->save($avifPath, 'image/avif');
        
        return !is_wp_error($result);
    }
    
    private function createBackup(string $filePath, int $attachmentId, string $sizeName): ?string {
        $uploadDir = wp_upload_dir();
        $backupDir = $uploadDir['basedir'] . '/mamba-backups/avif/' . $attachmentId;
        
        if (!wp_mkdir_p($backupDir)) {
            return null;
        }
        
        $backupPath = $backupDir . '/' . $sizeName . '_original_' . basename($filePath);
        
        if (!copy($filePath, $backupPath)) {
            return null;
        }
        
        return $backupPath;
    }
    
    private function getAvifPath(string $originalPath): ?string {
        return $originalPath . '.avif';
    }
    
    private function storeAvifInfo(int $attachmentId, string $sizeName, int $quality, string $avifPath, string $backupPath): void {
        $avifData = get_post_meta($attachmentId, self::AVIF_META_KEY, true) ?: [];
        $avifData[$sizeName] = [
            'quality' => $quality,
            'avif_path' => $avifPath,
            'backup_path' => $backupPath,
            'converted_at' => current_time('mysql')
        ];
        
        update_post_meta($attachmentId, self::AVIF_META_KEY, $avifData);
        wp_cache_delete('mamba_avif_stats', 'mamba_media');
    }
    
    private function getImagePath(int $attachmentId, string $sizeName): ?string {
        if ($sizeName === 'full') {
            $filePath = get_attached_file($attachmentId);
            return $filePath ? wp_normalize_path($filePath) : null;
        }

        $metadata = wp_get_attachment_metadata($attachmentId);
        if (!is_array($metadata) || !isset($metadata['file'], $metadata['sizes'][$sizeName]['file'])) {
            return null;
        }

        $uploadDir = wp_upload_dir();
        if (is_wp_error($uploadDir) || !isset($uploadDir['basedir'])) {
            return null;
        }
        
        $path = trailingslashit($uploadDir['basedir'])
            . dirname($metadata['file']) . '/'
            . $metadata['sizes'][$sizeName]['file'];
            
        return wp_normalize_path($path);
    }
    
    private function shouldProcessAttachment(int $attachmentId): bool {
        $mimeType = get_post_mime_type($attachmentId);
        if (!in_array($mimeType, ['image/jpeg', 'image/png'], true)) {
            return false;
        }
        
        $avifData = get_post_meta($attachmentId, self::AVIF_META_KEY, true);
        if (!empty($avifData)) {
            return false;
        }
        
        return $this->isWooCommerceImage($attachmentId);
    }
    
    public function processLinkedImage(int $metaId, int $postId, string $metaKey, $metaValue): void {
        if ($metaKey === '_thumbnail_id' || $metaKey === '_product_image_gallery') {
            $attachmentId = (int) $metaValue;
            
            if ($metaKey === '_product_image_gallery' && is_string($metaValue)) {
                $galleryIds = array_filter(array_map('intval', explode(',', $metaValue)));
                foreach ($galleryIds as $galleryId) {
                    $this->processImageIfNeeded($galleryId);
                }
            } else {
                $this->processImageIfNeeded($attachmentId);
            }
        }
    }
    
    private function processImageIfNeeded(int $attachmentId): void {
        if (!$this->shouldProcessAttachment($attachmentId)) {
            return;
        }
        
        $metadata = wp_get_attachment_metadata($attachmentId);
        if (!$metadata) {
            return;
        }
        
        $quality = (int) get_option('mamba_avif_quality', 65);
        
        foreach ($metadata['sizes'] ?? [] as $sizeName => $sizeData) {
            $this->processImageSize($attachmentId, $sizeName, $sizeData, $quality);
        }
        
        if (get_option('mamba_convert_full_size_avif', 0)) {
            $this->processImageSize($attachmentId, 'full', $metadata, $quality);
        }
    }
    
    private function isWooCommerceImage(int $attachmentId): bool {
        // Optimization: checking if linked to product, variation or in gallery
        // Try cache first
        $cacheKey = 'mamba_wc_img_' . $attachmentId;
        $cached = wp_cache_get($cacheKey, 'mamba_media');
        if (false !== $cached) {
            return (bool) $cached;
        }
        
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Cached above
        $count = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->postmeta} 
             WHERE meta_value = %s AND (meta_key = '_thumbnail_id' OR meta_key = '_product_image_gallery' OR (meta_key = '_product_image_gallery' AND meta_value LIKE %s))",
            $attachmentId,
            '%' . $attachmentId . '%'
        ));
        
        $result = (int)$count > 0;
        wp_cache_set($cacheKey, $result ? 1 : 0, 'mamba_media', 3600);
        return $result;
    }
    
    public function addAvifInfo(array $attr, $attachment, $size): array {
        if (!is_object($attachment)) {
            return $attr;
        }
        
        $avifData = get_post_meta($attachment->ID, self::AVIF_META_KEY, true);
        if (!empty($avifData)) {
            $attr['data-mamba-avif'] = 'true';
        }
        
        return $attr;
    }
    
    public function revertAvif(int $attachmentId): bool {
        $avifData = get_post_meta($attachmentId, self::AVIF_META_KEY, true);
        if (empty($avifData)) {
            return false;
        }
        
        $success = true;
        $backupDir = null;
        
        foreach ($avifData as $sizeName => $data) {
            $avifPath = $data['avif_path'] ?? '';
            $backupPath = $data['backup_path'] ?? '';
            
            if ($avifPath && file_exists($avifPath)) {
                if (!unlink($avifPath)) {
                    $success = false;
                }
            }
            
            if ($backupPath && file_exists($backupPath)) {
                $originalPath = $this->getImagePath($attachmentId, $sizeName);
                if ($originalPath && !copy($backupPath, $originalPath)) {
                    $success = false;
                }
                
                if ($backupDir === null) {
                    $backupDir = dirname($backupPath);
                }
            }
        }
        
        if ($success) {
            delete_post_meta($attachmentId, self::AVIF_META_KEY);
            wp_cache_delete('mamba_avif_stats', 'mamba_media');
            
            if ($backupDir && is_dir($backupDir)) {
                try {
                    foreach ($avifData as $sizeName => $data) {
                        $backupPath = $data['backup_path'] ?? '';
                        if ($backupPath && file_exists($backupPath)) {
                            unlink($backupPath);
                        }
                    }
                    
                    $remainingFiles = glob($backupDir . '/*');
                    if (empty($remainingFiles)) {
                        rmdir($backupDir);
                    }
                } catch (\Exception $e) {}
            }
        }
        
        return $success;
    }
    
    public function getAvifStats(): array {
        $cached = wp_cache_get('mamba_avif_stats', 'mamba_media');
        if (false !== $cached) {
            return $cached;
        }

        global $wpdb;
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Cached at function start
        $avifCount = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} 
             WHERE meta_key = %s",
            self::AVIF_META_KEY
        ));
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Cached at function start
        $totalImages = $wpdb->get_var("
            SELECT COUNT(*) FROM {$wpdb->posts} 
            WHERE post_type = 'attachment' 
            AND post_mime_type IN ('image/jpeg', 'image/png')
        ");
        
        $stats = [
            'converted' => (int) $avifCount,
            'total' => (int) $totalImages,
            'percentage' => $totalImages > 0 ? round(($avifCount / $totalImages) * 100, 1) : 0
        ];
        
        wp_cache_set('mamba_avif_stats', $stats, 'mamba_media', 3600);
        return $stats;
    }
}
