<?php

namespace AutoAdmin\Bundle\Tests\Functional;

use AutoAdmin\Bundle\Content\Duplicator\Service\StringDuplicator;
use AutoAdmin\Bundle\Seo\Entity\OpenGraphMetadata;
use AutoAdmin\Bundle\Seo\Entity\SchemaOrgMetadata;
use AutoAdmin\Bundle\Seo\Entity\SeoMetadata;
use AutoAdmin\Bundle\Tests\Functional\Entity\ContentEntity;
use AutoAdmin\Bundle\Tests\Functional\Entity\ContentEntityTranslation;
use AutoAdmin\Bundle\Tests\Functional\Entity\File;
use AutoAdmin\Bundle\Tests\Functional\Entity\Image;
use AutoAdmin\Bundle\Tests\Functional\Entity\Media;
use AutoAdmin\Bundle\Tests\Functional\Entity\Page;
use AutoAdmin\Bundle\Tests\Functional\Entity\SeoContentEntity;
use AutoAdmin\Bundle\Tests\Functional\Entity\SeoContentEntityTranslation;
use AutoAdmin\Bundle\Tests\Functional\Entity\SimpleEntity;
use AutoAdmin\Bundle\Tests\Functional\Entity\TranslatableEntity;
use AutoAdmin\Bundle\Tests\Functional\Entity\TranslatableEntityTranslation;
use AutoAdmin\Bundle\Tests\Functional\Entity\UntranslatedEntity;
use AutoAdmin\Bundle\Tests\Functional\Model\RegexModel;
use DateTime;


/**
 * We should test the duplication of a duplicate to make sure that @see StringDuplicator is properly behaving
 */
class DuplicationTest extends AbstractDuplicationTest
{
    private ?SimpleEntity $simpleEntity = null;
    private ?UntranslatedEntity $untranslatedEntity = null;
    private ?UntranslatedEntity $untranslatedEntityEmptySlugAdmin = null;
    private ?UntranslatedEntity $untranslatedEntityKebabSlugAdmin = null;
    private ?UntranslatedEntity $untranslatedEntitySnakeSlugAdmin = null;
    private ?TranslatableEntityTranslation $translatableEntityTranslationFR = null;
    private ?TranslatableEntity $translatableEntity = null;
    private ?ContentEntity $contentEntity = null;
    private ?SeoContentEntity $seoContentEntity = null;
    private ?Page $page = null;
    private ?Page $pageWithChild = null;
    private ?Page $pageWithChildWithChild = null;
    private ?Media $media = null;
    private ?File $file = null;
    private ?Image $image = null;

