<?php 
 
namespace DcSiteBundle\Controller; 
 
 
use CoreBundle\Component\CoreFormFactory; 
use CoreBundle\Component\FormManager; 
use CoreBundle\Controller\ViDiController; 
use CoreBundle\Entity\Dealer; 
use CoreBundle\Entity\Model; 
use CoreBundle\Factory\Vehicle as VehicleFactory; 
use CoreBundle\Model\Api\OnlineService\ApiServer1C; 
use CoreBundle\Model\Vehicles\AbstractVehicle; 
use CoreBundle\Model\Vehicles\InStockVehicle; 
use CoreBundle\Model\Vehicles\Repository; 
use CoreBundle\Model\Vehicles\Vehicle; 
use CoreBundle\Services\MediaExtensionVidi; 
use DateTime; 
use Doctrine\ORM\EntityManagerInterface; 
use Exception; 
use MyBundle\Entity\Basket; 
use PortalBundle\Model\SeoMetaTag; 
use Symfony\Component\Filesystem\Filesystem; 
use Symfony\Component\HttpFoundation\JsonResponse; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\RequestStack; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpFoundation\Session\SessionInterface; 
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; 
use Symfony\Component\Routing\RouterInterface; 
use Symfony\Component\String\UnicodeString; 
use Twig\Environment; 
 
class BaseDcController extends ViDiController 
{ 
    protected SeoMetaTag $seoMetaTag; 
    protected RequestStack $requestStack; 
    protected RouterInterface $router; 
    protected FormManager $formManager; 
    protected EntityManagerInterface $em; 
    protected ApiServer1C $apiServer1C; 
    protected SessionInterface $session; 
    protected Filesystem $filesystem; 
    protected MediaExtensionVidi $mediaExtensionVidi; 
    protected Repository $vehicleRepository; 
    protected VehicleFactory $vehicleFactory; 
    protected Environment $twig; 
 
    public function __construct(CoreFormFactory    $coreFormFactory, SeoMetaTag $seoMetaTag, RequestStack $requestStack, 
                                RouterInterface    $router, FormManager $formManager, EntityManagerInterface $em, 
                                ApiServer1C        $apiServer1C, SessionInterface $session, Filesystem $filesystem, 
                                MediaExtensionVidi $mediaExtensionVidi, Repository $vehicleRepository, 
                                VehicleFactory     $vehicleFactory, Environment $twig) 
    { 
        parent::__construct($coreFormFactory); 
        $this->seoMetaTag = $seoMetaTag; 
        $this->router = $router; 
        $this->formManager = $formManager; 
        $this->em = $em; 
        $this->apiServer1C = $apiServer1C; 
        $this->session = $session; 
        $this->filesystem = $filesystem; 
        $this->mediaExtensionVidi = $mediaExtensionVidi; 
        $this->vehicleRepository = $vehicleRepository; 
        $this->vehicleFactory = $vehicleFactory; 
        $this->twig = $twig; 
        $this->requestStack = $requestStack; 
    } 
 
    const DEALER_CITY_ID = 3; 
    /** 
     * @var array 
     */ 
    private static $dealers = []; 
 
    private $js = []; 
    private $baseJs = []; 
    private $jsParams = []; 
 
 
    protected function sendSmsLead(Request $request): JsonResponse 
    { 
        $formName = ''; 
        $formPhone = ''; 
        $formData = [ 
            'vin' => '', 'visit_date' => '', 'model' => '', 'brand' => '', 'year' => '', 'data' => [] 
        ]; 
 
        try { 
            if (empty($request->get('vin'))) { 
                throw new Exception("Не вказано 'vin'"); 
            } 
            if (empty($request->get('visitDate'))) { 
                throw new Exception("Не вказано 'visitDate'"); 
            } 
 
            $formData['vin'] = $request->get('vin'); 
            $formData['visit_date'] = str_replace('%', '-', $request->get('visitDate')); 
 
            $arr = $this->apiServer1C->getHistory($formData['vin']); 
 
            if (empty($arr)) { 
                throw new Exception("Не знайдено '{$formData['vin']}'"); 
            } 
            if (!empty($arr['ModelID'])) { 
 
                /** 
                 * @var $model Model 
                 */ 
                $model = $this->em 
                    ->getRepository(Model::class) 
                    ->findOneBy(['uid_1c' => $arr['ModelID']]); 
 
                if (!empty($model)) { 
                    $formData['model'] = $model->getTitle(); 
                    $formData['brand'] = $model->getBrand()->getName(); 
                } 
            } 
            if (!empty($arr['LastOwner'])) { 
                $formName = $arr['LastOwner']; 
            } 
            if (!empty($arr['Phone'])) { 
                $formPhone = $arr['Phone']; 
            } 
            if (!empty($arr['Year'])) { 
                $formData['year'] = $arr['Year']; 
            } 
            if (!empty($arr['data'])) { 
                $formData['data'] = $arr['data']; 
            } 
 
            $this->formManager->saveSmsLeadForm( 
                $request, 
                $this->getDealer(), 
                $formName, 
                $formPhone, 
                $formData 
            ); 
 
            return $this->success(); 
        } catch (Exception $e) { 
            return $this->error($e); 
        } 
    } 
 
