<?php

/*
|--------------------------------------------------------------------------
| OwnStore - Build your own online store
| Author: TakfeDev (MKJUEL)
| All Rights Reserved
|--------------------------------------------------------------------------
*/

namespace App\Services;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use App\Models\Setting;

class ImageOptimizer
{
    /**
     * Compress, resize, and upload an image based on Admin CP settings.
     * Uses Pure Native PHP GD (Zero third-party dependencies).
     * Guaranteed to work on all Shared Hosting environments.
     *
     * @param UploadedFile $file
     * @param string $directory
     * @return string Returns the stored file path
     */
    public static function upload(UploadedFile $file, string $directory): string
    {
        try {
            // 1. Check if Compression is Enabled globally
            $enabled = filter_var(Setting::where('key', 'image_compression_enabled')->value('value') ?? true, FILTER_VALIDATE_BOOLEAN);
            
            // If disabled or PHP GD is missing on the server, fallback to standard Laravel upload
            if (!$enabled || !extension_loaded('gd')) {
                return $file->store($directory, 'public');
            }

            // 2. Fetch Settings from Database
            $format = Setting::where('key', 'image_output_format')->value('value') ?? 'webp';
            $quality = (int) (Setting::where('key', 'image_quality')->value('value') ?? 80);
            $maxWidth = (int) (Setting::where('key', 'image_max_width')->value('value') ?? 1200);

            // 3. Get Source Image Information
            $sourcePath = $file->getRealPath();
            $mime = mime_content_type($sourcePath);

            // 4. Create GD Image Resource based on Mime Type
            $image = match ($mime) {
                'image/jpeg', 'image/jpg' => @imagecreatefromjpeg($sourcePath),
                'image/png' => @imagecreatefrompng($sourcePath),
                'image/webp' => @imagecreatefromwebp($sourcePath),
                'image/gif' => @imagecreatefromgif($sourcePath),
                default => false,
            };

            // If the image type isn't supported, fallback to standard upload
            if (!$image) {
                return $file->store($directory, 'public');
            }

            // 5. Get Original Dimensions
            $origWidth = imagesx($image);
            $origHeight = imagesy($image);

            // 6. Calculate New Dimensions (Maintain Aspect Ratio)
            if ($maxWidth > 0 && $origWidth > $maxWidth) {
                $newWidth = $maxWidth;
                $newHeight = (int) round(($origHeight / $origWidth) * $newWidth);
            } else {
                $newWidth = $origWidth;
                $newHeight = $origHeight;
            }

            // 7. Create New Canvas
            $canvas = imagecreatetruecolor($newWidth, $newHeight);

            // Handle Transparency for PNG and WEBP
            if ($format === 'png' || $format === 'webp') {
                imagealphablending($canvas, false);
                imagesavealpha($canvas, true);
                $transparent = imagecolorallocatealpha($canvas, 255, 255, 255, 127);
                imagefill($canvas, 0, 0, $transparent);
            } else {
                // Fill with white background for JPEGs (removes black backgrounds from transparent PNGs)
                $white = imagecolorallocate($canvas, 255, 255, 255);
                imagefill($canvas, 0, 0, $white);
            }

            // 8. Resample Image onto Canvas
            imagecopyresampled($canvas, $image, 0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);

            // 9. Capture Output to Memory Buffer
            ob_start();
            if ($format === 'webp') {
                imagewebp($canvas, null, $quality);
            } elseif ($format === 'png') {
                // GD PNG quality scale is 0-9 (0 is no compression, 9 is max). Convert from 0-100 scale.
                $pngQuality = (int) round(9 - ($quality * 0.09));
                imagepng($canvas, null, $pngQuality);
            } else {
                $format = 'jpg';
                imagejpeg($canvas, null, $quality);
            }
            $imageData = ob_get_clean(); // Get binary image data from buffer

            // Free up server memory
            imagedestroy($image);
            imagedestroy($canvas);

            // 10. Generate random filename and save using Laravel Storage
            $filename = Str::random(40) . '.' . $format;
            $path = trim($directory, '/') . '/' . $filename;

            Storage::disk('public')->put($path, $imageData);

            return $path;

        } catch (\Exception $e) {
            // Failsafe: If optimization fails (e.g. corrupted image, memory limit), upload original securely
            Log::error('Native Image Optimization Failed: ' . $e->getMessage());
            return $file->store($directory, 'public');
        }
    }
}