<?php

/*
 * This file is part of the Serenity package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Serenity\MediaBundle\Tests\Decorator;

use League\Flysystem\FilesystemOperator;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Serenity\CoreBundle\Saas\SerenitySaasContext;
use Serenity\MediaBundle\Decorator\FilesystemDecorator;

final class FilesystemDecoratorTest extends TestCase
{
    protected function tearDown(): void
    {
        SerenitySaasContext::$identifierSerenityId = null;
    }

    public function testPublicUrlUsesTheTenantPrefix(): void
    {
        SerenitySaasContext::$identifierSerenityId = 'tenant-42';
        $filesystem = $this->filesystemMock();
        $filesystem->expects(self::once())
            ->method('publicUrl')
            ->with('/tenant-84/image.jpg', ['visibility' => 'public', 'serenitySaasId' => 'tenant-84'])
            ->willReturn('https://cdn.example/tenant-84/image.jpg');

        $decorator = new FilesystemDecorator($filesystem);

        self::assertSame(
            'https://cdn.example/tenant-84/image.jpg',
            $decorator->publicUrl('image.jpg', ['visibility' => 'public', 'serenitySaasId' => 'tenant-84']),
        );
    }

    public function testTemporaryUrlUsesTheTenantPrefix(): void
    {
        SerenitySaasContext::$identifierSerenityId = 'tenant-42';
        $expiresAt = new \DateTimeImmutable('+10 minutes');
        $filesystem = $this->filesystemMock();
        $filesystem->expects(self::once())
            ->method('temporaryUrl')
            ->with('/tenant-84/image.jpg', $expiresAt, ['download' => true, 'serenitySaasId' => 'tenant-84'])
            ->willReturn('https://cdn.example/signed-image.jpg');

        $decorator = new FilesystemDecorator($filesystem);

        self::assertSame(
            'https://cdn.example/signed-image.jpg',
            $decorator->temporaryUrl('image.jpg', $expiresAt, ['download' => true, 'serenitySaasId' => 'tenant-84']),
        );
    }

    public function testChecksumUsesTheTenantPrefix(): void
    {
        SerenitySaasContext::$identifierSerenityId = 'tenant-42';
        $filesystem = $this->filesystemMock();
        $filesystem->expects(self::once())
            ->method('checksum')
            ->with('/tenant-84/image.jpg', ['checksum_algo' => 'sha256', 'serenitySaasId' => 'tenant-84'])
            ->willReturn('checksum');

        $decorator = new FilesystemDecorator($filesystem);

        self::assertSame(
            'checksum',
            $decorator->checksum('image.jpg', ['checksum_algo' => 'sha256', 'serenitySaasId' => 'tenant-84']),
        );
    }

    private function filesystemMock(): FutureFilesystemOperator&MockObject
    {
        return $this->createMock(FutureFilesystemOperator::class);
    }
}

interface FutureFilesystemOperator extends FilesystemOperator
{
    /** @param array<string, mixed> $config */
    public function publicUrl(string $path, array $config = []): string;

    /** @param array<string, mixed> $config */
    public function temporaryUrl(string $path, \DateTimeInterface $expiresAt, array $config = []): string;

    /** @param array<string, mixed> $config */
    public function checksum(string $path, array $config = []): string;
}