    protected function checkSend(Request $request): bool 
    { 
        $vin = $request->get('vin'); 
        $visitDate = str_replace('%', '-', $request->get('visitDate')); 
 
        $toCheck = md5($vin . $visitDate); 
        $inSes = $this->session->get('nselectcheck'); 
        $inSes = is_array($inSes) ? $inSes : []; 
        if (!in_array($toCheck, $inSes)) { 
            $inSes[] = $toCheck; 
            $this->session->set('nselectcheck', $inSes); 
            return false; 
        } else { 
            return true; 
        } 
    } 
 
    public function getDealer(): Dealer 
    { 
        $request = $this->requestStack->getCurrentRequest(); 
        $host = $request->getHost(); 
        if (!isset(self::$dealers[md5($host)])) { 
 
            $dealerId = $request->get('dealerId'); 
            if ($host == 'vidi.ua' && !is_null($dealerId)) { 
                $findDealer = ['id' => $request->get('dealerId')]; 
            } else { 
                $host = $this->isDealerShop($host); 
                $findDealer = ['domain' => $host]; 
            } 
 
            $Dealer = $this->em->getRepository(Dealer::class)->findOneBy($findDealer); 
 
            if (!$Dealer) { 
                throw new NotFoundHttpException(); 
            } 
            self::$dealers[md5($host)] = $Dealer; 
        } 
 
        return self::$dealers[md5($host)]; 
    } 
 
    private function isDealerShop($host) 
    { 
        return str_replace("shop.", "", $host); 
    } 
 
 
    protected function webpUpdate(Request $request, $url, $manager) 
    { 
        $userAgent = $request->server->get('HTTP_USER_AGENT'); 
        preg_match("/(MSIE|Opera|Firefox|Chrome|Version)(?:\/| )([0-9.]+)/", $userAgent, $browser_info); 
        $browser = $browser_info[1] ?? false; 
        if (!$browser) { 
            return $url; 
        } 
        if ($browser == 'Version' || $browser == 'MSIE') { 
            return $url; 
        } 
        $basePath = $this->getParameter('kernel.project_dir') . '/public'; 
        $path = $basePath . $url . '.webp'; 
        if (file_exists($path)) { 
            return $manager->getUrl($url . '.webp'); 
        } 
        $im = @imagecreatefrompng($basePath . $url); 
        if (!$im) { 
            $im = @imagecreatefromjpeg($basePath . $url); 
        } 
        if ($im) { 
            $newUrl = $url . '.webp'; 
            if (imagewebp($im, $path)) { 
                imagedestroy($im); 
                return $manager->getUrl($newUrl); 
            } else { 
                imagedestroy($im); 
                return $manager->getUrl($url); 
            } 
        } 
        return $url; 
    } 
 
 
    protected function baseDcRender($view, array $parameters = [], Response $response = null): ?Response 
    { 
        $request = $this->requestStack->getCurrentRequest(); 
 
        $dealer = $this->getDealer(); 
 
        $seoMeta = $this->seoMetaTag->getSeoMeta($request); 
 
        $subdomain = explode('.', $request->server->get('HTTP_HOST'))[0]; 
 
        $basketCount = []; 
        if ($this->getUser()) { 
            $basketCount = $this->em->getRepository(Basket::class)->getBasketCountByDealerUser($this->getDealer(), $this->getUser()); 
        } else { 
            $guestBasket = $this->session->get('guest_basket', []); 
            if ($guestBasket && isset($guestBasket[$this->getDealer()->getId()])) { 
                $basket = $guestBasket[$this->getDealer()->getId()]; 
                $basketCount['count'] = 0; 
                foreach ($basket as $accessory) { 
                    $basketCount['count'] += intval($accessory['count']); 
                } 
            } 
        } 
 
        $basketCount = ($basketCount) ? $basketCount['count'] : 0; 
 
        $isSubdomainShop = $subdomain === "shop"; 
 
        $utmData = $this->getUtmData(); 
 
        $parameters = array_merge($parameters, [ 
            'dealer' => $this->getDealer(), 
            'basketCount' => $basketCount, 
            'dealerCityNihgtBooking' => self::DEALER_CITY_ID, 
            'backLoginUrl' => $request->getUri(), 
            'seoMeta' => $seoMeta, 
            'isSubdomainShop' => $isSubdomainShop, 
            'currentYear' => (new DateTime('now'))->format('Y'), 
            'utmData' => $utmData, 
        ]); 
 
        $helpCrunchParams = $this->getParameter('help_crunch_params')[$dealer->getUniqueId()] ?? null; 
        if ($helpCrunchParams) { 
            $parameters = array_merge($parameters, ['helpCrunch' => $helpCrunchParams]); 
        } 
        $content = $this->twig->render($view, $parameters); 
 
        if (null === $response) { 
            $response = new Response(); 
        } 
 
        return $response->setContent($content); 
    } 
 
