<?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\CmsBundle\EventListener;

use Contao\CoreBundle\Event\RobotsTxtEvent;
use Ferienpass\CmsBundle\Filter\OfferListFilter;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use webignition\RobotsTxt\Directive\Directive;

/**
 * Keeps the offer list's filter permutations out of robots.txt-abiding crawlers.
 *
 * The filtered list is a combinatorial duplicate of one page — categories ×
 * ages × price × date presets — and JS-executing crawlers (Baiduspider-render,
 * Applebot) walk the whole space, each hit a full uncacheable list render. The
 * `noindex` those pages carry only stops indexing; this stops the fetch.
 *
 * Contributed to Contao's *dynamic* robots.txt (built per root page from
 * `tl_page.robotsTxt`) rather than shipped as `public/robots.txt`: a static file
 * would be served by the web server and shadow that route entirely, taking every
 * tenant's own directives and the generated `Sitemap:` line with it.
 *
 * Emitted as `/*?*param=` so the pattern matches whatever position the param
 * lands in — the UI does not fix the query order. Wildcards are an extension to
 * the original robots.txt spec, but every crawler that matters here (Google,
 * Bing, Baidu, Yandex, Applebot) supports them.
 */
final class OfferListRobotsTxtListener
{
    public function __construct(private readonly OfferListFilter $filter)
    {
    }

    /**
     * Negative priority so this runs after Contao's own RobotsTxtListener, which
     * is what guarantees a `user-agent: *` record exists to append to when the
     * root page defines none itself.
     */
    #[AsEventListener(priority: -100)]
    public function __invoke(RobotsTxtEvent $event): void
    {
        foreach ($event->getFile()->getRecords() as $record) {
            $directiveList = $record->getDirectiveList();

            foreach ($this->filter->getQueryParamNames() as $param) {
                $directiveList->add(new Directive('Disallow', '/*?*'.$param.'='));
            }
        }
    }
}
