<?php

namespace Webapp\Core\ApiOperation;

use ApiPlatform\Core\Api\IriConverterInterface;
use DateTime;
use Doctrine\Common\Proxy\Proxy;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Security;
use Webapp\Core\Entity\BusinessObject;
use Webapp\Core\Entity\Experiment;
use Webapp\Core\Entity\Individual;
use Webapp\Core\Entity\Move\Delete;
use Webapp\Core\Entity\Platform;
use Webapp\Core\Entity\SurfacicUnitPlot;
use Webapp\Core\Enumeration\PathLevelEnum;

/**
 * Class DeleteBusinessObjectOperation.
 */
final class DeleteBusinessObjectOperation extends MultipleBusinessObjectAbstractOperation
{
    public function __construct(Security $security, IriConverterInterface $iriConverter, EntityManagerInterface $entityManager)
    {
        parent::__construct($security, $iriConverter, $entityManager);
    }

    /**
     * @param Request $request
     * @param Delete $data
     * @return mixed
     */
    public function __invoke(Request $request, $data)
    {
        /** @var Platform | Experiment $parent common parent to do security checks */
        $parent = null;
        /** @var array<SurfacicUnitPlot | Individual> $objectToDelete iri => leaf object */
        $objectToDelete = $this->getObjectLeafs($data->getObjectIris(), $parent);
        if ($parent instanceof Proxy) {
            // Needed to trigger right exception because platform didn't load
            $parent->__load();
        }
        $deletedIris = [];
        // TODO Faire les tests de sécurité sur le parent
        foreach ([
                     PathLevelEnum::OEZ,
                     PathLevelEnum::INDIVIDUAL,
                     PathLevelEnum::SURFACIC_UNIT_PLOT,
                     PathLevelEnum::UNIT_PLOT,
                     PathLevelEnum::SUB_BLOCK,
                     PathLevelEnum::BLOCK,
                     PathLevelEnum::EXPERIMENT,
                     PathLevelEnum::PLATFORM,
                 ] as $level) {
            if (isset($data->getObjectIris()[$level])) {
                foreach ($data->getObjectIris()[$level] as $itemIri) {
                    $this->deleteItem($this->iriConverter->getItemFromIri($itemIri), $deletedIris);
                }
            }
        }

        $this->entityManager->flush();
        $data->setId(0)->setObjectIris($deletedIris);

        return $data;
    }

    private function deleteItem(BusinessObject $item, array &$deletedIris)
    {
        $itemIri = $this->iriConverter->getIriFromItem($item);
        $item->setGraphicallyDeletedAt(new DateTime());
        $deletedIris[] = $itemIri;
        // if every parent's children are in the deletedIri array
        if ($item->parent() !== null && array_reduce($item->parent()->children(), function ($acc, $item) use ($deletedIris) {
                return $acc && in_array($this->iriConverter->getIriFromItem($item), $deletedIris, true);
            }, true)) {
            $this->deleteItem($item->parent(), $deletedIris);
        }
    }

}
