<?php

/**
 * Хелпер для роботи з зображеннями
 * Обгортка над Image класом
 *
 * @package Flowaxy\Support\Helpers
 * @version 1.0.0 Alpha prerelease
 */

declare(strict_types=1);

namespace Flowaxy\Support\Helpers;

use Flowaxy\Infrastructure\Filesystem\Image;

final class ImageHelper
{
    /**
     * Створити екземпляр Image
     *
     * @param string|null $filePath
     * @return Image
     */
    public static function make(?string $filePath = null): Image
    {
        return new Image($filePath);
    }

    /**
     * Змінити розмір зображення
     *
     * @param string $filePath
     * @param int $width
     * @param int $height
     * @param bool $maintainAspectRatio
     * @return Image
     */
    public static function resize(string $filePath, int $width, int $height, bool $maintainAspectRatio = true): Image
    {
        $image = new Image($filePath);
        $image->resize($width, $height, $maintainAspectRatio);

        return $image;
    }

    /**
     * Обрізати зображення
     *
     * @param string $filePath
     * @param int $x
     * @param int $y
     * @param int $width
     * @param int $height
     * @return Image
     */
    public static function crop(string $filePath, int $x, int $y, int $width, int $height): Image
    {
        $image = new Image($filePath);
        $image->crop($x, $y, $width, $height);

        return $image;
    }

    /**
     * Повернути зображення
     *
     * @param string $filePath
     * @param int $angle
     * @return Image
     */
    public static function rotate(string $filePath, int $angle): Image
    {
        $image = new Image($filePath);
        $image->rotate($angle);

        return $image;
    }

    /**
     * Відобразити зображення дзеркально
     *
     * @param string $filePath
     * @param string $mode
     * @return Image
     */
    public static function flip(string $filePath, string $mode = 'horizontal'): Image
    {
        $image = new Image($filePath);
        $image->flip($mode);

        return $image;
    }

    /**
     * Додати водяний знак
     *
     * @param string $filePath
     * @param string $watermarkPath
     * @param string $position
     * @param int $opacity
     * @return Image
     */
    public static function watermark(string $filePath, string $watermarkPath, string $position = 'bottom-right', int $opacity = 50): Image
    {
        $image = new Image($filePath);
        $image->watermark($watermarkPath, $position, $opacity);

        return $image;
    }

    /**
     * Отримати ширину зображення
     *
     * @param string $filePath
     * @return int|false
     */
    public static function getWidth(string $filePath): int|false
    {
        $imageInfo = @getimagesize($filePath);

        return $imageInfo !== false ? $imageInfo[0] : false;
    }

    /**
     * Отримати висоту зображення
     *
     * @param string $filePath
     * @return int|false
     */
    public static function getHeight(string $filePath): int|false
    {
        $imageInfo = @getimagesize($filePath);

        return $imageInfo !== false ? $imageInfo[1] : false;
    }

    /**
     * Отримати розміри зображення
     *
     * @param string $filePath
     * @return array{width: int, height: int}|false
     */
    public static function getSize(string $filePath): array|false
    {
        $imageInfo = @getimagesize($filePath);
        if ($imageInfo === false) {
            return false;
        }

        return [
            'width' => $imageInfo[0],
            'height' => $imageInfo[1],
        ];
    }

    /**
     * Отримати MIME тип зображення
     *
     * @param string $filePath
     * @return string|false
     */
    public static function getMimeType(string $filePath): string|false
    {
        $imageInfo = @getimagesize($filePath);

        return $imageInfo !== false ? ($imageInfo['mime'] ?? false) : false;
    }

    /**
     * Зберегти зображення
     *
     * @param string $filePath
     * @param string $savePath
     * @param int $quality
     * @return bool
     */
    public static function save(string $filePath, string $savePath, int $quality = 90): bool
    {
        $image = new Image($filePath);

        return $image->save($savePath, $quality);
    }

    /**
     * Вивести зображення
     *
     * @param string $filePath
     * @param int $quality
     * @return void
     */
    public static function output(string $filePath, int $quality = 90): void
    {
        $image = new Image($filePath);
        $image->output($quality);
    }

    /**
     * Отримати base64 рядок зображення
     *
     * @param string $filePath
     * @return string|false
     */
    public static function base64(string $filePath): string|false
    {
        if (!FileHelper::exists($filePath)) {
            return false;
        }

        $imageData = FileHelper::get($filePath);
        if ($imageData === false) {
            return false;
        }

        $mimeType = self::getMimeType($filePath);
        if ($mimeType === false) {
            return false;
        }

        return 'data:' . $mimeType . ';base64,' . base64_encode($imageData);
    }

    /**
     * Створити мініатюру
     *
     * @param string $filePath
     * @param int $width
     * @param int $height
     * @param string $savePath
     * @return bool
     */
    public static function thumbnail(string $filePath, int $width, int $height, string $savePath): bool
    {
        $image = new Image($filePath);
        $image->resize($width, $height, true);

        return $image->save($savePath);
    }

    /**
     * Підігнати зображення під розміри з збереженням пропорцій
     *
     * @param string $filePath
     * @param int $width
     * @param int $height
     * @param string $savePath
     * @return bool
     */
    public static function fit(string $filePath, int $width, int $height, string $savePath): bool
    {
        $image = new Image($filePath);
        $image->resize($width, $height, true);

        return $image->save($savePath);
    }

    /**
     * Автоматично виправити орієнтацію зображення
     *
     * @param string $filePath
     * @return Image
     */
    public static function orientate(string $filePath): Image
    {
        $image = new Image($filePath);
        // EXIF орієнтація буде оброблена в класі Image, якщо підтримується

        return $image;
    }
}
