<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\WopiBundle\Service\Wopi;

use ChampsLibres\WopiLib\Contract\Entity\Document;
use Chill\DocStoreBundle\Repository\StoredObjectRepository;
use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
use Chill\MainBundle\Entity\User;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Psr\Http\Message\RequestInterface;
use Symfony\Component\Security\Core\Security;

class AuthorizationManager implements \ChampsLibres\WopiBundle\Contracts\AuthorizationManagerInterface
{
    public function __construct(private readonly JWTTokenManagerInterface $tokenManager, private readonly Security $security, private readonly StoredObjectRepository $storedObjectRepository) {}

    public function isRestrictedWebViewOnly(string $accessToken, Document $document, RequestInterface $request): bool
    {
        return false;
    }

    public function getRelatedStoredObject(Document $document)
    {
        return $this->storedObjectRepository->findOneBy(['uuid' => $document->getWopiDocId()]);
    }

    public function isTokenValid(string $accessToken, Document $document, RequestInterface $request): bool
    {
        $metadata = $this->tokenManager->parse($accessToken);

        if (false === $metadata) {
            return false;
        }

        $user = $this->security->getUser();

        if (!($user instanceof User || $this->security->isGranted('ROLE_ADMIN'))) {
            return false;
        }

        return $document->getWopiDocId() === $metadata['fileId'];
    }

    public function userCanAttend(string $accessToken, Document $document, RequestInterface $request): bool
    {
        return $this->isTokenValid($accessToken, $document, $request);
    }

    public function userCanDelete(string $accessToken, Document $document, RequestInterface $request): bool
    {
        return false;
    }

    public function userCannotWriteRelative(string $accessToken, Document $document, RequestInterface $request): bool
    {
        return true;
    }

    public function userCanPresent(string $accessToken, Document $document, RequestInterface $request): bool
    {
        $storedObject = $this->getRelatedStoredObject($document);
        if ($this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
            return $this->isTokenValid($accessToken, $document, $request);
        }

        return false;
    }

    public function userCanRead(string $accessToken, Document $document, RequestInterface $request): bool
    {
        $storedObject = $this->getRelatedStoredObject($document);

        if ($this->security->isGranted(StoredObjectRoleEnum::SEE->value, $storedObject)) {
            return $this->isTokenValid($accessToken, $document, $request);
        }

        return false;
    }

    public function userCanRename(string $accessToken, Document $document, RequestInterface $request): bool
    {
        return false;
    }

    public function userCanWrite(string $accessToken, Document $document, RequestInterface $request): bool
    {
        $storedObject = $this->getRelatedStoredObject($document);

        if ($this->security->isGranted(StoredObjectRoleEnum::EDIT->value, $storedObject)) {
            return $this->isTokenValid($accessToken, $document, $request);
        }

        return false;
    }
}