    protected function getMpdfTempDir(): string 
    { 
        $newTempDir = $this->getParameter('file_directory_mpdf'); 
        if (!$this->filesystem->exists($newTempDir)) { 
            $this->filesystem-- > mkdir($newTempDir, 0777); 
        } 
        return $newTempDir; 
    } 
 
    public function getCarStructuredDataCarInStock(Request $request, InStockVehicle $item): bool|string 
    { 
        $twig = $this->mediaExtensionVidi; 
        $router = $this->router; 
 
        $routerCurrent = $router->getMatcher()->match($router->getContext()->getPathInfo())['_route']; 
        $routerCurrentParams = [ 
            'car' => $item->getUrl(), 
            'url' => $item->getUrl(), 
            'category' => $item->getCategory()->getUrl() 
        ]; 
 
        if ($routerCurrent == 'suzuki_card_moto') { 
            $routerCurrentParams = [ 
                'moto' => $item->getUrl() 
            ]; 
        } 
 
        $images = []; 
        $gallery = $item->getGallery(); 
 
        if (!empty($gallery)) { 
            $gallery = $gallery->getGalleryItems(); 
 
            if (!empty($gallery)) { 
                $images = $gallery->toArray(); 
            } 
        } 
 
        $images = array_reduce($images, function ($rows, $row) use ($request, $twig) { 
            $rows[] = $request->getSchemeAndHttpHost() . $twig->getPath($row->getMedia(), 'reference'); 
 
            return $rows; 
        }, [$request->getSchemeAndHttpHost() . $twig->getPath($item->getPreview(), 'reference')]); 
 
        $characteristics = $item->getCharacterisaticsByGroup($request->getLocale()); 
        $characteristicsSize = $characteristics[1] ?? []; 
 
        $characteristicsSizeNumberOfDoors = array_filter($characteristicsSize['characteristics'], fn($row) => $row['id'] === 15); 
        $characteristicsSizeNumberOfDoors = array_values($characteristicsSizeNumberOfDoors); 
 
        $characteristicsSizeVehicleSeatingCapacity = array_filter($characteristicsSize['characteristics'], fn($row) => $row['id'] === 20); 
        $characteristicsSizeVehicleSeatingCapacity = array_values($characteristicsSizeVehicleSeatingCapacity); 
 
        switch ($item->getDriveUnitType()->getId()) { 
            case 13: 
                $driveWheelConfiguration = 'AllWheelDriveConfiguration'; // Повний 
                break; 
            case 3: 
                $driveWheelConfiguration = 'FrontWheelDriveConfiguration'; // Передній 
                break; 
            case 11: 
                $driveWheelConfiguration = 'RearWheelDriveConfiguration'; // Задній 
                break; 
            case 27: 
                $driveWheelConfiguration = 'FourWheelDriveConfiguration'; // AWD 
                break; 
            default: 
                $driveWheelConfiguration = 'undefined'; 
                break; 
        } 
 
        return json_encode([ 
            "@context" => "http://schema.org", 
            "@type" => "Car", 
            "name" => $item->getFullName(), 
            "vehicleIdentificationNumber" => $item->getVin() ?? '00000000000000000', 
            "image" => $images, 
            "url" => $router->generate($routerCurrent, $routerCurrentParams, UrlGeneratorInterface::ABSOLUTE_URL), 
            "offers" => [ 
                "@type" => "Offer", 
                "availability" => "http://schema.org/InStock", 
                "price" => $item->price(), 
                "priceCurrency" => "UAH" 
            ], 
            "itemCondition" => "https://schema.org/NewCondition", 
            "brand" => [ 
                "@type" => "Brand", 
                "name" => $item->getBrand()->getName() 
            ], 
            "model" => $item->getModelName(), 
            "vehicleConfiguration" => $item->getEquipment()->getTitle(), 
            "vehicleModelDate" => $item->getYear(), 
            "mileageFromOdometer" => [ 
                "@type" => "QuantitativeValue", 
                "value" => 0, 
                "unitCode" => 'KMT' 
            ], 
            "color" => $item->getColor(), 
            "vehicleInteriorColor" => $item->getColor(), 
            "vehicleInteriorType" => 'Standard', 
            "bodyType" => $item->getBodyTypeName($request->getLocale()), 
            "driveWheelConfiguration" => $driveWheelConfiguration, 
            "vehicleEngine" => [ 
                "@type" => "EngineSpecification", 
                "engineType" => $item->getFuelTypeName($request->getLocale()), 
            ], 
            "vehicleTransmission" => $item->getTransmissionTypeName($request->getLocale()), 
            "numberOfDoors" => $characteristicsSizeNumberOfDoors[0]['value'] ?? null, 
            "vehicleSeatingCapacity" => $characteristicsSizeVehicleSeatingCapacity[0]['value'] ?? null 
        ], JSON_UNESCAPED_SLASHES); 
    } 
 
