<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Tests\Comment;

use Ferienpass\CoreBundle\Comment\InboundAttachmentPolicy;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Validation;

class InboundAttachmentPolicyTest extends TestCase
{
    public function testAcceptsAPngAndReturnsTheCanonicalMime(): void
    {
        $decision = $this->policy()->validate('Ferien Foto.png', self::png());

        self::assertTrue($decision['ok']);
        self::assertSame('image/png', $decision['mime']);
        self::assertSame('png', $decision['ext']);
        // The stored name is slugged: no spaces, no second extension, no separators.
        self::assertSame('Ferien-Foto.png', $decision['name']);
    }

    public function testRejectsContentThatDoesNotMatchTheClaimedExtension(): void
    {
        // A PNG renamed to .pdf: the MIME comes from the bytes, not the name.
        $decision = $this->policy()->validate('rechnung.pdf', self::png());

        self::assertFalse($decision['ok']);
    }

    public function testRejectsAnExtensionOutsideTheNarrowedAllowList(): void
    {
        // The full allow-list has png, but a PDF-only question must not take one.
        $decision = $this->policy()->validate('foto.png', self::png(), ['pdf']);

        self::assertFalse($decision['ok']);
        self::assertStringContainsString('extension not allowed', $decision['reason']);
    }

    public function testAcceptsAnExtensionInsideTheNarrowedAllowList(): void
    {
        self::assertTrue($this->policy()->validate('foto.png', self::png(), ['png', 'jpg'])['ok']);
    }

    public function testEnforcesTheOverriddenSizeCap(): void
    {
        $decision = $this->policy()->validate('foto.png', self::png(), null, 10);

        self::assertFalse($decision['ok']);
    }

    public function testRejectsAnEmptyFile(): void
    {
        self::assertFalse($this->policy()->validate('foto.png', '')['ok']);
    }

    private function policy(): InboundAttachmentPolicy
    {
        return new InboundAttachmentPolicy(Validation::createValidator());
    }

    /**
     * The smallest valid PNG — 1×1 pixel, so libmagic reports image/png.
     */
    private static function png(): string
    {
        return base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFAAH/q842iQAAAABJRU5ErkJggg==', true);
    }
}
