<?php

namespace MintyPHP\Module\Audit;

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

final class AuditAuthorizationPolicy implements AuthorizationPolicyInterface
{
    public const ABILITY_API_AUDIT_VIEW = 'audit.api.view';
    public const ABILITY_API_AUDIT_PURGE = 'audit.api.purge';
    public const ABILITY_SYSTEM_AUDIT_VIEW = 'audit.system.view';
    public const ABILITY_SYSTEM_AUDIT_PURGE = 'audit.system.purge';
    public const ABILITY_IMPORTS_AUDIT_VIEW = 'audit.imports.view';
    public const ABILITY_IMPORTS_AUDIT_PURGE = 'audit.imports.purge';
    public const ABILITY_USER_LIFECYCLE_VIEW = 'audit.user_lifecycle.view';
    public const ABILITY_USER_LIFECYCLE_RESTORE = 'audit.user_lifecycle.restore';

    private const ABILITY_PERMISSION_MAP = [
        self::ABILITY_API_AUDIT_VIEW => 'audit.api.view',
        self::ABILITY_API_AUDIT_PURGE => 'audit.api.purge',
        self::ABILITY_SYSTEM_AUDIT_VIEW => 'audit.system.view',
        self::ABILITY_SYSTEM_AUDIT_PURGE => 'audit.system.purge',
        self::ABILITY_IMPORTS_AUDIT_VIEW => 'audit.imports.view',
        self::ABILITY_IMPORTS_AUDIT_PURGE => 'audit.imports.purge',
        self::ABILITY_USER_LIFECYCLE_VIEW => 'audit.user_lifecycle.view',
        self::ABILITY_USER_LIFECYCLE_RESTORE => 'audit.user_lifecycle.restore',
    ];

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

    public function supports(string $ability): bool
    {
        return isset(self::ABILITY_PERMISSION_MAP[$ability]);
    }

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

        $permissionKey = self::ABILITY_PERMISSION_MAP[$ability] ?? null;
        if ($permissionKey === null) {
            return AuthorizationDecision::deny(403, 'forbidden');
        }

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

        return AuthorizationDecision::allow();
    }
}
