<?php

declare(strict_types=1);

namespace RectorLaravel\NodeFactory;

use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Expression;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\ValueObject\Type\FullyQualifiedIdentifierTypeNode;
use RectorLaravel\ValueObject\ServiceNameTypeAndVariableName;

final class AppAssignFactory
{
    /**
     * @readonly
     */
    private PhpDocInfoFactory $phpDocInfoFactory;
    public function __construct(PhpDocInfoFactory $phpDocInfoFactory)
    {
        $this->phpDocInfoFactory = $phpDocInfoFactory;
    }

    public function createAssignExpression(
        ServiceNameTypeAndVariableName $serviceNameTypeAndVariableName,
        Expr $expr
    ): Expression {
        $variable = new Variable($serviceNameTypeAndVariableName->getVariableName());
        $assign = new Assign($variable, $expr);
        $expression = new Expression($assign);

        $this->decorateWithVarAnnotation($expression, $serviceNameTypeAndVariableName);

        return $expression;
    }

    private function decorateWithVarAnnotation(
        Expression $expression,
        ServiceNameTypeAndVariableName $serviceNameTypeAndVariableName
    ): void {
        $phpDocInfo = $this->phpDocInfoFactory->createEmpty($expression);

        $fullyQualifiedIdentifierTypeNode = new FullyQualifiedIdentifierTypeNode(
            $serviceNameTypeAndVariableName->getType()
        );

        $varTagValueNode = new VarTagValueNode(
            $fullyQualifiedIdentifierTypeNode,
            '$' . $serviceNameTypeAndVariableName->getVariableName(),
            ''
        );

        $phpDocInfo->addTagValueNode($varTagValueNode);
    }
}
