<?php

declare(strict_types=1);

namespace App\Support\Tenants;

final readonly class TenantOperabilityOutcome
{
    /**
     * @param  array<string, mixed>  $metadata
     */
    public function __construct(
        public TenantOperabilityQuestion $question,
        public bool $allowed,
        public TenantLifecycle $lifecycle,
        public TenantInteractionLane $lane,
        public ?TenantOperabilityReasonCode $reasonCode = null,
        public ?string $requiredCapability = null,
        public bool $discoverable = false,
        public ?string $informationalMessageKey = null,
        public array $metadata = [],
    ) {}

    /**
     * @param  array<string, mixed>  $metadata
     */
    public static function allow(
        TenantOperabilityQuestion $question,
        TenantLifecycle $lifecycle,
        TenantInteractionLane $lane,
        bool $discoverable = true,
        ?string $requiredCapability = null,
        ?string $informationalMessageKey = null,
        array $metadata = [],
    ): self {
        return new self(
            question: $question,
            allowed: true,
            lifecycle: $lifecycle,
            lane: $lane,
            reasonCode: null,
            requiredCapability: $requiredCapability,
            discoverable: $discoverable,
            informationalMessageKey: $informationalMessageKey,
            metadata: $metadata,
        );
    }

    /**
     * @param  array<string, mixed>  $metadata
     */
    public static function deny(
        TenantOperabilityQuestion $question,
        TenantLifecycle $lifecycle,
        TenantInteractionLane $lane,
        TenantOperabilityReasonCode $reasonCode,
        bool $discoverable = false,
        ?string $requiredCapability = null,
        ?string $informationalMessageKey = null,
        array $metadata = [],
    ): self {
        return new self(
            question: $question,
            allowed: false,
            lifecycle: $lifecycle,
            lane: $lane,
            reasonCode: $reasonCode,
            requiredCapability: $requiredCapability,
            discoverable: $discoverable,
            informationalMessageKey: $informationalMessageKey,
            metadata: $metadata,
        );
    }

    public function isDeniedForCapability(): bool
    {
        return $this->reasonCode === TenantOperabilityReasonCode::MissingCapability;
    }

    public function isDeniedForLifecycle(): bool
    {
        return in_array($this->reasonCode, [
            TenantOperabilityReasonCode::SelectorIneligibleLifecycle,
            TenantOperabilityReasonCode::TenantNotArchived,
            TenantOperabilityReasonCode::TenantAlreadyArchived,
            TenantOperabilityReasonCode::OnboardingNotResumable,
        ], true);
    }
}
