<?php
namespace App\EventListener;
use App\Entity\Customer\Customer;
use App\Entity\Vignette\Availability;
use App\Entity\Vignette\Category;
use App\Entity\Vignette\Price;
use App\Entity\Vignette\VignetteApi;
use App\Events\VignetteEvent;
use App\Manager\Partner\PartnerManager;
use App\Manager\Vignette\CategoryManager;
use App\Model\Vignette\ValidityModel;
use App\Service\Customer\VehicleService;
use App\Service\CustomerService;
use App\Service\SystemService;
use App\Service\VignetteApiService;
use App\Service\VignetteOrderService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class VignetteListener
{
protected $listener;
protected $entityManager;
protected $container;
protected $event;
protected $request;
public function __construct(VignetteEvent $listener, EntityManagerInterface $entityManager
, ContainerInterface $container, RequestStack $requestStack)
{
$this->listener = $listener;
$this->entityManager = $entityManager;
$this->container = $container;
$this->request = $requestStack->getCurrentRequest();
}
/**
* @return EntityManagerInterface
*/
public function getEntityManager(): EntityManagerInterface
{
return $this->entityManager;
}
/**
* @return ContainerInterface
*/
public function getContainer(): ContainerInterface
{
return $this->container;
}
/**
* @return VignetteEvent
*/
public function getListener(): VignetteEvent
{
return $this->listener;
}
/**
* @throws \Exception
*/
public function checkVignette()
{
if ($this->request->request->has('specialErrors')) {
$this->request->request->remove('specialErrors');
$this->request->request->remove('apiStatusCode');
}
if ($this->request->request->has('vignetteSubmitForm')) {
$this->request->request->remove('vignetteSubmitForm');
}
$apiService = new VignetteApiService($this->getEntityManager());
$params = $this->request->request->all();
$data = $apiService->constructInitDataArray($params);
$apiServiceRepository = $this->getEntityManager()->getRepository(VignetteApi::class);
if (!empty($data)) {
$apiResponse = $apiServiceRepository->checkRoVignette($data);
$ignoreAlreadyActive = $this->request->get('ignoreAlreadyActive') === 'true';
$fullIntersection = false;
if ($apiResponse && isset($apiResponse['intervals']) && $apiResponse['intervals']) {
$lastKey = array_key_last($apiResponse['intervals']);
if ($fullIntersection = $this->checkIfVignetteHasFullIntersection($apiResponse['intervals'][$lastKey], $data)) {
if ($apiResponse['isCategoryValid']) {
$ignoreAlreadyActive = false;
}
}
}
$ignoreWrongCategory = $this->request->get('ignoreWrongCategory') === 'true';
if ($ignoreWrongCategory) {
$ignoreAlreadyActive = true;
}
$isAvailabilityValid = !$apiResponse['alreadyActive'] || $ignoreAlreadyActive;
$isCategoryValid = $apiResponse['isCategoryValid'] || $ignoreWrongCategory;
if ($apiResponse['isCategoryValid'] && $fullIntersection) {
$isAvailabilityValid = false;
}
if ($apiResponse && $isAvailabilityValid && $isCategoryValid) {
if (isset($data['vignette_alert']) && $data['vignette_alert'] == 1 ) {
$data['vignette_alert'] = 1;
} else {
$data['vignette_alert'] = 0;
}
if (isset($data['email_allowed']) && $data['email_allowed'] == 1){
$data['email_allowed'] = 1;
} else {
$data['email_allowed'] = 0;
}
if ($this->request->get('partnerQueryParams')) {
$session = $this->request->getSession();
$session->set('partnerQueryParams',$this->request->get('partnerQueryParams'));
}
$data['publicToken'] = $params['publicToken'] ?? null;
$vignetteOrderService = new VignetteOrderService();
$data = $this->constructVignetteDataToStore($data);
$vignetteOrderService->storeVignetteInGlobalOrderSession($this->request, $data);
$this->request->request->set('vignetteSubmitForm', 1);
} else {
$errors = '';
if (!$isAvailabilityValid) {
$errors = $this->retrieveAlreadyActiveIntervalsMessage($apiResponse, $fullIntersection);
if ($errors) {
if ($this->container->has('security.token_storage')) {
$customer = CustomerService::retrieveCustomerBySecurityToken($this->container->get('security.token_storage'));
if ($customer && $customer instanceof Customer
&& isset($params['vin']) && $params['vin']) {
$validUntil = null;
foreach ($apiResponse['intervals'] as $key => $interval) {
$validUntil = new \DateTime($interval->valid_until);
}
$params['validUntil'] = $validUntil;
VehicleService::updateVehicleRoVignetteExpiresAtIfAvailable($params, $customer, $this->entityManager);
}
}
}
}
if (!$isCategoryValid) {
if ($errors) {
$errors = $errors . ' ' . $this->retrieveWrongCategoryMessage($apiResponse['validCategoryId']);
} else {
$errors = $this->retrieveWrongCategoryMessage($apiResponse['validCategoryId']);
}
}
$this->request->request->set('specialErrors', $errors);
}
}
}
/**
* @param $validCategoryId
* @return string|string[]
*/
public function retrieveWrongCategoryMessage($validCategoryId)
{
$translator = $this->getContainer()->get('translator');
$message = SystemService::retrieveMessage('valid_category_from_ws', $translator);
$categoryName = SystemService::retrieveMessage('category_rovignette_' . CategoryManager::retrieveCategoryShortCodeById($validCategoryId) . '_name',
$translator);
$message = str_replace('%CategoryName%', $categoryName, $message);
return $message;
}
/**
* @param $apiResponse
* @param $fullIntersection
* @return string|null
* @throws \Exception
*/
private function retrieveAlreadyActiveIntervalsMessage($apiResponse, $fullIntersection): ?string
{
$intervals = $apiResponse['intervals'];
$translator = $this->getContainer()->get('translator');
$message = SystemService::retrieveMessage('already_active_intervals', $translator);
$lastKey = array_key_last($intervals);
foreach ($intervals as $key => $interval) {
$validFrom = new \DateTime($interval->valid_from);
$validUntil = new \DateTime($interval->valid_until);
$message .= $validFrom->format('Y-m-d H:i:s') . ' - ' . $validUntil->format('Y-m-d H:i:s');
if ($key != $lastKey) {
$message .= ', ';
}
}
if (isset($apiResponse['vin']) && $apiResponse['vin']) {
$continueMessage = SystemService::retrieveMessage('already_active_intervals_vin', $translator);
$continueMessage = $continueMessage . $apiResponse['vin'];
$message = $message . $continueMessage;
}
if ($fullIntersection) {
$continueMessage = SystemService::retrieveMessage('already_active_intervals_continue', $translator);
$message = $message . $continueMessage;
}
return $message;
}
/**
* @param $data
* @return \stdClass
*/
private function constructVignetteDataToStore($data): \stdClass
{
$category = $this->entityManager->getRepository(Category::class)->findCategoryByUrl($data['category']);
$availability = $this->entityManager->getRepository(Availability::class)->findAvailabilityByUrl($data['availability']);
$price = $this->entityManager->getRepository(Price::class)->getPriceForCategoryAndAvailability($category, $availability);
$data['price'] = $price->getCustomerPrice();
$data['guid'] = SystemService::generateRandomString(32);
if (isset($data['valid_from']) && isset($data['availability'])) {
$validUntil = ValidityModel::retrieveValidUntilByValidFromAndAvailability(new \DateTime($data['valid_from']),
$this->entityManager->getRepository(Availability::class)->findAvailabilityByUrl($data['availability']));
$data['valid_until'] = $validUntil ? $validUntil->format(\DateTime::ATOM) : null;
}
//convert to stObject
$data = json_decode(json_encode($data));
return $data;
}
/**
* @param $activeIntervals
* @param $vignetteParams
* @return bool
* @throws \Exception
*/
private function checkIfVignetteHasFullIntersection($activeIntervals, $vignetteParams): bool
{
$isFullIntersection = false;
$validFrom = new \DateTime($vignetteParams['valid_from']);
$validUntil = ValidityModel::retrieveValidUntilByValidFromAndAvailability($validFrom,
$this->entityManager->getRepository(Availability::class)->findAvailabilityByUrl($vignetteParams['availability']));
$validFrom = new \DateTime($vignetteParams['valid_from']);
if ($validUntil) {
$activeStartDate = new \DateTime($activeIntervals->valid_from);
$activeEndDate = new \DateTime($activeIntervals->valid_until);
if ($activeStartDate->format('Y-m-d') == $validFrom->format('Y-m-d')
&& $activeEndDate->format('Y-m-d') == $validUntil->format('Y-m-d')) {
$isFullIntersection = true;
}
}
return $isFullIntersection;
}
}