<?php

namespace Velis\Test\Image\Processor;

use PHPUnit\Framework\TestCase;
use Velis\App;
use Velis\Filesystem\FilesystemInterface;
use Velis\Image\Processor\Decorator\ConvertDecorator;
use Velis\Image\Processor\Decorator\RemoveExifDecorator;
use Velis\Image\Processor\Decorator\ResizeDecorator;
use Velis\Image\Processor\Decorator\RotateDecorator;

final class ImageProcessorTest extends TestCase
{
    private FilesystemInterface $localFilesystem;

    protected function setUp(): void
    {
        $this->localFilesystem = App::getService('filesystem.app');
    }

    public function testRotateDecorator(): void
    {
        $filename = $this->createTmpFile();
        $key = 'data/temp/' . basename($filename);

        $this->assertTrue($this->localFilesystem->has($key));

        $mimeType = $this->localFilesystem->mimeType($key);

        $this->assertEquals('image/png', $mimeType);

        $imagick  = new \Imagick();
        $imagick->readImageBlob($this->localFilesystem->read($key));

        $imageWidth = $imagick->getImageWidth();
        $imageHeight = $imagick->getImageHeight();

        $this->assertEquals(10, $imageWidth);
        $this->assertEquals(5, $imageHeight);

        $rotateDecorator = new RotateDecorator($this->localFilesystem, 90);
        $rotateDecorator->process($key);

        $imagick->readImageBlob($this->localFilesystem->read($key));
        $imageWidth = $imagick->getImageWidth();
        $imageHeight = $imagick->getImageHeight();

        $this->assertEquals(5, $imageWidth);
        $this->assertEquals(10, $imageHeight);

        unlink($key);
    }

    public function testResizeDecorator(): void
    {
        $filename = $this->createTmpFile();
        $key = 'data/temp/' . basename($filename);

        $resizeDecorator = new ResizeDecorator($this->localFilesystem, 20, 10);
        $resizeDecorator->process($key);

        $imagick  = new \Imagick();
        $imagick->readImageBlob($this->localFilesystem->read($key));
        $imageWidth = $imagick->getImageWidth();
        $imageHeight = $imagick->getImageHeight();

        $this->assertEquals(20, $imageWidth);
        $this->assertEquals(10, $imageHeight);

        unlink($key);
    }

    public function testConvertDecorator(): void
    {
        $filename = $this->createTmpFile();
        $key = 'data/temp/' . basename($filename);

        $convertDecorator = new ConvertDecorator($this->localFilesystem, ['image/png'], 'jpg');
        $convertDecorator->process($key);

        $mimeType = $this->localFilesystem->mimeType($key);

        $this->assertEquals('image/jpeg', $mimeType);

        unlink($key);
    }

    public function testRemoveExifDecorator(): void
    {
        $this->markTestSkipped('This test requires Imagick extension with HEIC to be installed.');

        $key = 'data/phpunit_test_files/sample_image_with_exif.HEIC';
        $keyTmp = $key . '.tmp';

        // Save as tmp file
        file_put_contents($keyTmp, $this->localFilesystem->read($key));

        $imagick = new \Imagick();
        $imagick->readImageBlob($this->localFilesystem->read($keyTmp));
        $exifData = $imagick->getImageProperties("exif:*");

        $this->assertNotEmpty($exifData);
        $this->assertArrayHasKey('exif:Model', $exifData);
        $this->assertEquals('iPhone 11 Pro Max', $exifData['exif:Model']);

        $removeExifDecorator = new RemoveExifDecorator($this->localFilesystem);
        $removeExifDecorator->process($keyTmp);

        $imagick = new \Imagick();
        $imagick->readImageBlob($this->localFilesystem->read($keyTmp));
        $exifData = $imagick->getImageProperties("exif:*");

        $this->assertEmpty($exifData);
        $this->assertArrayNotHasKey('exif:Model', $exifData);

        unlink($keyTmp);
    }

    private function createTmpFile(): string
    {
        // 10x5 pixels
        $imageBin = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAFCAIAAADzBuo/AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAHUlEQVQImWNgYGBgYGD4////////MdlMDHgBTaUBhtcL/UmTYD4AAAAASUVORK5CYII=');
        $tmpFile = tempnam('data/temp', 'test_image_');

        rename($tmpFile, $tmpFile . '.png');
        $tmpFile .= '.png';

        file_put_contents($tmpFile, $imageBin);

        return $tmpFile;
    }
}