    public static function provideEntitiesForDuplication(): array
    {
        $helper = new self();
        $helper->loadEntities();

        return [
            'simple entity' => [
                'originalEntity' => $helper->simpleEntity,
                'expectedProperties' => $helper->baseExpectations([
                    'name' => $helper->simpleEntity?->getName(). ' (dup)',
                    'slug' => new RegexModel('/^test-dup-[a-f0-9]{3}$/'),
                    'publishable' => false,
                    'publishStartDate' => $helper->simpleEntity->getPublishStartDate(),
                    'publishEndDate' => $helper->simpleEntity->getPublishEndDate(),
                    'sequence' => $helper->simpleEntity->getSequence(),
                ]),
            ],
            'untranslated entity' => [
                'originalEntity' => $helper->untranslatedEntity,
                'expectedProperties' => [
                    'site' => $helper->site,
                    'slugAdmin' => new RegexModel('/^test-admin-dup-[a-f0-9]{3}$/'),
                ],
            ],
            'slug admin empty' => [
                'originalEntity' => $helper->untranslatedEntityEmptySlugAdmin,
                'expectedProperties' => [
                    'slugAdmin' => '',
                ],
            ],
            'slug admin kebab' => [
                'originalEntity' => $helper->untranslatedEntityKebabSlugAdmin,
                'expectedProperties' => [
                    'slugAdmin' => new RegexModel('/^my-admin-slug-dup-[a-zA-Z0-9]{3}$/'),
                ],
            ],
            'slug admin snake' => [
                'originalEntity' => $helper->untranslatedEntitySnakeSlugAdmin,
                'expectedProperties' => [
                    'slugAdmin' => new RegexModel('/^my_admin_slug_dup_[a-zA-Z0-9]{3}$/'),
                ],
            ],
            'translation entity' => [
                'originalEntity' => $helper->translatableEntityTranslationFR,
                'expectedProperties' => $helper->expectedTranslation($helper->localeFR),
            ],
            'translatable entity' => [
                'originalEntity' => $helper->translatableEntity,
                'expectedProperties' => $helper->baseExpectations([
                    'translations' => [
                        $helper->expectedTranslation($helper->localeFR),
                        $helper->expectedTranslation($helper->localeEN),
                    ],
                ]),
            ],
            'content entity' => [
                'originalEntity' => $helper->contentEntity,
                'expectedProperties' => $helper->baseExpectations([
                    'hiddenBreadcrumbs' => true,
                    'translations' => [
                        $helper->expectedTranslation($helper->localeFR, [
                            'name' => 'Nom (dup)',
                            'slug' => new RegexModel('/^nom-dup-[a-f0-9]{3}$/'),
                            'breadcrumbsLabel' => 'nom-fil-d-ariane',
                        ]),
                        $helper->expectedTranslation($helper->localeEN, [
                            'name' => 'Name (dup)',
                            'slug' => new RegexModel('/^name-dup-[a-f0-9]{3}$/'),
                            'breadcrumbsLabel' => 'name-breadcrumbs',
                        ]),
                    ],
                ]),
            ],
            'seo content entity' => [
                'originalEntity' => $helper->seoContentEntity,
                'expectedProperties' => $helper->baseExpectations([
                    'translations' => [
                        $helper->expectedTranslation($helper->localeFR, [
                            'seoMetadata' => [
                                'noIndex' => true,
                                'noFollow' => true,
                                'hideFromSitemap' => true,
                                'canonicalOverride' => 'https://test.fr/test',
                                'title' => 'Titre',
                                'description' => 'Description FR',
                                'metas' => ['meta1' => 'value1'],
                            ],
                            'schemaOrgMetadata' => [
                                'jsonLd' => json_encode([
                                    '@context' => 'https://schema.org',
                                    '@type' => 'WebPage',
                                    'name' => 'Test Page',
                                    'description' => 'Page de test avec schema.org metadata.',
                                    'url' => 'https://test.fr/test',
                                ]),
                                'override' => true,
                            ],
                            'openGraphMetadata' => ['image' => 'https://test.fr/test.jpg'],
                        ]),
                        $helper->expectedTranslation($helper->localeEN, [
                            'seoMetadata' => [
                                'noIndex' => true,
                                'noFollow' => true,
                                'hideFromSitemap' => true,
                                'canonicalOverride' => 'https://test.com/test',
                                'title' => 'Title',
                                'description' => 'Description EN',
                                'metas' => ['meta1' => 'value1'],
                            ],
                            'schemaOrgMetadata' => [
                                'jsonLd' => json_encode([
                                    '@context' => 'https://schema.org',
                                    '@type' => 'WebPage',
                                    'name' => 'Test Page',
                                    'description' => 'A sample page with schema.org metadata.',
                                    'url' => 'https://test.com/test',
                                ]),
                                'override' => true,
                            ],
                            'openGraphMetadata' => ['image' => 'https://test.com/test.jpg'],
                        ]),
                    ],
                ]),
            ],
            'page homepage' => [
                'originalEntity' => $helper->page,
                'expectedProperties' => $helper->baseExpectations([
                    'homepage' => false,
                    'translations' => [
                        $helper->expectedTranslation($helper->localeFR),
                        $helper->expectedTranslation($helper->localeEN),
                    ],
                ]),
            ],
            'page with child' => [
                'originalEntity' => $helper->pageWithChild,
                'expectedProperties' => $helper->baseExpectations([
                    'translations' => [
                        $helper->expectedTranslation($helper->localeFR),
                        $helper->expectedTranslation($helper->localeEN),
                    ],
                    'children' => [
                        $helper->baseExpectations([
                            'translations' => [
                                $helper->expectedTranslation($helper->localeFR),
                                $helper->expectedTranslation($helper->localeEN),
                            ],
                        ]),
                    ],
                ]),
            ],
            'page with child with child' => [
                'originalEntity' => $helper->pageWithChildWithChild,
                'expectedProperties' => $helper->baseExpectations([
                    'translations' => [
                        $helper->expectedTranslation($helper->localeFR),
                        $helper->expectedTranslation($helper->localeEN),
                    ],
                    'children' => [
                        $helper->baseExpectations([
                            'translations' => [
                                $helper->expectedTranslation($helper->localeFR),
                                $helper->expectedTranslation($helper->localeEN),
                            ],
                            'children' => [
                                $helper->baseExpectations([
                                    'translations' => [
                                        $helper->expectedTranslation($helper->localeFR),
                                        $helper->expectedTranslation($helper->localeEN),
                                    ],
                                ]),
                            ],
                        ]),
                    ],
                ]),
            ],
            'media' => [
                'originalEntity' => $helper->media,
                'expectedProperties' => $helper->baseExpectations([
                    'mediaChangedAt' => (new DateTime())->getTimestamp(),
                    'mapping' => $helper->media->getMapping(),
                    'mappingConfig' => $helper->media->getMappingConfig(),
                ]),
            ],
            'file' => [
                'originalEntity' => $helper->file,
                'expectedProperties' => $helper->baseExpectations([
                    'title' => $helper->file->getTitle(),
                    'fileName' => new RegexModel("/^[a-f0-9]{8}-{$helper->file->getFileName()}$/"),
                    'originalName' => new RegexModel("/^[a-f0-9]{8}-{$helper->file->getFileName()}$/"),
                    'mimeType' => $helper->file->getMimeType(),
                    'size' => $helper->file->getSize(),
                    'extension' => $helper->file->getExtension(),
                ]),
            ],
            'image' => [
                'originalEntity' => $helper->image,
                'expectedProperties' => $helper->baseExpectations([
                    'alt' => $helper->image->getAlt(),
                    'width' => $helper->image->getWidth(),
                    'height' => $helper->image->getHeight(),
                ]),
            ],
        ];
    }

