<?php

namespace Seo\Extractor;

use AutoAdmin\Bundle\Content\Configuration\ConfigManager;
use AutoAdmin\Bundle\Content\Entity\Domain;
use AutoAdmin\Bundle\Content\Entity\Site;
use AutoAdmin\Bundle\Content\Model\LocaleInterface;
use AutoAdmin\Bundle\Content\Model\TranslatableInterface;
use AutoAdmin\Bundle\Content\Model\TranslationInterface;
use AutoAdmin\Bundle\Content\Routing\ContentRouter;
use AutoAdmin\Bundle\Content\Site\SiteContextHelper;
use AutoAdmin\Bundle\Seo\Entity\SeoMetadata;
use AutoAdmin\Bundle\Seo\Extractor\SeoContentExtractor;
use AutoAdmin\Bundle\Seo\Model\Alternate;
use AutoAdmin\Bundle\Seo\Model\Header;
use AutoAdmin\Bundle\Seo\Model\Meta;
use AutoAdmin\Bundle\Seo\Model\SeoContentTranslationInterface;
use AutoAdmin\Bundle\Seo\Model\SeoPage;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\MockObject\Rule\InvokedCount;
use PHPUnit\Framework\TestCase;
use stdClass;
use Symfony\Component\HttpFoundation\Request;

