<?php

namespace Seo\EventListener;

use AutoAdmin\Bundle\Content\Context\ContentContext;
use AutoAdmin\Bundle\Content\Entity\AbstractSeoContent;
use AutoAdmin\Bundle\Content\Event\ContentMetadataEvent;
use AutoAdmin\Bundle\Content\Model\TranslationInterface;
use AutoAdmin\Bundle\Seo\EventListener\ContentMetadataEventListener;
use AutoAdmin\Bundle\Seo\Extractor\ExtractorManager;
use AutoAdmin\Bundle\Seo\Model\SeoPage;
use PHPUnit\Framework\TestCase;
use ReflectionClass;

class ContentMetadataEventListenerTest extends TestCase
{
    /**
     * @dataProvider onContentMetadataDataProvider
     */
    public function testOnContentMetadata(
        ?object $mainContent,
        ?SeoPage $getSeoPage = null,
        ?SeoPage $extract = null,
        ?SeoPage $setSeoPage = null
    )
    {
        $contentMetadataEventListener = $this->getMockBuilder(ContentMetadataEventListener::class)
            ->disableOriginalConstructor()
            ->getMock();

        $event = $this->getMockBuilder(ContentMetadataEvent::class)
            ->disableOriginalConstructor()
            ->getMock();

        $contentContext = $this->getMockBuilder(ContentContext::class)
            ->disableOriginalConstructor()
            ->getMock();

        $contentContext->expects($this->once())
            ->method('getMainContent')
            ->willReturn($mainContent);

        $contentContext->method('getSeoPage')
            ->willReturn($getSeoPage);

        $contentContext->expects($setSeoPage === null ? $this->never() : $this->once())
            ->method('setSeoPage')
            ->with($setSeoPage);

        $event->expects($this->once())
            ->method('getContentContext')
            ->willReturn($contentContext);

        $extractorManager = $this->getMockBuilder(ExtractorManager::class)
            ->disableOriginalConstructor()
            ->getMock();

        $extractorManager->method('extract')
            ->willReturn($extract);

        $reflection = new ReflectionClass(ContentMetadataEventListener::class);
        $reflection->getProperty('extractorManager')->setValue($contentMetadataEventListener, $extractorManager);

        $method = $reflection->getMethod('onContentMetadata');

        $method->invokeArgs($contentMetadataEventListener, [$event]);
    }

    private function onContentMetadataDataProvider()
    {
        $anonymousClass = new class() {};

        $original = new SeoPage();
        $original->setTitle('Original Title');
        $override = new SeoPage();
        $override->setTitle('Override Title');

        return [
            'main content is null' => [
                'mainContent' => null,
            ],
            'simple main content no SeoPage' => [
                'mainContent' => $anonymousClass,
            ],
            'simple main content' => [
                'mainContent' => $anonymousClass,
                'getSeoPage' => $original,
            ],
            'override' => [
                'mainContent' => $anonymousClass,
                'getSeoPage' => $original,
                'extract' => $override,
                'setSeoPage' => $override,
            ],
            'translatable main content null' => [
                'mainContent' => $this->createAnonymousSeoContent(),
                'getSeoPage' => $original,
                'extract' => $override,
            ],
            'translatable main content' => [
                'mainContent' => $this->createAnonymousSeoContent($this->createMock(TranslationInterface::class)),
                'getSeoPage' => $original,
                'extract' => $override,
                'setSeoPage' => $override,
            ],
        ];
    }

    private function createAnonymousSeoContent(?TranslationInterface $translation = null): AbstractSeoContent
    {
        $anonymousSeoContentClass = $this->getMockBuilder(AbstractSeoContent::class)
            ->disableOriginalConstructor()
            ->getMock();

        $anonymousSeoContentClass->method('getCurrentTranslation')
            ->willReturn($translation);

        return $anonymousSeoContentClass;
    }
}
