<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Fixtures\Doctrine;

use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\TokenType;

/**
 * `JSON_CONTAINS_PATH(doc, one|all, path, …)`.
 *
 * The application registers scienta/doctrine-json-functions for this; that package is
 * not a dependency of the core bundle, so the test ORM brings its own node. It emits
 * the same MySQL call, which {@see OrmHarness} backs with a SQLite user function.
 */
class JsonContainsPath extends FunctionNode
{
    /** @var list<Node> */
    private array $arguments = [];

    public function parse(Parser $parser): void
    {
        $parser->match(TokenType::T_IDENTIFIER);
        $parser->match(TokenType::T_OPEN_PARENTHESIS);

        $this->arguments[] = $parser->StringPrimary();

        while ($parser->getLexer()->isNextToken(TokenType::T_COMMA)) {
            $parser->match(TokenType::T_COMMA);
            $this->arguments[] = $parser->StringPrimary();
        }

        $parser->match(TokenType::T_CLOSE_PARENTHESIS);
    }

    public function getSql(SqlWalker $sqlWalker): string
    {
        return \sprintf('JSON_CONTAINS_PATH(%s)', implode(', ', array_map(
            static fn (Node $argument): string => $argument->dispatch($sqlWalker),
            $this->arguments,
        )));
    }
}
