<?php

namespace App\Services;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class ImageService
{
    /**
     * Upload and optionally convert image to WebP.
     */
    public function upload(UploadedFile $file, string $directory = 'images', bool $convertToWebP = true): string
    {
        $filename = Str::uuid() . '_' . time();

        if ($convertToWebP && $this->canConvertToWebP() && $this->isConvertibleImage($file)) {
            return $this->uploadAsWebP($file, $directory, $filename);
        }

        $extension = $file->getClientOriginalExtension();
        $path = $file->storeAs($directory, "{$filename}.{$extension}", 'public');

        return $path;
    }

    /**
     * Upload image and convert to WebP format.
     */
    protected function uploadAsWebP(UploadedFile $file, string $directory, string $filename): string
    {
        $image = $this->createImageResource($file);

        if (!$image) {
            // Fallback: store original if conversion fails
            $extension = $file->getClientOriginalExtension();
            return $file->storeAs($directory, "{$filename}.{$extension}", 'public');
        }

        $path = "{$directory}/{$filename}.webp";
        $fullPath = Storage::disk('public')->path($path);

        // Ensure directory exists
        $dir = dirname($fullPath);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        // Convert to WebP with 85% quality
        imagewebp($image, $fullPath, 85);
        imagedestroy($image);

        return $path;
    }

    /**
     * Create GD image resource from uploaded file.
     */
    protected function createImageResource(UploadedFile $file)
    {
        $mime = $file->getMimeType();
        $sourcePath = $file->getPathname();

        return match ($mime) {
            'image/jpeg', 'image/jpg' => imagecreatefromjpeg($sourcePath),
            'image/png' => $this->createFromPngPreservingTransparency($sourcePath),
            'image/gif' => imagecreatefromgif($sourcePath),
            'image/webp' => imagecreatefromwebp($sourcePath),
            default => null,
        };
    }

    /**
     * Create image from PNG while preserving transparency.
     */
    protected function createFromPngPreservingTransparency(string $path)
    {
        $image = imagecreatefrompng($path);
        if ($image) {
            imagepalettetotruecolor($image);
            imagealphablending($image, true);
            imagesavealpha($image, true);
        }
        return $image;
    }

    /**
     * Check if GD supports WebP.
     */
    protected function canConvertToWebP(): bool
    {
        if (!function_exists('imagewebp')) {
            return false;
        }

        if (function_exists('gd_info')) {
            $info = gd_info();
            return !empty($info['WebP Support']);
        }

        return false;
    }

    /**
     * Check if the file is a convertible image type.
     */
    protected function isConvertibleImage(UploadedFile $file): bool
    {
        return in_array($file->getMimeType(), [
            'image/jpeg',
            'image/jpg',
            'image/png',
            'image/gif',
            'image/webp',
        ]);
    }

    /**
     * Delete an image from storage.
     */
    public function delete(?string $path): bool
    {
        if (!$path) {
            return false;
        }

        return Storage::disk('public')->delete($path);
    }

    /**
     * Get the full URL for a stored image.
     */
    public function url(?string $path): ?string
    {
        if (!$path) {
            return null;
        }

        return Storage::disk('public')->url($path);
    }

    /**
     * Upload multiple images.
     */
    public function uploadMultiple(array $files, string $directory = 'images'): array
    {
        $paths = [];
        foreach ($files as $file) {
            if ($file instanceof UploadedFile) {
                $paths[] = $this->upload($file, $directory);
            }
        }
        return $paths;
    }

    /**
     * Create a thumbnail from an existing stored image.
     */
    public function createThumbnail(string $originalPath, int $width = 300, int $height = 300): ?string
    {
        $fullPath = Storage::disk('public')->path($originalPath);

        if (!file_exists($fullPath)) {
            return null;
        }

        $imageInfo = getimagesize($fullPath);
        if (!$imageInfo) {
            return null;
        }

        $source = match ($imageInfo['mime']) {
            'image/jpeg' => imagecreatefromjpeg($fullPath),
            'image/png' => imagecreatefrompng($fullPath),
            'image/webp' => imagecreatefromwebp($fullPath),
            'image/gif' => imagecreatefromgif($fullPath),
            default => null,
        };

        if (!$source) {
            return null;
        }

        $origWidth = imagesx($source);
        $origHeight = imagesy($source);

        // Calculate dimensions maintaining aspect ratio
        $ratio = min($width / $origWidth, $height / $origHeight);
        $newWidth = (int) round($origWidth * $ratio);
        $newHeight = (int) round($origHeight * $ratio);

        $thumb = imagecreatetruecolor($newWidth, $newHeight);

        // Preserve transparency
        imagealphablending($thumb, false);
        imagesavealpha($thumb, true);

        imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);

        $thumbDir = dirname($originalPath) . '/thumbnails';
        $thumbFilename = pathinfo($originalPath, PATHINFO_FILENAME) . '_thumb.webp';
        $thumbPath = "{$thumbDir}/{$thumbFilename}";
        $thumbFullPath = Storage::disk('public')->path($thumbPath);

        $dir = dirname($thumbFullPath);
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }

        imagewebp($thumb, $thumbFullPath, 80);
        imagedestroy($source);
        imagedestroy($thumb);

        return $thumbPath;
    }
}
