<?php

namespace MintyPHP\Service\Access;

use Throwable;

class AuthorizationService
{
    /** @var array<int, AuthorizationPolicyInterface> */
    private array $policies = [];

    /**
     * @param array<int, AuthorizationPolicyInterface> $policies
     */
    public function __construct(array $policies)
    {
        foreach ($policies as $policy) {
            $this->policies[] = $policy;
        }
    }

    public function authorize(string $ability, array $context = []): AuthorizationDecision
    {
        // First matching policy wins. No match → 500 (misconfiguration, not a user error).
        foreach ($this->policies as $policy) {
            if (!$policy->supports($ability)) {
                continue;
            }

            try {
                return $policy->authorize($ability, $context);
            } catch (Throwable) {
                return AuthorizationDecision::deny(500, 'authorization_failed');
            }
        }

        return AuthorizationDecision::deny(500, 'authorization_policy_missing');
    }

    public function allow(string $ability, array $context = []): bool
    {
        return $this->authorize($ability, $context)->isAllowed();
    }
}