    public function getCarStructuredDataCarUsed(Request $request, AbstractVehicle $item): bool|string 
    { 
        $twig = $this->mediaExtensionVidi; 
        $router = $this->router; 
 
        $routerCurrent = $router->getMatcher()->match($router->getContext()->getPathInfo())['_route']; 
        $routerCurrentParams = [ 
            'id' => $item->getVehicleId(), 
            'url' => $item->getUrl() 
        ]; 
 
        if ($routerCurrent == 'suzuki_card_moto') { 
            $routerCurrentParams = [ 
                'moto' => $item->getUrl() 
            ]; 
        } 
 
        $images = array_reduce(($item->getGallery()) ? $item->getGallery()->getGalleryItems()->toArray() : [], function ($rows, $row) use ($request, $twig) { 
            $rows[] = $request->getSchemeAndHttpHost() . $twig->getPath($row->getMedia(), 'reference'); 
 
            return $rows; 
        }, [$request->getSchemeAndHttpHost() . $twig->getPath($item->getPreview(), 'reference')]); 
 
        $characteristics = $item->getCharacterisaticsWithGroup($request->getLocale()); 
        $characteristicsSize = $characteristics[1] ?? []; 
 
        $characteristicsSizeNumberOfDoors = array_filter($characteristicsSize['characteristics'], fn($row) => $row['id'] === 15); 
        $characteristicsSizeNumberOfDoors = array_values($characteristicsSizeNumberOfDoors); 
 
        $characteristicsSizeVehicleSeatingCapacity = array_filter($characteristicsSize['characteristics'], fn($row) => $row['id'] === 20); 
        $characteristicsSizeVehicleSeatingCapacity = array_values($characteristicsSizeVehicleSeatingCapacity); 
 
        return json_encode([ 
            "@context" => "http://schema.org", 
            "@type" => "Car", 
            "name" => $item->getFullName(), 
            "vehicleIdentificationNumber" => $item->getVIN() ?? '00000000000000000', 
            "image" => $images, 
            "url" => $router->generate($routerCurrent, $routerCurrentParams, UrlGeneratorInterface::ABSOLUTE_URL), 
            "offers" => [ 
                "@type" => "Offer", 
                "availability" => "http://schema.org/InStock", 
                "price" => $item->price(), 
                "priceCurrency" => "UAH" 
            ], 
            "itemCondition" => "https://schema.org/UsedCondition", 
            "brand" => [ 
                "@type" => "Brand", 
                "name" => $item->getBrand()->getName() 
            ], 
            "model" => $item->getModelName(), 
            "vehicleConfiguration" => $item->getEquipment()->getTitle(), 
            "vehicleModelDate" => $item->getYear(), 
            "mileageFromOdometer" => [ 
                "@type" => "QuantitativeValue", 
                "value" => $item->getMileage(), 
                "unitCode" => 'KMT' 
            ], 
            "color" => $item->getBodyColor($request->getLocale()), 
            "vehicleInteriorColor" => $item->getBodyColor($request->getLocale()), 
            "vehicleInteriorType" => 'Standard', 
            "bodyType" => $item->getBodyTypeName($request->getLocale()), 
            "driveWheelConfiguration" => $item->getDriveUnitTypeName($request->getLocale()), 
            "vehicleEngine" => [ 
                "@type" => "EngineSpecification", 
                "engineType" => $item->getFuelTypeName($request->getLocale()), 
            ], 
            "vehicleTransmission" => $item->getTransmissionTypeName($request->getLocale()), 
            "numberOfDoors" => $characteristicsSizeNumberOfDoors[0]['value'] ?? null, 
            "vehicleSeatingCapacity" => $characteristicsSizeVehicleSeatingCapacity[0]['value'] ?? null 
        ], JSON_UNESCAPED_SLASHES); 
    } 
 
