<?php

namespace App\Http\Controllers;

use App\Models\Product;
use App\Models\ProductImage;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class ImageController extends Controller
{
    private const MAX_IMAGES      = 10;
    private const MAX_SIZE_MB     = 50;
    private const ALLOWED_MIMES   = ['image/jpeg', 'image/png', 'image/webp'];
    private const MAX_WIDTH       = 1200;

    public function upload(Request $request, int $productId): JsonResponse
    {
        $product = Product::findOrFail($productId);

        // Check image count limit
        if ($product->images()->count() >= self::MAX_IMAGES) {
            return response()->json([
                'success' => false,
                'message' => 'Product already has maximum ' . self::MAX_IMAGES . ' images.',
            ], 422);
        }

        $request->validate([
            'image'      => 'required|file|mimes:jpeg,png,webp|max:' . (self::MAX_SIZE_MB * 1024),
            'is_primary' => 'boolean',
        ]);

        $file   = $request->file('image');
        $path   = $file->store('products', 'public');

        // Optimize image (resize to max 1200px width using GD)
        $optimizedPath = $this->optimizeImage($path);

        $isPrimary = $request->boolean('is_primary', false);

        // If setting as primary, unset others
        if ($isPrimary) {
            $product->images()->update(['is_primary' => false]);
        }

        // If this is the first image, make it primary
        if ($product->images()->count() === 0) {
            $isPrimary = true;
        }

        $image = ProductImage::create([
            'product_id'     => $productId,
            'path'           => $path,
            'optimized_path' => $optimizedPath,
            'is_primary'     => $isPrimary,
            'sort_order'     => $product->images()->count(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Image uploaded successfully.',
            'data'    => $image,
        ], 201);
    }

    public function setPrimary(int $productId, int $imageId): JsonResponse
    {
        $product = Product::findOrFail($productId);
        $image   = ProductImage::where('product_id', $productId)->findOrFail($imageId);

        $product->images()->update(['is_primary' => false]);
        $image->update(['is_primary' => true]);

        return response()->json([
            'success' => true,
            'message' => 'Primary image updated.',
        ]);
    }

    public function destroy(int $productId, int $imageId): JsonResponse
    {
        $image = ProductImage::where('product_id', $productId)->findOrFail($imageId);

        // Delete files from storage
        Storage::disk('public')->delete($image->path);
        if ($image->optimized_path && $image->optimized_path !== $image->path) {
            Storage::disk('public')->delete($image->optimized_path);
        }

        $wasPrimary = $image->is_primary;
        $image->delete();

        // If deleted image was primary, set first remaining as primary
        if ($wasPrimary) {
            $firstImage = ProductImage::where('product_id', $productId)->first();
            if ($firstImage) {
                $firstImage->update(['is_primary' => true]);
            }
        }

        return response()->json([
            'success' => true,
            'message' => 'Image deleted successfully.',
        ]);
    }

    private function optimizeImage(string $storagePath): string
    {
        $fullPath = Storage::disk('public')->path($storagePath);

        if (!function_exists('imagecreatefromjpeg')) {
            return $storagePath; // GD not available, return original
        }

        try {
            [$width, $height, $type] = getimagesize($fullPath);

            if ($width <= self::MAX_WIDTH) {
                return $storagePath; // No resizing needed
            }

            $ratio     = self::MAX_WIDTH / $width;
            $newWidth  = self::MAX_WIDTH;
            $newHeight = (int) ($height * $ratio);

            // Create source image
            $source = match ($type) {
                IMAGETYPE_JPEG => imagecreatefromjpeg($fullPath),
                IMAGETYPE_PNG  => imagecreatefrompng($fullPath),
                IMAGETYPE_WEBP => imagecreatefromwebp($fullPath),
                default        => null,
            };

            if (!$source) {
                return $storagePath;
            }

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

            // Preserve transparency for PNG
            if ($type === IMAGETYPE_PNG) {
                imagealphablending($destination, false);
                imagesavealpha($destination, true);
            }

            imagecopyresampled($destination, $source, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);

            $optimizedPath = str_replace('.', '_optimized.', $storagePath);
            $fullOptPath   = Storage::disk('public')->path($optimizedPath);

            match ($type) {
                IMAGETYPE_JPEG => imagejpeg($destination, $fullOptPath, 85),
                IMAGETYPE_PNG  => imagepng($destination, $fullOptPath, 7),
                IMAGETYPE_WEBP => imagewebp($destination, $fullOptPath, 85),
                default        => copy($fullPath, $fullOptPath),
            };

            imagedestroy($source);
            imagedestroy($destination);

            return $optimizedPath;
        } catch (\Throwable $e) {
            return $storagePath;
        }
    }
}
