<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\MessageHandler\Carrier;

use Doctrine\DBAL\Connection;
use Gls\GlsPoland\PrestaShop\Message\DeleteCarrierCommand;
use Gls\GlsPoland\PrestaShop\ObjectModel\Repository\CarrierRepository as ObjectModelRepository;

final class DeleteCarrierHandler implements DeleteCarrierHandlerInterface
{
    private $connection;
    private $objectModelRepository;
    private $dbPrefix;

    public function __construct(Connection $connection, ObjectModelRepository $objectModelRepository, string $dbPrefix)
    {
        $this->connection = $connection;
        $this->objectModelRepository = $objectModelRepository;
        $this->dbPrefix = $dbPrefix;
    }

    public function handle(DeleteCarrierCommand $command): void
    {
        if (!$this->moduleCarrierExists($command->getCarrierId())) {
            return;
        }

        $this->deleteObjectModel($command->getCarrierId());
        $this->connection->delete($this->dbPrefix . 'gls_poland_carrier', [
            'id_reference' => $command->getCarrierId(),
        ]);
    }

    private function deleteObjectModel(int $referenceId): void
    {
        $carrier = $this->objectModelRepository->findOneByReferenceId($referenceId);

        if (null === $carrier || $carrier->deleted) {
            return;
        }

        if ($carrier->isUsed()) {
            $carrier->deleted = true;
            $carrier->setFieldsToUpdate(['deleted' => true]);
            $this->objectModelRepository->update($carrier);
        } else {
            $this->objectModelRepository->remove($carrier);
        }
    }

    private function moduleCarrierExists(int $referenceId): bool
    {
        $statement = $this->connection
            ->createQueryBuilder()
            ->select('1')
            ->from($this->dbPrefix . 'gls_poland_carrier')
            ->where('id_reference = :referenceId')
            ->setParameter('referenceId', $referenceId)
            ->setMaxResults(1)
            ->execute();

        if (method_exists($statement, 'fetchOne')) {
            return false !== $statement->fetchOne();
        }

        return false !== $statement->fetchColumn();
    }
}
