<?php

namespace NoahVet\Reef\Infrastructure\Security\IAM\Transformer;

use NoahVet\Reef\Domain\Security\Policy\PolicyResult;
use NoahVet\Reef\Domain\Security\Policy\PolicyResultGrant;
use NoahVet\Reef\Iam\Model\GrantedPermissionShort;
use NoahVet\Reef\Iam\Model\PolicyResultPost;

class PolicyResultTransformer implements PolicyResultTransformerInterface
{
    /**
     * @return GrantedPermissionShort[]
     */
    #[\Override]
    public function resultGrantToGrantedPermissions(PolicyResultGrant $resultGrant): array
    {
        $allowed = \array_map(
            static fn (string $permission): GrantedPermissionShort => (new GrantedPermissionShort())
                    ->setResource((string) $resultGrant->getResource())
                    ->setPrincipal($resultGrant->getPrincipal())
                    ->setPermission($permission)
                    ->setGrantType(1),
            $resultGrant->getAllow(),
        );

        $denied = \array_map(
            static fn (string $permission): GrantedPermissionShort => (new GrantedPermissionShort())
                    ->setResource((string) $resultGrant->getResource())
                    ->setPrincipal($resultGrant->getPrincipal())
                    ->setPermission($permission)
                    ->setGrantType(-1),
            $resultGrant->getDeny(),
        );

        return \array_merge($allowed, $denied);
    }

    #[\Override]
    public function toApiDto(PolicyResult $policyResult): PolicyResultPost
    {
        $ret = new PolicyResultPost();

        $ret->setName($policyResult->getPolicyName());
        $ret->setSubject($policyResult->getSubject());
        $ret->setEtag($policyResult->etag ?? '');

        $grants = \array_map(
            [$this, 'resultGrantToGrantedPermissions'],
            $policyResult->getGrants(),
        );

        if (empty($grants)) {
            $ret->setGrants([]);
        } else {
            $ret->setGrants(\array_values(\array_merge(...$grants)));
        }

        return $ret;
    }
}
