<?php

declare(strict_types=1);

namespace App\Support\Baselines;

use App\Models\ManagedEnvironment;
use App\Support\Ui\DerivedState\DerivedStateFamily;
use App\Support\Ui\DerivedState\DerivedStateKey;
use App\Support\Ui\DerivedState\RequestScopedDerivedStateStore;

final class TenantGovernanceAggregateResolver
{
    public const string VARIANT_TENANT_GOVERNANCE_SUMMARY = 'tenant_governance_summary';

    public function __construct(
        private readonly RequestScopedDerivedStateStore $derivedStateStore,
    ) {}

    public function forTenant(?ManagedEnvironment $tenant, bool $fresh = false): ?TenantGovernanceAggregate
    {
        if (! $tenant instanceof ManagedEnvironment) {
            return null;
        }

        return $this->resolveAggregate(
            tenant: $tenant,
            resolver: fn (): TenantGovernanceAggregate => BaselineCompareStats::forTenant($tenant)
                ->toTenantGovernanceAggregate($tenant),
            fresh: $fresh,
        );
    }

    public function fromStats(?ManagedEnvironment $tenant, BaselineCompareStats $stats, bool $fresh = false): ?TenantGovernanceAggregate
    {
        if (! $tenant instanceof ManagedEnvironment) {
            return null;
        }

        return $this->resolveAggregate(
            tenant: $tenant,
            resolver: fn (): TenantGovernanceAggregate => $stats->toTenantGovernanceAggregate($tenant),
            fresh: $fresh,
        );
    }

    private function resolveAggregate(ManagedEnvironment $tenant, callable $resolver, bool $fresh = false): TenantGovernanceAggregate
    {
        $key = DerivedStateKey::fromModel(
            DerivedStateFamily::TenantGovernanceAggregate,
            $tenant,
            self::VARIANT_TENANT_GOVERNANCE_SUMMARY,
        );

        $value = $fresh
            ? $this->derivedStateStore->resolveFresh(
                $key,
                $resolver,
                DerivedStateFamily::TenantGovernanceAggregate->defaultFreshnessPolicy(),
                DerivedStateFamily::TenantGovernanceAggregate->allowsNegativeResultCache(),
            )
            : $this->derivedStateStore->resolve(
                $key,
                $resolver,
                DerivedStateFamily::TenantGovernanceAggregate->defaultFreshnessPolicy(),
                DerivedStateFamily::TenantGovernanceAggregate->allowsNegativeResultCache(),
            );

        return $value;
    }
}
