<?php

declare(strict_types=1);

namespace Gls\GlsPoland\EventListener;

use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\EntityManagerInterface;
use Gls\GlsPoland\AdePlus\Consignment\Consignment as AdeConsignment;
use Gls\GlsPoland\AdePlus\ConsignmentsApiClientInterface;
use Gls\GlsPoland\Entity\Parcel;
use Gls\GlsPoland\MessageHandler\Labels\LabelsEvent;
use Gls\GlsPoland\MessageHandler\Pickup\PickupCreatedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

final class UpdateParcelNumbersListener implements EventSubscriberInterface
{
    private $entityManager;
    private $prepBoxClient;
    private $pickupsClient;

    public function __construct(EntityManagerInterface $entityManager, ConsignmentsApiClientInterface $prepBoxClient, ConsignmentsApiClientInterface $pickupsClient)
    {
        $this->entityManager = $entityManager;
        $this->prepBoxClient = $prepBoxClient;
        $this->pickupsClient = $pickupsClient;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            LabelsEvent::PREP_BOX_DOWNLOADED => 'onLabelDownloaded',
            PickupCreatedEvent::class => ['onPickupCreated', 10],
        ];
    }

    public function onLabelDownloaded(LabelsEvent $event): void
    {
        $consignment = $event->getConsignment();

        if ($consignment->hasParcelNumbers()) {
            return;
        }

        $this->setParcelNumbers(
            $this->prepBoxClient->getConsignment($consignment->getPreparingBoxId()),
            $consignment->getParcels()
        );

        $this->entityManager->flush();
    }

    public function onPickupCreated(PickupCreatedEvent $event): void
    {
        foreach ($event->getConsignments() as $consignment) {
            if ($consignment->hasParcelNumbers()) {
                return;
            }

            $this->setParcelNumbers(
                $this->pickupsClient->getConsignment($consignment->getAdeConsignmentId()),
                $consignment->getParcels()
            );
        }

        $this->entityManager->flush();
    }

    /**
     * @param Collection<int, Parcel> $parcels
     */
    private function setParcelNumbers(AdeConsignment $consignment, Collection $parcels): void
    {
        foreach ($consignment->getParcels() as $key => $adeParcel) {
            if ($parcel = $parcels->get($key)) {
                $parcel->setNumber($adeParcel->getNumber());
            }
        }
    }
}