    public function getCarPageStructuredData(Request $request, Vehicle $vehicle): string 
    { 
        $twig = $this->mediaExtensionVidi; 
        $router = $this->router; 
        $currentRoute = $router->getMatcher()->match($router->getContext()->getPathInfo())['_route']; 
        if ($vehicle->getDealer()->getUrl() !== 'land-rover') { 
            $homepageRoute = $router->generate( 
                preg_replace('([^a-zA-Z])', '_', $vehicle->getDealer()->getUrl()) . '_homepage', [], UrlGeneratorInterface::ABSOLUTE_URL 
            ); 
        } else { 
            $homepageRoute = $router->generate( 
                preg_replace('([^a-zA-Z])', '', $vehicle->getDealer()->getUrl()) . '_homepage', [], UrlGeneratorInterface::ABSOLUTE_URL 
            ); 
        } 
        $params = [ 
            'car' => $vehicle->getUrl(), 
            'url' => $vehicle->getUrl(), 
            'category' => $vehicle->getCategory() ? $vehicle->getCategory()->getUrl() : '', 
        ]; 
        if ($currentRoute == 'suzuki_card_moto') { 
            $params = ['moto' => $vehicle->getUrl()]; 
        } 
        $images = [ 
            $request->getSchemeAndHttpHost() . $twig->getPath($vehicle->getPreview(), 'reference'), 
        ]; 
        $gallery = $vehicle->getGallery(); 
        if ($gallery) { 
            foreach ($gallery->getGalleryItems() as $galleryItem) { 
                $images[] = $request->getSchemeAndHttpHost() . $twig->getPath($galleryItem->getMedia(), 'reference'); 
            } 
        } 
 
        return json_encode([ 
            "@context" => "http://schema.org", 
            "@type" => "Product", 
            "image" => $images, 
            "brand" => [ 
                "@type" => "Brand", 
                "name" => $vehicle->getBrand()->getName(), 
            ], 
            "manufacturer" => [ 
                "@type" => "Corporation", 
                "name" => $vehicle->getBrand()->getName() 
            ], 
            "description" => $vehicle->seoDescription($request->getLocale()), 
            "sku" => $vehicle->getVehicleId(), 
            "name" => $vehicle->getFullName(), 
            "offers" => [ 
                "@type" => "AggregateOffer", 
                "availability" => "http://schema.org/InStock", 
                "priceCurrency" => "UAH", 
                "price" => $vehicle->price(), 
                "lowPrice" => $vehicle->minPrice(), 
                "highPrice" => $vehicle->maxPrice(), 
            ], 
            "itemCondition" => "http://schema.org/NewCondition", 
            "url" => $router->generate($currentRoute, $params, UrlGeneratorInterface::ABSOLUTE_URL) 
        ], JSON_UNESCAPED_SLASHES); 
    } 
 
