<?php

declare (strict_types=1);
namespace Rector\Doctrine\Orm214\Rector\Param;

use PhpParser\Node;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ObjectType;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
 * @see https://github.com/doctrine/orm/pull/10086
 * @see \Rector\Doctrine\Tests\Orm214\Rector\Param\ReplaceLifecycleEventArgsByDedicatedEventArgsRector\ReplaceLifecycleEventArgsByDedicatedEventArgsRectorTest
 */
final class ReplaceLifecycleEventArgsByDedicatedEventArgsRector extends AbstractRector
{
    /**
     * @var array<string, class-string>
     */
    private const EVENT_CLASSES = ['prePersist' => 'Doctrine\ORM\Event\PrePersistEventArgs', 'preUpdate' => 'Doctrine\ORM\Event\PreUpdateEventArgs', 'preRemove' => 'Doctrine\ORM\Event\PreRemoveEventArgs', 'postPersist' => 'Doctrine\ORM\Event\PostPersistEventArgs', 'postUpdate' => 'Doctrine\ORM\Event\PostUpdateEventArgs', 'postRemove' => 'Doctrine\ORM\Event\PostRemoveEventArgs', 'postLoad' => 'Doctrine\ORM\Event\PostLoadEventArgs'];
    public function getRuleDefinition(): RuleDefinition
    {
        return new RuleDefinition('Replace Doctrine\ORM\Event\LifecycleEventArgs with specific event classes based on the function call', [new CodeSample(<<<'CODE_SAMPLE'
use Doctrine\ORM\Event\LifecycleEventArgs;

class PrePersistExample
{
    public function prePersist(LifecycleEventArgs $args)
    {
        // ...
    }
}

CODE_SAMPLE
, <<<'CODE_SAMPLE'
use Doctrine\ORM\Event\PrePersistEventArgs;

class PrePersistExample
{
    public function prePersist(PrePersistEventArgs $args)
    {
        // ...
    }
}
CODE_SAMPLE
)]);
    }
    /**
     * @return array<class-string<ClassMethod>>
     */
    public function getNodeTypes(): array
    {
        return [ClassMethod::class];
    }
    /**
     * @param ClassMethod $node
     */
    public function refactor(Node $node): ?Node
    {
        if ($node->params === []) {
            return null;
        }
        $hasChanged = \false;
        foreach ($node->params as $param) {
            if (!$this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\LifecycleEventArgs'))) {
                continue;
            }
            if ($this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\PrePersistEventArgs')) || $this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\PreUpdateEventArgs')) || $this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\PreRemoveEventArgs')) || $this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\PostPersistEventArgs')) || $this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\PostUpdateEventArgs')) || $this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\PostRemoveEventArgs')) || $this->isObjectType($param, new ObjectType('Doctrine\ORM\Event\PostLoadEventArgs'))) {
                continue;
            }
            $eventClass = self::EVENT_CLASSES[$node->name->name] ?? null;
            if ($eventClass === null) {
                continue;
            }
            $param->type = new FullyQualified($eventClass);
            $hasChanged = \true;
        }
        if ($hasChanged) {
            return $node;
        }
        return null;
    }
}