    protected function loadEntities(): void
    {
        parent::loadEntities();

        $this->simpleEntity = new SimpleEntity();
        $this->simpleEntity->setId(123);
        $this->simpleEntity->setName('test');
        $this->simpleEntity->setSlug('test');
        $this->simpleEntity->setPublishable(true);
        $this->simpleEntity->setPublishStartDate(new DateTime('2022-01-01 00:00:00'));
        $this->simpleEntity->setPublishEndDate(new DateTime('2022-01-01 00:00:00'));
        $this->simpleEntity->setSequence(5);
        $this->simpleEntity->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->simpleEntity->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));

        $this->untranslatedEntity = new UntranslatedEntity();
        $this->untranslatedEntity->setSite($this->site);
        $this->untranslatedEntity->setSlugAdmin('test-admin');

        $this->untranslatedEntityEmptySlugAdmin = new UntranslatedEntity();
        $this->untranslatedEntityEmptySlugAdmin->setSite($this->site);

        $this->untranslatedEntityKebabSlugAdmin = new UntranslatedEntity();
        $this->untranslatedEntityKebabSlugAdmin->setSite($this->site);
        $this->untranslatedEntityKebabSlugAdmin->setSlugAdmin('my-admin-slug');

        $this->untranslatedEntitySnakeSlugAdmin = new UntranslatedEntity();
        $this->untranslatedEntitySnakeSlugAdmin->setSite($this->site);
        $this->untranslatedEntitySnakeSlugAdmin->setSlugAdmin('my_admin_slug');

        $this->translatableEntityTranslationFR = new TranslatableEntityTranslation();
        $this->translatableEntityTranslationFR->setId(123);
        $this->translatableEntityTranslationFR->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->translatableEntityTranslationFR->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->translatableEntityTranslationFR->setLocale($this->localeFR);

        $translatableEntityTranslationEN = new TranslatableEntityTranslation();
        $translatableEntityTranslationEN->setId(123);
        $translatableEntityTranslationEN->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $translatableEntityTranslationEN->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $translatableEntityTranslationEN->setLocale($this->localeEN);

        $this->translatableEntity = new TranslatableEntity();
        $this->translatableEntity->setId(123);
        $this->translatableEntity->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->translatableEntity->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->translatableEntity->addTranslation($this->translatableEntityTranslationFR);
        $this->translatableEntity->addTranslation($translatableEntityTranslationEN);

        $contentEntityTranslationFR = new ContentEntityTranslation();
        $contentEntityTranslationFR->setId(123);
        $contentEntityTranslationFR->setName('Nom');
        $contentEntityTranslationFR->setSlug('nom');
        $contentEntityTranslationFR->setBreadcrumbsLabel('nom-fil-d-ariane');
        $contentEntityTranslationFR->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $contentEntityTranslationFR->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $contentEntityTranslationFR->setLocale($this->localeFR);

        $contentEntityTranslationEN = new ContentEntityTranslation();
        $contentEntityTranslationEN->setId(123);
        $contentEntityTranslationEN->setName('Name');
        $contentEntityTranslationEN->setSlug('name');
        $contentEntityTranslationEN->setBreadcrumbsLabel('name-breadcrumbs');
        $contentEntityTranslationEN->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $contentEntityTranslationEN->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $contentEntityTranslationEN->setLocale($this->localeEN);

        $this->contentEntity = new ContentEntity();
        $this->contentEntity->setId(123);
        $this->contentEntity->setHiddenBreadcrumbs(true);
        $this->contentEntity->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->contentEntity->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->contentEntity->addTranslation($contentEntityTranslationFR);
        $this->contentEntity->addTranslation($contentEntityTranslationEN);

        $seoMetadataFR = new SeoMetadata();
        $seoMetadataFR->setNoIndex(true);
        $seoMetadataFR->setNoFollow(true);
        $seoMetadataFR->setHideFromSitemap(true);
        $seoMetadataFR->setCanonicalOverride('https://test.fr/test');
        $seoMetadataFR->setTitle('Titre');
        $seoMetadataFR->setDescription('Description FR');
        $seoMetadataFR->setMetas(['meta1' => 'value1']);

        $schemaOrgMetadataFR = new SchemaOrgMetadata();
        $schemaOrgMetadataFR->setJsonLd(json_encode([
            '@context' => 'https://schema.org',
            '@type' => 'WebPage',
            'name' => 'Test Page',
            'description' => 'Page de test avec schema.org metadata.',
            'url' => 'https://test.fr/test',
        ]));
        $schemaOrgMetadataFR->setOverride(true);

        $openGraphMetadataFR = new OpenGraphMetadata();
        $openGraphMetadataFR->setImage('https://test.fr/test.jpg');

        $seoContentEntityTranslationFR = new SeoContentEntityTranslation();
        $seoContentEntityTranslationFR->setId(123);
        $seoContentEntityTranslationFR->setSeoMetadata($seoMetadataFR);
        $seoContentEntityTranslationFR->setSchemaOrgMetadata($schemaOrgMetadataFR);
        $seoContentEntityTranslationFR->setOpenGraphMetadata($openGraphMetadataFR);
        $seoContentEntityTranslationFR->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $seoContentEntityTranslationFR->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $seoContentEntityTranslationFR->setLocale($this->localeFR);

        $seoMetadataEN = new SeoMetadata();
        $seoMetadataEN->setNoIndex(true);
        $seoMetadataEN->setNoFollow(true);
        $seoMetadataEN->setHideFromSitemap(true);
        $seoMetadataEN->setCanonicalOverride('https://test.com/test');
        $seoMetadataEN->setTitle('Title');
        $seoMetadataEN->setDescription('Description EN');
        $seoMetadataEN->setMetas(['meta1' => 'value1']);

        $schemaOrgMetadataEN = new SchemaOrgMetadata();
        $schemaOrgMetadataEN->setJsonLd(json_encode([
            '@context' => 'https://schema.org',
            '@type' => 'WebPage',
            'name' => 'Test Page',
            'description' => 'A sample page with schema.org metadata.',
            'url' => 'https://test.com/test',
        ]));
        $schemaOrgMetadataEN->setOverride(true);

        $openGraphMetadataEN = new OpenGraphMetadata();
        $openGraphMetadataEN->setImage('https://test.com/test.jpg');

        $seoContentEntityTranslationEN = new SeoContentEntityTranslation();
        $seoContentEntityTranslationEN->setId(123);
        $seoContentEntityTranslationEN->setSeoMetadata($seoMetadataEN);
        $seoContentEntityTranslationEN->setSchemaOrgMetadata($schemaOrgMetadataEN);
        $seoContentEntityTranslationEN->setOpenGraphMetadata($openGraphMetadataEN);
        $seoContentEntityTranslationEN->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $seoContentEntityTranslationEN->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $seoContentEntityTranslationEN->setLocale($this->localeEN);

        $this->seoContentEntity = new SeoContentEntity();
        $this->seoContentEntity->setId(123);
        $this->seoContentEntity->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->seoContentEntity->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->seoContentEntity->addTranslation($seoContentEntityTranslationFR);
        $this->seoContentEntity->addTranslation($seoContentEntityTranslationEN);

        $this->page = $this->createPage([$this->createPageTranslation($this->localeFR), $this->createPageTranslation($this->localeEN)]);
        $this->page->setHomepage(true);

        $this->pageWithChild = $this->createPage([$this->createPageTranslation($this->localeFR), $this->createPageTranslation($this->localeEN)]);
        $this->pageWithChild->setHomepage(true);
        $this->pageWithChild->addChild($this->page);

        $this->pageWithChildWithChild = $this->createPage([$this->createPageTranslation($this->localeFR), $this->createPageTranslation($this->localeEN)]);
        $this->pageWithChildWithChild->setHomepage(true);
        $this->pageWithChildWithChild->addChild($this->pageWithChild);

        $this->media = new Media();
        $this->media->setId(123);
        $this->media->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->media->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->media->setMediaChangedAt((new DateTime('2022-01-01 00:00:00'))->getTimestamp());
        $this->media->setMapping('test');
        $this->media->setMappingConfig(['test' => 'test']);

        $this->file = new File();
        $this->file->setId(123);
        $this->file->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->file->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->file->setMediaChangedAt($this->media->getMediaChangedAt());
        $this->file->setMapping($this->media->getMapping());
        $this->file->setMappingConfig($this->media->getMappingConfig());
        $this->file->setTitle('Title');
        $this->file->setFileName('a6e3e58d-file-name.png');
        $this->file->setOriginalName('File Name.png');
        $this->file->setMimeType('image/png');
        $this->file->setSize(123);
        $this->file->setExtension('.png');

        $this->image = new Image();
        $this->image->setId(123);
        $this->image->setCreatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->image->setUpdatedAt(new DateTime('2022-01-01 00:00:00'));
        $this->image->setMediaChangedAt($this->file->getMediaChangedAt());
        $this->image->setMapping($this->file->getMapping());
        $this->image->setMappingConfig($this->file->getMappingConfig());
        $this->image->setTitle($this->file->getTitle());
        $this->image->setFileName($this->file->getFileName());
        $this->image->setOriginalName($this->file->getOriginalName());
        $this->image->setMimeType($this->file->getMimeType());
        $this->image->setSize($this->file->getSize());
        $this->image->setExtension($this->file->getExtension());
        $this->image->setAlt('Alt');
        $this->image->setWidth(123);
        $this->image->setHeight(123);
    }
}