    public function getModelMenuItems($locale, $format = null, $categId = false): array 
    { 
        $cars = $this->vehicleRepository->getNewByDealer($this->getDealer()); 
        $categories = []; 
        /** @var \CoreBundle\Entity\Vehicles\Vehicle $car */ 
        foreach ($cars as $car) { 
            $vehicleModel = $this->vehicleFactory->createByEntity($car); 
            if (!$vehicleModel) { 
                continue; 
            } 
            $categoryId = $car->getCategory() ? $car->getCategory()->getId() : null; 
            if ($categId && $categoryId != $categId) continue; 
 
            $key = array_search($categoryId, array_column($categories, 'id')); 
            $format = $format ?: 'menu'; 
            $oneCar = [ 
                'id' => $vehicleModel->getVehicleId(), 
                'title' => $vehicleModel->getModelName(), 
                'customTitle' => $vehicleModel->getCustomName($locale), 
                'isNew' => $vehicleModel->isNew(), 
                'isPreOrder' => $vehicleModel->isPreOrder(), 
                'onTestDrive' => $vehicleModel->getTestDrive(), 
                'position' => $vehicleModel->getPosition(), 
                'url' => $vehicleModel->getUrl(), 
                'hasHybrid' => $vehicleModel->hasHybrid(), 
                'price' => round($vehicleModel->price()), 
                'image' => $vehicleModel->getPreviewPath($format), 
                'image_webp' => $vehicleModel->getPreviewPathWebp($format), 
                'modelId' => $vehicleModel->getModel()->getId(), 
                'preorderPrice' => $vehicleModel->getPreorderPrice(), 
            ]; 
 
            if ($key === false && $car->getCategory()) { 
                $category = [ 
                    'id' => $categoryId, 
                    'title' => $vehicleModel->getCategory()->getTitle($locale), 
                    'position' => $vehicleModel->getCategory()->getPosition(), 
                    'url' => $vehicleModel->getCategory()->getUrl(), 
                    'cars' => [] 
                ]; 
                $category['cars'][] = $oneCar; 
                $categories[] = $category; 
            } else { 
                $categories[$key]['cars'][] = $oneCar; 
            } 
        } 
        $positionC = []; 
        foreach ($categories as $k => &$row) { 
            $position = []; 
            foreach ($row['cars'] as $key => $car) { 
                $position[$key] = $car['position']; 
            } 
            $positionC[$k] = $row['position']; 
            array_multisort($position, SORT_ASC, $row['cars']); 
        } 
 
        array_multisort($positionC, SORT_ASC, $categories); 
        return $categories; 
    } 
 
    protected function removeBOM($str = ""): bool|string 
    { 
        if (substr($str, 0, 3) == pack('CCC', 0xef, 0xbb, 0xbf)) { 
            $str = substr($str, 3); 
        } 
        return $str; 
    } 
 
    public function getUtmData(): string 
    { 
        $request = $this->requestStack->getCurrentRequest(); 
 
        if (!$request) { 
            return json_encode([], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); 
        } 
 
        $utmData = []; 
        $utmTags = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content']; 
 
        foreach ($utmTags as $tag) { 
            $pascalCaseTag = (new UnicodeString($tag))->camel()->title()->toString(); 
 
            $utmData[$pascalCaseTag] = $request->query->get($tag, ''); 
        } 
 
        $utmData['BpmRef'] = $request->headers->get('referer', ''); 
        $utmData['BpmHref'] = $request->getUri(); 
 
        return json_encode($utmData,  JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); 
    } 
 
}