<?php

namespace Myvetshop\Module\Clinique\Prestashop\Hook;

use Doctrine\ORM\EntityManagerInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectCustomerUpdateBeforeInterface;
use Myvetshop\Module\Clinique\Adapter\PrestashopLoggerAdapter;
use Myvetshop\Module\Clinique\Entity\EstablishmentEvent;
use Myvetshop\Module\Clinique\Entity\Factory\EstablishmentEventFactory;
use Myvetshop\Module\Clinique\Repository\MyvetshopCliniqueRepository;

class CustomerGroupListener implements ActionObjectCustomerUpdateBeforeInterface
{
    private \Db $db;

    private EntityManagerInterface $entityManager;

    private EstablishmentEventFactory $establishmentEventFactory;

    private MyvetshopCliniqueRepository $cliniqueRepository;

    private PrestashopLoggerAdapter $prestashopLoggerAdapter;

    public function __construct(
        \Db $db,
        EntityManagerInterface $entityManager,
        EstablishmentEventFactory $establishmentEventFactory,
        MyvetshopCliniqueRepository $cliniqueRepository,
        PrestashopLoggerAdapter $prestashopLoggerAdapter
    ) {
        $this->db = $db;
        $this->entityManager = $entityManager;
        $this->establishmentEventFactory = $establishmentEventFactory;
        $this->cliniqueRepository = $cliniqueRepository;
        $this->prestashopLoggerAdapter = $prestashopLoggerAdapter;
    }

    public function actionObjectCustomerUpdateBefore(\Customer $customer): void
    {
        $oldValues = $this->db->getRow('SELECT `id_default_group` FROM `' . _DB_PREFIX_ . 'customer` c'
                . ' WHERE `c`.`id_customer` = ' . \intval($customer->id));

        if (!\is_array($oldValues)) {
            return;
        }

        if ((int) $oldValues['id_default_group'] !== (int) $customer->id_default_group) {
            // Change privilege code
            if ((int) $oldValues['id_default_group'] !== 3) {
                // Add leave event
                try {
                    $oldClinique = $this->cliniqueRepository->findByGroupId((int) $oldValues['id_default_group']);

                    if ($oldClinique && !$oldClinique->deleted) {
                        $event = $this->establishmentEventFactory->createCustomerEvent(
                            EstablishmentEvent::EVENT_CUSTOMER_LEAVE,
                            $customer
                        );
                        $event->clinique = $oldClinique;

                        $this->entityManager->persist($event);
                        $this->entityManager->flush();
                    }
                } catch (\Exception $e) {
                    // Log error
                    $this->prestashopLoggerAdapter->error(
                        $e->getMessage(),
                        [
                            'errorCode' => $e->getCode(),
                            'objectType' => 'EstablishmentEvent',
                            'stackTrace' => $e->getTraceAsString(),
                        ]
                    );
                }
            }

            if ((int) $customer->id_default_group !== 3) {
                // Add join event
                try {
                    $event = $this->establishmentEventFactory->createCustomerEvent(
                        EstablishmentEvent::EVENT_CUSTOMER_JOIN,
                        $customer
                    );

                    $this->entityManager->persist($event);
                    $this->entityManager->flush();
                } catch (\Exception $e) {
                    // Log error
                    $this->prestashopLoggerAdapter->error(
                        $e->getMessage(),
                        [
                            'errorCode' => $e->getCode(),
                            'objectType' => 'EstablishmentEvent',
                            'stackTrace' => $e->getTraceAsString(),
                        ]
                    );
                }
            }
        } else {
            $clinique = $this->cliniqueRepository->findByGroupId((int) $customer->id_default_group);

            if ($clinique) {
                // Add customer_update event
                try {
                    $event = $this->establishmentEventFactory->createCustomerEvent(
                        EstablishmentEvent::EVENT_CUSTOMER_UPDATE,
                        $customer
                    );

                    $this->entityManager->persist($event);
                    $this->entityManager->flush();
                } catch (\Exception $e) {
                    // Log error
                    $this->prestashopLoggerAdapter->error(
                        $e->getMessage(),
                        [
                            'errorCode' => $e->getCode(),
                            'objectType' => 'EstablishmentEvent',
                            'stackTrace' => $e->getTraceAsString(),
                        ]
                    );
                }
            }
        }
    }
}
