<?php

namespace MintyPHP\Module\Security;

use MintyPHP\Service\Access\AuthorizationDecision;
use MintyPHP\Service\Access\AuthorizationPolicyInterface;
use MintyPHP\Service\Access\PermissionService;

/**
 * Authorization policy for the Security module.
 *
 * Maps module abilities to permission keys resolved via the core RBAC
 * PermissionService. Registered by the core AuthorizationService through the
 * module manifest's authorization_policies.
 *
 * @api Ability/permission constants are referenced from Security page actions.
 */
final class SecurityAuthorizationPolicy implements AuthorizationPolicyInterface
{
    public const ABILITY_ACCESS = 'security.access';
    public const ABILITY_CHECKS_VIEW = 'security.checks.view';
    public const ABILITY_CHECKS_CREATE = 'security.checks.create';
    public const ABILITY_CHECKS_MANAGE = 'security.checks.manage';
    public const ABILITY_TEMPLATES_MANAGE = 'security.templates.manage';
    public const ABILITY_SETTINGS_MANAGE = 'security.settings.manage';

    public const PERMISSION_ACCESS = 'security.access';
    public const PERMISSION_CHECKS_VIEW = 'security.checks.view';
    public const PERMISSION_CHECKS_CREATE = 'security.checks.create';
    public const PERMISSION_CHECKS_MANAGE = 'security.checks.manage';
    public const PERMISSION_TEMPLATES_MANAGE = 'security.templates.manage';
    public const PERMISSION_SETTINGS_MANAGE = 'security.settings.manage';

    public function __construct(
        private readonly PermissionService $permissionService
    ) {
    }

    public function supports(string $ability): bool
    {
        return in_array($ability, [
            self::ABILITY_ACCESS,
            self::ABILITY_CHECKS_VIEW,
            self::ABILITY_CHECKS_CREATE,
            self::ABILITY_CHECKS_MANAGE,
            self::ABILITY_TEMPLATES_MANAGE,
            self::ABILITY_SETTINGS_MANAGE,
        ], true);
    }

    public function authorize(string $ability, array $context = []): AuthorizationDecision
    {
        $actorUserId = (int) ($context['actor_user_id'] ?? 0);
        if ($actorUserId <= 0) {
            return AuthorizationDecision::deny(403, 'forbidden');
        }

        $permissionKey = match ($ability) {
            self::ABILITY_ACCESS => self::PERMISSION_ACCESS,
            self::ABILITY_CHECKS_VIEW => self::PERMISSION_CHECKS_VIEW,
            self::ABILITY_CHECKS_CREATE => self::PERMISSION_CHECKS_CREATE,
            self::ABILITY_CHECKS_MANAGE => self::PERMISSION_CHECKS_MANAGE,
            self::ABILITY_TEMPLATES_MANAGE => self::PERMISSION_TEMPLATES_MANAGE,
            self::ABILITY_SETTINGS_MANAGE => self::PERMISSION_SETTINGS_MANAGE,
            default => null,
        };

        if ($permissionKey === null) {
            return AuthorizationDecision::deny(403, 'forbidden');
        }

        if (!$this->permissionService->userHas($actorUserId, $permissionKey)) {
            return AuthorizationDecision::deny(403, 'forbidden');
        }

        return AuthorizationDecision::allow();
    }
}
