<?php
declare(strict_types=1);

namespace App\Shared\Services;

use App\Core\App;

final class PhotoUploadService
{
    private const MAX_SIZE_BYTES = 5 * 1024 * 1024;
    private const MAX_DIMENSION = 8000;
    private const OUTPUT_MAX_WIDTH = 800;
    private const OUTPUT_MAX_HEIGHT = 800;
    private const THUMBNAIL_SIZE = 200;
    private const JPEG_QUALITY = 82;
    private const ALLOWED_MIMES = ['image/jpeg', 'image/png', 'image/webp'];

    public static function isUploaded(array $file): bool
    {
        return !empty($file['tmp_name']) && $file['error'] === UPLOAD_ERR_OK;
    }

    /**
     * @return array{valid: bool, errors: string[]}
     */
    public static function validate(array $file): array
    {
        $errors = [];

        if (empty($file['tmp_name']) || $file['error'] !== UPLOAD_ERR_OK) {
            $errors[] = 'لم يتم رفع الصورة بشكل صحيح';
            return ['valid' => false, 'errors' => $errors];
        }

        if ($file['size'] > self::MAX_SIZE_BYTES) {
            $errors[] = 'حجم الصورة يتجاوز الحد المسموح (5 ميجابايت)';
        }

        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $file['tmp_name']);
        finfo_close($finfo);

        if (!in_array($mime, self::ALLOWED_MIMES, true)) {
            $errors[] = 'صيغة الصورة غير مدعومة — يُقبل فقط JPG, PNG, WEBP';
        }

        $imageInfo = @getimagesize($file['tmp_name']);
        if ($imageInfo === false) {
            $errors[] = 'الملف ليس صورة صالحة';
        } elseif ($imageInfo[0] > self::MAX_DIMENSION || $imageInfo[1] > self::MAX_DIMENSION) {
            $errors[] = 'أبعاد الصورة كبيرة جداً (الحد الأقصى 8000×8000)';
        }

        return ['valid' => empty($errors), 'errors' => $errors];
    }

    /**
     * @return array{path: string, thumbnail_path: string}|null
     */
    public static function upload(array $file, string $category, int $entityId): ?array
    {
        $validation = self::validate($file);
        if (!$validation['valid']) {
            return null;
        }

        $uploadDir = self::getUploadDir($category);
        $thumbDir = $uploadDir . 'thumbnails/';

        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        if (!is_dir($thumbDir)) {
            mkdir($thumbDir, 0755, true);
        }

        $filename = $category . '_' . $entityId . '_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.jpg';
        $destPath = $uploadDir . $filename;
        $thumbPath = $thumbDir . $filename;

        if (!self::compress($file['tmp_name'], $destPath)) {
            return null;
        }

        self::createThumbnail($destPath, $thumbPath);

        $relativePath = 'uploads/photos/' . $category . '/' . $filename;
        $thumbRelative = 'uploads/photos/' . $category . '/thumbnails/' . $filename;

        return ['path' => $relativePath, 'thumbnail_path' => $thumbRelative];
    }

    private static function compress(string $sourcePath, string $destPath): bool
    {
        $imageInfo = @getimagesize($sourcePath);
        if ($imageInfo === false) {
            return false;
        }

        $mime = $imageInfo['mime'];
        $srcImage = match ($mime) {
            'image/jpeg' => @imagecreatefromjpeg($sourcePath),
            'image/png'  => @imagecreatefrompng($sourcePath),
            'image/webp' => @imagecreatefromwebp($sourcePath),
            default      => false,
        };

        if ($srcImage === false) {
            return false;
        }

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

        $ratio = min(
            self::OUTPUT_MAX_WIDTH / $origWidth,
            self::OUTPUT_MAX_HEIGHT / $origHeight,
            1.0
        );

        $newWidth = (int) round($origWidth * $ratio);
        $newHeight = (int) round($origHeight * $ratio);

        if ($ratio < 1.0) {
            $resized = imagecreatetruecolor($newWidth, $newHeight);
            imagecopyresampled($resized, $srcImage, 0, 0, 0, 0, $newWidth, $newHeight, $origWidth, $origHeight);
            imagedestroy($srcImage);
            $srcImage = $resized;
        }

        $result = imagejpeg($srcImage, $destPath, self::JPEG_QUALITY);
        imagedestroy($srcImage);

        return $result;
    }

    private static function createThumbnail(string $sourcePath, string $destPath): bool
    {
        $imageInfo = @getimagesize($sourcePath);
        if ($imageInfo === false) {
            return false;
        }

        $srcImage = @imagecreatefromjpeg($sourcePath);
        if ($srcImage === false) {
            return false;
        }

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

        $size = min($origWidth, $origHeight);
        $offsetX = (int) round(($origWidth - $size) / 2);
        $offsetY = (int) round(($origHeight - $size) / 2);

        $thumb = imagecreatetruecolor(self::THUMBNAIL_SIZE, self::THUMBNAIL_SIZE);
        imagecopyresampled(
            $thumb, $srcImage,
            0, 0, $offsetX, $offsetY,
            self::THUMBNAIL_SIZE, self::THUMBNAIL_SIZE, $size, $size
        );

        $result = imagejpeg($thumb, $destPath, self::JPEG_QUALITY);
        imagedestroy($srcImage);
        imagedestroy($thumb);

        return $result;
    }

    private static function getUploadDir(string $category): string
    {
        return App::getInstance()->basePath() . '/public/uploads/photos/' . $category . '/';
    }
}
