<?php

namespace AutoAdmin\Bundle\Content\Duplicator;

use AutoAdmin\Bundle\BrickBuilder\Builder\BuilderService;
use AutoAdmin\Bundle\Content\Duplicator\Interfaces\DuplicatorInterface;
use AutoAdmin\Bundle\Content\Duplicator\Manager\DuplicatorManager;
use AutoAdmin\Bundle\Content\Duplicator\Service\StringDuplicator;
use Doctrine\ORM\EntityManagerInterface;
use ReflectionClass;
use Symfony\Contracts\Service\Attribute\Required;

abstract class AbstractDuplicator implements DuplicatorInterface
{
    protected DuplicatorManager $duplicatorManager;
    protected BuilderService $builderService;
    protected EntityManagerInterface $em;
    protected StringDuplicator $suffixes;

    #[Required]
    public function dependencies(
        DuplicatorManager $duplicatorManager,
        BuilderService $builderService,
        EntityManagerInterface $em,
        StringDuplicator $duplicateSuffixes,
    ): void {
        $this->duplicatorManager = $duplicatorManager;
        $this->builderService = $builderService;
        $this->em = $em;
        $this->suffixes = $duplicateSuffixes;
    }

    public function isSupported(object $entity): bool
    {
        $reflection = new ReflectionClass($entity);

        $interfacesDiff = array_intersect($reflection->getInterfaceNames(), $this->supportInterfaces());
        $attributeProps = $this->getPropertiesWithAttributes($entity, $this->supportAttributes());

        return !empty($interfacesDiff) || !empty($attributeProps);
    }

    public function supportInterfaces(): array
    {
        return [
            // replace with interfaces if needed
//            SequencedInterface::class
        ];
    }

    public function supportAttributes(): array
    {
        return [
            // replace with attributes if needed
//            BrickBuilder::class
        ];
    }

    protected function getPropertiesWithAttribute(mixed $entity, string $attributeClassName): array
    {
        $reflection = new ReflectionClass($entity);
        $matching = [];

        foreach ($reflection->getProperties() as $property) {
            foreach ($property->getAttributes() as $attribute) {
                if ($attribute->getName() === $attributeClassName) {
                    $matching[] = $property;
                }
            }
        }

        return $matching;
    }

    protected function getPropertiesWithAttributes(mixed $entity, array $attributes): array
    {
        $matching = [];

        foreach ($attributes as $attribute) {
            $matching = [...$matching, ...$this->getPropertiesWithAttribute($entity, $attribute)];
        }

        return $matching;
    }
}
