<?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\Service\Signature;

use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowSignatureStateEnum;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStep;
use Chill\MainBundle\Entity\Workflow\EntityWorkflowStepSignature;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\WopiBundle\Service\WopiConverter;
use Symfony\Contracts\Translation\LocaleAwareInterface;

class PDFSignatureZoneAvailable implements LocaleAwareInterface
{
    private string $locale;

    public function __construct(
        private readonly EntityWorkflowManager $entityWorkflowManager,
        private readonly PDFSignatureZoneParser $pdfSignatureZoneParser,
        private readonly StoredObjectManagerInterface $storedObjectManager,
        private readonly WopiConverter $converter,
    ) {}

    public function setLocale(string $locale)
    {
        $this->locale = $locale;
    }

    public function getLocale()
    {
        return $this->locale;
    }

    /**
     * @return list<PDFSignatureZone>
     */
    public function getAvailableSignatureZones(EntityWorkflow $entityWorkflow): array
    {
        $storedObject = $this->entityWorkflowManager->getAssociatedStoredObject($entityWorkflow);

        if (null === $storedObject) {
            throw new \RuntimeException('No stored object found');
        }

        if ('application/pdf' !== $storedObject->getType()) {
            $content = $this->converter->convert($this->getLocale(), $this->storedObjectManager->read($storedObject), $storedObject->getType());
        } else {
            $content = $this->storedObjectManager->read($storedObject);
        }

        $zones = $this->pdfSignatureZoneParser->findSignatureZones($content);

        // free some memory as soon as possible...
        unset($content);

        $signatureZonesIndexes = array_map(
            fn (EntityWorkflowStepSignature $step) => $step->getZoneSignatureIndex(),
            $this->collectSignaturesInUse($entityWorkflow)
        );

        return array_values(array_filter($zones, fn (PDFSignatureZone $zone) => !in_array($zone->index, $signatureZonesIndexes, true)));
    }

    /**
     * @return list<EntityWorkflowStepSignature>
     */
    private function collectSignaturesInUse(EntityWorkflow $entityWorkflow): array
    {
        return array_reduce($entityWorkflow->getSteps()->toArray(), function (array $result, EntityWorkflowStep $step) {
            $current = [...$result];
            foreach ($step->getSignatures() as $signature) {
                if (EntityWorkflowSignatureStateEnum::SIGNED === $signature->getState()) {
                    $current[] = $signature;
                }
            }

            return $current;
        }, []);
    }
}
