<?php

namespace Mamba\Modules\Media\Services;

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

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

final class WebPConverter {
    
    private const WEBP_META_KEY = '_mamba_webp_conversion';
    
    public function register(): void {
        // WebP Conversion is now a Free feature
        if (!get_option('mamba_enable_webp_conversion', 0)) {
            return;
        }
        
        add_filter('wp_generate_attachment_metadata', [$this, 'processNewUpload'], 10, 2);
        add_filter('wp_get_attachment_image_attributes', [$this, 'addWebPInfo'], 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_webp_quality', 85);
        
        foreach ($metadata['sizes'] ?? [] as $sizeName => $sizeData) {
            $this->processImageSize($attachmentId, $sizeName, $sizeData, $quality);
        }
        
        if (get_option('mamba_convert_full_size', 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;
        }
        
        $webpPath = $this->getWebPPath($filePath);
        if (!$webpPath || !is_string($webpPath)) {
            return false;
        }
        
        // Check if already converted and has backup
        $webpData = get_post_meta($attachmentId, self::WEBP_META_KEY, true) ?: [];
        $existingBackup = $webpData[$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 WebP
        $success = $this->convertToWebP($filePath, $webpPath, $quality);
        
        if ($success) {
            $this->storeWebPInfo($attachmentId, $sizeName, $quality, $webpPath, $backupPath);
            
            // Track savings if we have valid sizes
            $webpSize = @filesize($webpPath);
            if ($originalSize > 0 && $webpSize > 0) {
                SavingsTracker::trackImageSavings($originalSize, $webpSize, 'webp');
            }
        }
        
        return $success;
    }
    
    private function convertToWebP(string $sourcePath, string $webpPath, int $quality): bool {
        if (!function_exists('wp_image_editor_supports') ||
            !wp_image_editor_supports(['mime_type' => 'image/webp'])) {
            return false;
        }
        
        // Validate and normalize paths
        $sourcePath = wp_normalize_path($sourcePath);
        $webpPath = wp_normalize_path($webpPath);
        
        if (empty($sourcePath) || empty($webpPath) || 
            !is_string($sourcePath) || !is_string($webpPath)) {
            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 WebP
        $editor->set_quality($quality);
        $result = $editor->save($webpPath, 'image/webp');
        
        return !is_wp_error($result);
    }
    
    private function createBackup(string $filePath, int $attachmentId, string $sizeName): ?string {
        $uploadDir = wp_upload_dir();
        $backupDir = $uploadDir['basedir'] . '/mamba-backups/webp/' . $attachmentId;
        
        if (!wp_mkdir_p($backupDir)) {
            return null;
        }
        
        $backupPath = $backupDir . '/' . $sizeName . '_original_' . basename($filePath);
        
        if (!copy($filePath, $backupPath)) {
            return null;
        }
        
        return $backupPath;
    }
    
    private function getWebPPath(string $originalPath): ?string {
        // Create WebP path by appending .webp to the original filename
        // This creates files like image.jpg.webp (not image.webp)
        // to match the .htaccess rewrite rules
        return $originalPath . '.webp';
    }
    
    private function storeWebPInfo(int $attachmentId, string $sizeName, int $quality, string $webpPath, string $backupPath): void {
        $webpData = get_post_meta($attachmentId, self::WEBP_META_KEY, true) ?: [];
        $webpData[$sizeName] = [
            'quality' => $quality,
            'webp_path' => $webpPath,
            'backup_path' => $backupPath,
            'converted_at' => current_time('mysql')
        ];
        
        update_post_meta($attachmentId, self::WEBP_META_KEY, $webpData);
        wp_cache_delete('mamba_webp_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;
        }
        
        $webpData = get_post_meta($attachmentId, self::WEBP_META_KEY, true);
        if (!empty($webpData)) {
            return false;
        }
        
        return $this->isWooCommerceImage($attachmentId);
    }
    
    /**
     * Process image when it's linked to a product
     */
    public function processLinkedImage(int $metaId, int $postId, string $metaKey, $metaValue): void {
        // Check if this is a product linking to an image
        if ($metaKey === '_thumbnail_id' || $metaKey === '_product_image_gallery') {
            $attachmentId = (int) $metaValue;
            
            // For gallery, check each image
            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);
            }
        }
    }
    
    /**
     * Process image if it needs WebP conversion
     */
    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_webp_quality', 85);
        
        foreach ($metadata['sizes'] ?? [] as $sizeName => $sizeData) {
            $this->processImageSize($attachmentId, $sizeName, $sizeData, $quality);
        }
        
        if (get_option('mamba_convert_full_size', 0)) {
            $this->processImageSize($attachmentId, 'full', $metadata, $quality);
        }
    }
    
    private function isWooCommerceImage(int $attachmentId): bool {
        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
        $products = get_posts([
            'post_type' => 'product',
            'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                [
                    'key' => '_thumbnail_id',
                    'value' => $attachmentId
                ]
            ],
            'posts_per_page' => 1
        ]);
        