class SeoContentExtractorTest extends TestCase
{
//    /**
//     * @dataProvider supportsDataProvider
//     */
//    public function testSupports(
//        bool $isTranslatable,
//        bool $isTranslation,
//        bool $isUntranslatedContent,
//        bool $expected
//    ): void
//    {
//        $extractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->onlyMethods(['isTranslatable', 'isTranslation', 'isUntranslatedContent'])
//            ->getMock();
//
//        $extractor->method('isTranslatable')
//            ->willReturn($isTranslatable);
//
//        $extractor->method('isTranslation')
//            ->willReturn($isTranslation);
//
//        $extractor->method('isUntranslatedContent')
//            ->willReturn($isUntranslatedContent);
//
//        $this->assertEquals($expected, $extractor->supports(new stdClass()));
//    }
//
//    /**
//     * @dataProvider extractDataProvider
//     */
//    public function testExtract(
//        TranslatableInterface|SeoContentTranslationInterface|null $translatable,
//        TranslationInterface|SeoContentTranslationInterface|null $translation,
//        InvokedCount $handleTitle,
//        InvokedCount $handleDescription,
//        InvokedCount $handleMetas,
//        InvokedCount $handleCanonical,
//        InvokedCount $handleRobotsTag,
//        InvokedCount $handleAlternates
//    ): void {
//        $extractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->onlyMethods([
//                'getTranslatableTranslationObjects',
//                'handleTitle',
//                'handleDescription',
//                'handleMetas',
//                'handleCanonical',
//                'handleRobotsTag',
//                'handleAlternates',
//            ])
//            ->getMock();
//
//        $extractor->method('getTranslatableTranslationObjects')
//            ->willReturn([$translatable, $translation]);
//
//        $extractor->expects($handleTitle)
//            ->method('handleTitle');
//
//        $extractor->expects($handleDescription)
//            ->method('handleDescription');
//
//        $extractor->expects($handleMetas)
//            ->method('handleMetas');
//
//        $extractor->expects($handleCanonical)
//            ->method('handleCanonical');
//
//        $extractor->expects($handleRobotsTag)
//            ->method('handleRobotsTag');
//
//        $extractor->expects($handleAlternates)
//            ->method('handleAlternates');
//
//        $result = $extractor->extract(new Request(), new stdClass(), new SeoPage());
//
//        $this->assertInstanceOf(SeoPage::class, $result);
//    }
//
//    /**
//     * @dataProvider handleTitleDataProvider
//     */
//    public function testHandleTitle(?string $title = null): void
//    {
//        $seoContentExtractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->onlyMethods(['sanitize'])
//            ->getMock();
//
//        $seoContentExtractor->method('sanitize')
//            ->willReturn($title ?? '');
//
//        $seoMetadata = $this->getMockBuilder(SeoMetadata::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata->method('getTitle')
//            ->willReturn($title);
//
//        $seoPage = $this->getMockBuilder(SeoPage::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoPage->expects(!empty($title) ? $this->once() : $this->never())
//            ->method('setTitle')
//            ->with($title);
//
//        $reflection = new \ReflectionClass(SeoContentExtractor::class);
//
//        $method = $reflection->getMethod('handleTitle');
//
//        $method->invokeArgs($seoContentExtractor, [$seoMetadata, $seoPage]);
//    }
//
//    /**
//     * @dataProvider handleDescriptionDataProvider
//     */
//    public function testHandleDescription(?string $description = null): void
//    {
//        $seoContentExtractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->onlyMethods(['sanitize'])
//            ->getMock();
//
//        $seoContentExtractor->method('sanitize')
//            ->willReturn($description ?? '');
//
//        $seoMetadata = $this->getMockBuilder(SeoMetadata::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata->method('getDescription')
//            ->willReturn($description);
//
//        $seoPage = $this->getMockBuilder(SeoPage::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoPage->expects(!empty($title) ? $this->once() : $this->never())
//            ->method('addMeta')
//            ->willReturnCallback(function ($meta) use ($description) {
//                $this->assertInstanceOf(Meta::class, $meta);
//                $this->assertEquals('description', $meta->getName());
//                $this->assertEquals($description, $meta->getContent());
//            });
//
//        $reflection = new \ReflectionClass(SeoContentExtractor::class);
//
//        $method = $reflection->getMethod('handleTitle');
//
//        $method->invokeArgs($seoContentExtractor, [$seoMetadata, $seoPage]);
//    }
//
//    /**
//     * @dataProvider handleMetasDataProvider
//     */
//    public function testHandleMetas(?array $metas, InvokedCount $addMeta): void
//    {
//        $seoContentExtractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata = $this->getMockBuilder(SeoMetadata::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata->method('getMetas')
//            ->willReturn($metas);
//
//        $seoPage = $this->getMockBuilder(SeoPage::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $callCount = 0;
//        $seoPage->expects($addMeta)
//            ->method('addMeta')
//            ->willReturnCallback(function ($meta) use ($metas, &$callCount) {
//                $split = array_chunk($metas, 1, true);
//
//                $this->assertInstanceOf(Meta::class, $meta);
//                foreach ($split[$callCount] as $key => $value) {
//                    $this->assertEquals($key, $meta->getName());
//                    $this->assertEquals($value, $meta->getValue());
//                }
//
//                $callCount++;
//            });
//
//        $reflection = new \ReflectionClass(SeoContentExtractor::class);
//
//        $method = $reflection->getMethod('handleMetas');
//
//        $method->invokeArgs($seoContentExtractor, [$seoMetadata, $seoPage]);
//    }
//
//    /**
//     * @dataProvider handleCanonicalDataProvider
//     */
//    public function testHandleCanonical(?string $canonicalOverride, string $uri, string $expected): void
//    {
//        $seoContentExtractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata = $this->getMockBuilder(SeoMetadata::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata->method('getCanonicalOverride')
//            ->willReturn($canonicalOverride);
//
//        $seoPage = $this->getMockBuilder(SeoPage::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoPage->expects($this->once())
//            ->method('setCanonical')
//            ->with($expected);
//
//        $request = $this->getMockBuilder(Request::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $request->method('getUri')
//            ->willReturn($uri);
//
//        $reflection = new \ReflectionClass(SeoContentExtractor::class);
//
//        $method = $reflection->getMethod('handleCanonical');
//
//        $method->invokeArgs($seoContentExtractor, [$seoMetadata, $seoPage, $request]);
//    }
//
//    /**
//     * @dataProvider handleRobotsTagDataProvider
//     */
//    public function testHandleRobotsTag(bool $noIndex, bool $noFollow, ?string $expected): void
//    {
//        $seoContentExtractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata = $this->getMockBuilder(SeoMetadata::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoMetadata->method('isNoIndex')
//            ->willReturn($noIndex);
//
//        $seoMetadata->method('isNoFollow')
//            ->willReturn($noFollow);
//
//        $seoPage = $this->getMockBuilder(SeoPage::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoPage->expects($expected !== null ? $this->once() : $this->never())
//            ->method('addResponseHeader')
//            ->willReturnCallback(function ($header) use ($expected) {
//                $this->assertInstanceOf(Header::class, $header);
//                $this->assertEquals('X-Robots-Tag', $header->getName());
//                $this->assertEquals($expected, $header->getValue());
//            });
//
//        $reflection = new \ReflectionClass(SeoContentExtractor::class);
//
//        $method = $reflection->getMethod('handleRobotsTag');
//
//        $method->invokeArgs($seoContentExtractor, [$seoMetadata, $seoPage]);
//    }
//
//    /**
//     * @dataProvider handleAlternatesDataProvider
//     */
//    public function testHandleAlternates(
//        string $route,
//        ?string $action,
//        Collection $translations,
//        ?string $siteLocaleForCode,
//        ?Site $site,
//        ?Domain $domain,
//        ?string $generatedUrl,
//        ?string $exception,
//        array $expected
//    ): void {
//        if ($exception !== null) {
//            $this->expectExceptionMessage($exception);
//        }
//
//        $seoContentExtractor = $this->getMockBuilder(SeoContentExtractor::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $translatable = $this->getMockBuilder(TranslatableInterface::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $translatable->method('getTranslations')
//            ->willReturn($translations);
//
//        $translatable->method('getSite')
//            ->willReturn($site);
//
//        $seoPage = $this->getMockBuilder(SeoPage::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoPage->expects($exception === null ? $this->once() : $this->never())
//            ->method('setAlternates')
//            ->willReturnCallback(function ($alternates) use ($expected) {
//                if ($expected === []) {
//                    $this->assertEmpty($alternates);
//
//                    return;
//                } else {
//                    $index = 0;
//                    foreach ($expected as $locale => $url) {
//                        $this->assertInstanceOf(Alternate::class, $alternates[$index]);
//                        $this->assertEquals($locale, $alternates[$index]->getHrefLang()->getCode());
//                        $this->assertEquals($url, $alternates[$index]->getHref());
//                        $index++;
//                    }
//                }
//            });
//
//        $request = $this->getMockBuilder(Request::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $request->method('get')
//            ->with('_route')
//            ->willReturn($route);
//
//        $configManager = $this->getMockBuilder(ConfigManager::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $configManager->method('getRouteAction')
//            ->with($route)
//            ->willReturn($action);
//
//        $siteContextHelper = $this->getMockBuilder(SiteContextHelper::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $siteContextHelper->method('getDomainByLocale')
//            ->with($site, $this->isInstanceOf(LocaleInterface::class))
//            ->willReturn($domain);
//
//        if ($siteLocaleForCode !== null) {
//            $locale = $this->getMockBuilder(LocaleInterface::class)
//                ->disableOriginalConstructor()
//                ->getMock();
//
//            $locale->method('getCode')
//                ->willReturn($siteLocaleForCode);
//
//            $siteContextHelper->method('getSiteLocaleForCode')
//                ->with($siteLocaleForCode)
//                ->willReturn($locale);
//        }
//
//        $contentRouter = $this->getMockBuilder(ContentRouter::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $contentRouter->method('generate')
//            ->willReturn($generatedUrl);
//
//        $reflection = new \ReflectionClass(SeoContentExtractor::class);
//        $reflection->getProperty('config')
//            ->setValue($seoContentExtractor, $configManager);
//        $reflection->getProperty('contextHelper')
//            ->setValue($seoContentExtractor, $siteContextHelper);
//        $reflection->getProperty('contentRouter')
//            ->setValue($seoContentExtractor, $contentRouter);
//
//        $method = $reflection->getMethod('handleAlternates');
//
//        $method->invokeArgs($seoContentExtractor, [$translatable, $seoPage, $request]);
//    }
//
//    private function supportsDataProvider(): array
//    {
//        return [
//            'is translatable' => [
//                true,
//                false,
//                false,
//                true,
//            ],
//            'is translation' => [
//                false,
//                true,
//                false,
//                true,
//            ],
//            'is untranslated content' => [
//                false,
//                false,
//                true,
//                true,
//            ],
//            'is not translatable content' => [
//                false,
//                true,
//                true,
//                true,
//            ],
//            'is not translation content' => [
//                true,
//                false,
//                true,
//                true,
//            ],
//            'is not untranslated content' => [
//                true,
//                true,
//                false,
//                true,
//            ],
//            'is all content' => [
//                true,
//                true,
//                true,
//                true,
//            ],
//            'is not content' => [
//                false,
//                false,
//                false,
//                false,
//            ],
//        ];
//    }
//
//    private function extractDataProvider(): array
//    {
//        return [
//            'translatable/translation' => [
//                'translatable' => $this->createMock(TranslatableInterface::class),
//                'translation' => $this->createMock(TranslationInterface::class),
//                'handleTitle' => $this->never(),
//                'handleDescription' => $this->never(),
//                'handleMetas' => $this->never(),
//                'handleCanonical' => $this->never(),
//                'handleRobotsTag' => $this->never(),
//                'handleAlternates' => $this->once(),
//            ],
//            'untranslated content no SeoMetadata' => [
//                'translatable' => $this->createSeoContentTranslation(),
//                'translation' => $this->createSeoContentTranslation(),
//                'handleTitle' => $this->never(),
//                'handleDescription' => $this->never(),
//                'handleMetas' => $this->never(),
//                'handleCanonical' => $this->never(),
//                'handleRobotsTag' => $this->never(),
//                'handleAlternates' => $this->never(),
//            ],
//            'untranslated content' => [
//                'translatable' => $this->createSeoContentTranslation($this->createMock(SeoMetadata::class)),
//                'translation' => $this->createSeoContentTranslation($this->createMock(SeoMetadata::class)),
//                'handleTitle' => $this->once(),
//                'handleDescription' => $this->once(),
//                'handleMetas' => $this->once(),
//                'handleCanonical' => $this->once(),
//                'handleRobotsTag' => $this->once(),
//                'handleAlternates' => $this->never(),
//            ],
//        ];
//    }
//
//    private function createSeoContentTranslation(?MockObject $seoMetadata = null): MockObject
//    {
//        $seoContentTranslation = $this->getMockBuilder(SeoContentTranslationInterface::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $seoContentTranslation->method('getSeoMetadata')
//            ->willReturn($seoMetadata);
//
//        return $seoContentTranslation;
//    }
//
//    private function handleTitleDataProvider(): array
//    {
//        return [
//            'null title' => [
//                'title' => null,
//            ],
//            'empty title' => [
//                'title' => '',
//            ],
//            'title' => [
//                'title' => 'title',
//            ],
//        ];
//    }
//
//    private function handleDescriptionDataProvider(): array
//    {
//        return [
//            'null description' => [
//                'description' => null,
//            ],
//            'empty description' => [
//                'description' => '',
//            ],
//            'description' => [
//                'description' => 'description',
//            ],
//        ];
//    }
//
//    private function handleMetasDataProvider(): array
//    {
//        return [
//            'null metas' => [
//                'metas' => null,
//                'addMeta' => $this->never(),
//            ],
//            'empty metas' => [
//                'metas' => [],
//                'addMeta' => $this->never(),
//            ],
//            'metas' => [
//                'metas' => ['meta' => 'value'],
//                'addMeta' => $this->once(),
//            ],
//            'multiple metas' => [
//                'metas' => [
//                    'meta1' => 'value1',
//                    'meta2' => 'value2',
//                ],
//                'addMeta' => $this->exactly(2),
//            ],
//        ];
//    }
//
//    private function handleCanonicalDataProvider(): array
//    {
//        return [
//            'canonical override' => [
//                'canonicalOverride' => 'override',
//                'uri' => 'uri',
//                'expected' => 'override',
//            ],
//            'no canonical override' => [
//                'canonicalOverride' => null,
//                'uri' => 'uri',
//                'expected' => 'uri',
//            ],
//            'uri with ?' => [
//                'canonicalOverride' => null,
//                'uri' => 'uri?query',
//                'expected' => 'uri',
//            ],
//        ];
//    }
//
//    private function handleRobotsTagDataProvider(): array
//    {
//        return [
//            'no index' => [
//                'noIndex' => true,
//                'noFollow' => false,
//                'expected' => 'noindex',
//            ],
//            'no follow' => [
//                'noIndex' => false,
//                'noFollow' => true,
//                'expected' => 'nofollow',
//            ],
//            'no index and no follow' => [
//                'noIndex' => true,
//                'noFollow' => true,
//                'expected' => 'noindex, nofollow',
//            ],
//            'index and follow' => [
//                'noIndex' => false,
//                'noFollow' => false,
//                'expected' => null,
//            ],
//        ];
//    }
//
//    private function handleAlternatesDataProvider(): array
//    {
//        return [
//            'not Page, no translations' => [
//                'route' => 'route',
//                'action' => null,
//                'translations' => new ArrayCollection(),
//                'siteLocaleForCode' => null,
//                'site' => null,
//                'domaine' => null,
//                'generatedUrl' => null,
//                'exception' => null,
//                'expected' => [],
//            ],
//            'not Page, translations but no Locale' => [
//                'route' => 'route',
//                'action' => null,
//                'translations' => new ArrayCollection([
//                    $this->createTranslation(),
//                ]),
//                'siteLocaleForCode' => null,
//                'site' => null,
//                'domaine' => null,
//                'generatedUrl' => null,
//                'exception' => "Locale is required for translatable content",
//                'expected' => [],
//            ],
//            'not Page, translations but no Site' => [
//                'route' => 'route',
//                'action' => null,
//                'translations' => new ArrayCollection([
//                    $this->createTranslation('fr'),
//                ]),
//                'siteLocaleForCode' => null,
//                'site' => null,
//                'domaine' => null,
//                'generatedUrl' => null,
//                'exception' => "Site is required for translatable content",
//                'expected' => [],
//            ],
//            'not Page, translations but no Domaine' => [
//                'route' => 'route',
//                'action' => null,
//                'translations' => new ArrayCollection([
//                    $this->createTranslation('fr'),
//                ]),
//                'siteLocaleForCode' => null,
//                'site' => $this->createMock(Site::class),
//                'domaine' => null,
//                'generatedUrl' => null,
//                'exception' => "Domain is required for translatable content",
//                'expected' => [],
//            ],
//            'Page' => [
//                'route' => 'route',
//                'action' => null,
//                'translations' => new ArrayCollection([
//                    $this->createTranslation('fr'),
//                ]),
//                'siteLocaleForCode' => null,
//                'site' => $this->createMock(Site::class),
//                'domaine' => $this->createDomaine('domain'),
//                'generatedUrl' => '/generated/url',
//                'exception' => null,
//                'expected' => [
//                    'fr' => '/generated/url',
//                ],
//            ],
//            'Page translated route' => [
//                'route' => 'route.en',
//                'action' => null,
//                'translations' => new ArrayCollection([
//                    $this->createTranslation('fr'),
//                ]),
//                'siteLocaleForCode' => 'en',
//                'site' => $this->createMock(Site::class),
//                'domaine' => $this->createDomaine('domain'),
//                'generatedUrl' => '/generated/url',
//                'exception' => null,
//                'expected' => [
//                    'en' => '/generated/url',
//                ],
//            ],
//        ];
//    }
//
//    private function createTranslation(?string $code = null): MockObject
//    {
//        $translation = $this->getMockBuilder(TranslationInterface::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        if ($code !== null) {
//            $locale = $this->getMockBuilder(LocaleInterface::class)
//                ->disableOriginalConstructor()
//                ->getMock();
//
//            $locale->method('getCode')
//                ->willReturn($code);
//
//            $translation->method('getLocale')
//                ->willReturn($locale);
//        }
//
//        return $translation;
//    }
//
//    private function createDomaine(string $domain): MockObject
//    {
//        $domaine = $this->getMockBuilder(Domain::class)
//            ->disableOriginalConstructor()
//            ->getMock();
//
//        $domaine->method('getDomain')
//            ->willReturn($domain);
//
//        return $domaine;
//    }
}
