<?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\DocStoreBundle\GenericDoc\Providers;

use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
use Chill\DocStoreBundle\GenericDoc\GenericDocDTO;
use Chill\DocStoreBundle\GenericDoc\GenericDocForAccompanyingPeriodProviderInterface;
use Chill\DocStoreBundle\GenericDoc\GenericDocForPersonProviderInterface;
use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface;
use Chill\DocStoreBundle\Repository\PersonDocumentRepository;
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\Person;
use Symfony\Component\Security\Core\Security;

final readonly class PersonDocumentGenericDocProvider implements GenericDocForPersonProviderInterface, GenericDocForAccompanyingPeriodProviderInterface
{
    public const KEY = 'person_document';

    public function __construct(
        private Security $security,
        private PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository,
        private PersonDocumentRepository $personDocumentRepository,
    ) {}

    public function fetchAssociatedStoredObject(GenericDocDTO $genericDocDTO): ?StoredObject
    {
        return $this->personDocumentRepository->find($genericDocDTO->identifiers['id'])?->getObject();
    }

    public function supportsGenericDoc(GenericDocDTO $genericDocDTO): bool
    {
        return $this->supportsKeyAndIdentifiers($genericDocDTO->key, $genericDocDTO->identifiers);
    }

    public function supportsKeyAndIdentifiers(string $key, array $identifiers): bool
    {
        return self::KEY === $key && array_key_exists('id', $identifiers);
    }

    public function buildOneGenericDoc(string $key, array $identifiers): ?GenericDocDTO
    {
        if (null === $document = $this->personDocumentRepository->find($identifiers['id'])) {
            return null;
        }

        return new GenericDocDTO(
            self::KEY,
            $identifiers,
            \DateTimeImmutable::createFromInterface($document->getDate()),
            $document->getPerson()
        );
    }

    public function buildFetchQueryForPerson(
        Person $person,
        ?\DateTimeImmutable $startDate = null,
        ?\DateTimeImmutable $endDate = null,
        ?string $content = null,
        ?string $origin = null,
    ): FetchQueryInterface {
        return $this->personDocumentACLAwareRepository->buildFetchQueryForPerson(
            $person,
            $startDate,
            $endDate,
            $content
        );
    }

    public function isAllowedForPerson(Person $person): bool
    {
        return $this->security->isGranted(PersonDocumentVoter::SEE, $person);
    }

    public function buildFetchQueryForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod, ?\DateTimeImmutable $startDate = null, ?\DateTimeImmutable $endDate = null, ?string $content = null, ?string $origin = null): FetchQueryInterface
    {
        return $this->personDocumentACLAwareRepository->buildFetchQueryForAccompanyingPeriod($accompanyingPeriod, $startDate, $endDate, $content);
    }

    public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool
    {
        // we assume that the user is allowed to see at least one person of the course
        // this will be double checked when running the query
        return true;
    }
}