        if (!empty($products)) {
            return true;
        }
        
        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
        $products = get_posts([
            'post_type' => 'product',
            'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                [
                    'key' => '_product_image_gallery',
                    'value' => $attachmentId,
                    'compare' => 'LIKE'
                ]
            ],
            'posts_per_page' => 1
        ]);
        
        if (!empty($products)) {
            return true;
        }
        
        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
        $variations = get_posts([
            'post_type' => 'product_variation',
            'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
                [
                    'key' => '_thumbnail_id',
                    'value' => $attachmentId
                ]
            ],
            'posts_per_page' => 1
        ]);
        
        return !empty($variations);
    }
    

    
    public function addWebPInfo(array $attr, $attachment, $size): array {
        if (!is_object($attachment)) {
            return $attr;
        }
        
        $webpData = get_post_meta($attachment->ID, self::WEBP_META_KEY, true);
        if (!empty($webpData)) {
            $attr['data-mamba-webp'] = 'true';
        }
        
        return $attr;
    }
    
    public function revertWebP(int $attachmentId): bool {
        $webpData = get_post_meta($attachmentId, self::WEBP_META_KEY, true);
        if (empty($webpData)) {
            return false;
        }
        
        $success = true;
        $backupDir = null;
        
        foreach ($webpData as $sizeName => $data) {
            $webpPath = $data['webp_path'] ?? '';
            $backupPath = $data['backup_path'] ?? '';
            
            // Remove WebP file
            if ($webpPath && file_exists($webpPath)) {
                if (!unlink($webpPath)) {
                    $success = false;
                }
            }
            
            // Restore original if backup exists
            if ($backupPath && file_exists($backupPath)) {
                $originalPath = $this->getImagePath($attachmentId, $sizeName);
                if ($originalPath && !copy($backupPath, $originalPath)) {
                    $success = false;
                }
                
                // Track backup directory for cleanup
                if ($backupDir === null) {
                    $backupDir = dirname($backupPath);
                }
            }
        }
        
        if ($success) {
            delete_post_meta($attachmentId, self::WEBP_META_KEY);
            wp_cache_delete('mamba_webp_stats', 'mamba_media');
            
            // Clean up WebP backup directory
            if ($backupDir && is_dir($backupDir)) {
                try {
                    // Only remove files listed in our meta (WebP backups)
                    foreach ($webpData as $sizeName => $data) {
                        $backupPath = $data['backup_path'] ?? '';
                        if ($backupPath && file_exists($backupPath)) {
                            unlink($backupPath);
                        }
                    }
                    
                    // Remove directory if empty
                    $remainingFiles = glob($backupDir . '/*');
                    if (empty($remainingFiles)) {
                        rmdir($backupDir);
                    }
                } catch (\Exception $e) {
                    // Suppress cleanup failures - not critical
                }
            }
        }
        
        return $success;
    }
    
    public function getWebPStats(): array {
        $cached = wp_cache_get('mamba_webp_stats', 'mamba_media');
        if (false !== $cached) {
            return $cached;
        }

        global $wpdb;
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $webpCount = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} 
             WHERE meta_key = %s",
            self::WEBP_META_KEY
        ));
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $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) $webpCount,
            'total' => (int) $totalImages,
            'percentage' => $totalImages > 0 ? round(($webpCount / $totalImages) * 100, 1) : 0
        ];
        
        wp_cache_set('mamba_webp_stats', $stats, 'mamba_media', 3600);
        return $stats;
    }
}
