<?php

namespace Tests\Unit\Framework\ImageTool;

use Openguru\OpenCartFramework\ImageTool\ImageFactory;
use Openguru\OpenCartFramework\ImageTool\ImageNotFoundException;
use Tests\TestCase;

class ImageFactoryTest extends TestCase
{
    private string $tempDir;
    private string $imageDir;
    private string $siteUrl = 'http://localhost';

    protected function setUp(): void
    {
        parent::setUp();
        // Используем путь внутри контейнера или монтируемую папку, если это необходимо.
        // Но sys_get_temp_dir() тоже должен работать внутри контейнера.
        $this->tempDir = sys_get_temp_dir() . '/oc_test_' . uniqid();
        $this->imageDir = $this->tempDir . '/images';

        if (!mkdir($this->imageDir, 0755, true) && !is_dir($this->imageDir)) {
             $this->markTestSkipped('Cannot create temp dir');
        }

        // 1x1 прозрачный пиксель
        $imageContent = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=');
        file_put_contents($this->imageDir . '/test.png', $imageContent);
        file_put_contents($this->imageDir . '/no_image.png', $imageContent);
    }

    protected function tearDown(): void
    {
        $this->recursiveRemove($this->tempDir);
        parent::tearDown();
    }

    private function recursiveRemove($dir) {
        if (is_dir($dir)) {
            $objects = scandir($dir);
            foreach ($objects as $object) {
                if ($object != "." && $object != "..") {
                    if (is_dir($dir . "/" . $object))
                        $this->recursiveRemove($dir . "/" . $object);
                    else
                        unlink($dir . "/" . $object);
                }
            }
            rmdir($dir);
        }
    }

    public function testUrlGenerationLtrimBug()
    {
        // Создаем подпапку catalog
        $subDir = $this->imageDir . '/catalog';
        mkdir($subDir, 0755, true);
        copy($this->imageDir . '/test.png', $subDir . '/test.png');

        $factory = new ImageFactory($this->imageDir, $this->siteUrl, 'gd');

        // Ожидание: http://localhost/image/cache/telecart/catalog/test_...
        $url = $factory->make('catalog/test.png')->url();

        // Проверяем, что 'cache' не пострадал от ltrim и путь содержит telecart
        $this->assertStringContainsString('/image/cache/telecart/catalog/test', $url, 'URL corrupted: ' . $url);
    }
    
    public function testFilenameLengthAndDuplication()
    {
        $factory = new ImageFactory($this->imageDir, $this->siteUrl, 'gd');
        
        $factory->make('test.png')->resize(100, 100);
        
        $url = $factory->url();
        $pathInfo = pathinfo($url);
        $filename = $pathInfo['filename'];
        
        // Теперь имя файла НЕ должно содержать явного resize_100x100, только хеш
        // $this->assertStringNotContainsString('resize_100x100', $filename);
        
        // Проверяем хеш (первые 12 символов SHA256)
        $expectedHash = substr(hash('SHA256', json_encode(['resize' => ['width' => 100, 'height' => 100]])), 0, 12);
        $this->assertStringContainsString($expectedHash, $filename);
        
        $this->assertFileExists($this->imageDir . '/cache/telecart/test_' . $expectedHash . '.webp');
    }

    public function testMissingImageFallback()
    {
         $factory = new ImageFactory($this->imageDir, $this->siteUrl, 'gd');
         
         // Запрашиваем несуществующую картинку
         $url = $factory->make('non_existent.png')->url();
         
         // Должен вернуть no_image
         // Так как путь к no_image = no_image.png, а модификаций нет, 
         // кеш файл будет no_image.webp (по умолчанию формат webp)
         $this->assertStringContainsString('no_image', $url);
         
         // Проверяем, что сам файл создался (конвертация в webp)
         $this->assertFileExists($this->imageDir . '/cache/telecart/no_image.webp');
    }
    
    public function testMissingFallbackImageSafeFail()
    {
        // Удаляем no_image.png
        unlink($this->imageDir . '/no_image.png');
        
        // Теперь ImageFactory не должен падать с Exception в конструкторе/make, 
        // но ensureFileExists вызовется.
        // Подождите, в моей реализации я добавил:
        // if (file_exists($this->fullPath)) { $this->ensureFileExists($this->fullPath); }
        // То есть если файла нет И фоллбека нет, то $path останется 'no_image.png', fullPath = .../no_image.png
        // И file_exists вернет false.
        // И ensureFileExists НЕ вызовется.
        // И вернется объект.
        
        $factory = new ImageFactory($this->imageDir, $this->siteUrl, 'gd');
        $obj = $factory->make('non_existent.png');
        
        $this->assertNotNull($obj);
        
        // Но при попытке сделать url() -> make() -> ImageManager попытается открыть файл и упадет?
        // $this->image = $this->manager->make($this->fullPath);
        // Intervention Image кинет исключение, если файла нет.
        
        $this->expectException(\Intervention\Image\Exception\NotReadableException::class);
        $obj->url();
    }
}

