<?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\Tenant;

use Ferienpass\CoreBundle\Entity\Tenant;

/**
 * What a request host serves — the answer {@see HostResolver} produces, and
 * the only thing routing, the firewall and URL generation need to know about
 * the host they are working on.
 */
final class ResolvedHost
{
    private function __construct(
        public readonly string $host,
        public readonly ?Tenant $tenant,
        public readonly bool $servesFrontend,
        public readonly bool $servesAdmin,
        /**
         * The admin is at the root of this domain, with no `/admin` segment in
         * its URLs.
         */
        public readonly bool $adminAtRoot,
        /**
         * The installation-wide console. It belongs to no tenant: the active
         * one comes from the signed-in global admin's session instead.
         */
        public readonly bool $isPlatform = false,
    ) {
    }

    /**
     * A single-tenant build: one host, both surfaces, admin under `/admin`.
     */
    public static function untenanted(string $host): self
    {
        return new self($host, null, true, true, false);
    }

    /**
     * A tenant's public site. It keeps serving the admin under `/admin` for as
     * long as the tenant has no admin domain of its own — that is the
     * behaviour every installation had before domains had a surface, and it is
     * what a municipality that wants one domain still gets.
     */
    public static function frontend(string $host, Tenant $tenant, bool $alsoServesAdmin): self
    {
        return new self($host, $tenant, true, $alsoServesAdmin, false);
    }

    /**
     * A tenant's admin domain: the admin at the root, and no public site.
     */
    public static function admin(string $host, Tenant $tenant): self
    {
        return new self($host, $tenant, false, true, true);
    }

    /**
     * The shared platform console — an admin domain without a tenant.
     */
    public static function platform(string $host): self
    {
        return new self($host, null, false, true, true, true);
    }

    public function serves(Surface $surface): bool
    {
        return match ($surface) {
            Surface::Frontend => $this->servesFrontend,
            Surface::Admin => $this->servesAdmin,
        };
    }
}
