<?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\Security\UserChecker;

use Ferienpass\CoreBundle\Entity\User;
use Ferienpass\CoreBundle\Tenant\SurfaceContext;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * Keeps the platform console to the people who run the installation.
 *
 * That domain belongs to no tenant, so the account behind an e-mail address
 * has to be looked up across all of them — the one place in the application
 * where that happens. Whoever signs in there therefore has to be someone the
 * whole installation is theirs to administer; everybody else signs in on their
 * own municipality's admin domain, inside their own tenant.
 *
 * Since an e-mail address is only unique *within* a tenant, the same address
 * may exist in two municipalities. The cross-tenant lookup then finds an
 * arbitrary one of them — which is exactly why this refuses anything but a
 * global admin, and why a global admin's address should be unique across the
 * installation.
 */
class PlatformConsoleUserChecker implements UserCheckerInterface
{
    public function __construct(private readonly SurfaceContext $surfaces)
    {
    }

    public function checkPreAuth(UserInterface $user, ?TokenInterface $token = null): void
    {
    }

    public function checkPostAuth(UserInterface $user, ?TokenInterface $token = null): void
    {
        if (!($this->surfaces->current()?->isPlatform ?? false) || !$user instanceof User) {
            return;
        }

        if ($user->isGlobalAdmin()) {
            return;
        }

        $ex = new CustomUserMessageAccountStatusException('Dieses Konto gehört zu einem einzelnen Ferienpass. Bitte melden Sie sich unter der Adresse Ihrer Kommune an.');
        $ex->setUser($user);

        throw $ex;
    }
}
