<?php

namespace Benhauer\Salesmanago\Observer\Events\Purchase;

use \Psr\Log\LoggerInterface;
use \Magento\Framework\Stdlib\DateTime\TimezoneInterface as MagentoDateTime;
use \Magento\Framework\Event\ObserverInterface;
use \Magento\Checkout\Model\Session;
use \Magento\Store\Api\Data\StoreInterface;
use \Magento\Framework\UrlInterface;
use \Magento\Newsletter\Model\Subscriber;
use \Magento\Customer\Api\CustomerRepositoryInterface;
use \Magento\Framework\Stdlib\CookieManagerInterface;
use \Magento\Store\Model\StoreManagerInterface;
use \Magento\Sales\Api\OrderRepositoryInterface;
use \Magento\Quote\Model\QuoteFactory;
use \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory;
use \Magento\Framework\Session\SessionManagerInterface;
use \Magento\Framework\Event\Observer;

use \SALESmanago\Services\ConnectSalesManagoService;
use \SALESmanago\Provider\UserProvider;
use \SALESmanago\Factories\FactoryOrganizer;

use \Benhauer\Salesmanago\Model\Hooks as HooksModel;
use \Benhauer\Salesmanago\Model\Contact;
use \Benhauer\Salesmanago\Helper\Tagger;
use \Benhauer\Salesmanago\Model\Config\PurchasesConfig;
use \Benhauer\Salesmanago\Observer\AbstractObserver as SalesmanagoAbstractObserver;

abstract class AbstractPurchaseObserver extends SalesmanagoAbstractObserver
{
    public $purchasesConfigModel;
    public $orderRepository;
    public $quoteFactory;

    const ORDER_ID_COOKIE_NAME = 'smorid';

    static $cookieExpiredTime = 30960000;

    public function __construct(
        Session $session,
        StoreInterface $store,
        Subscriber $subscriber,
        HooksModel $model,
        CustomerRepositoryInterface $customerRepositoryInterface,
        CookieManagerInterface $cookieManager,
        MagentoDateTime $objDate,
        FactoryOrganizer $factoryOrganizer,
        Tagger $tagger,
        LoggerInterface $logger,
        Contact $modelContact,
        StoreManagerInterface $storeManager,
        PurchasesConfig $purchasesConfigModel,
        OrderRepositoryInterface $orderRepository,
        QuoteFactory $quoteFactory,
        CookieMetadataFactory $cookieMetadataFactory,
        SessionManagerInterface $sessionManager
    ) {
        parent::__construct(
            $session,
            $store,
            $subscriber,
            $model,
            $customerRepositoryInterface,
            $cookieManager,
            $objDate,
            $factoryOrganizer,
            $tagger,
            $logger,
            $modelContact,
            $storeManager
        );
        $this->purchasesConfigModel = $purchasesConfigModel;
        $this->orderRepository = $orderRepository;
        $this->quoteFactory = $quoteFactory;
        $this->cookieMetadataFactory = $cookieMetadataFactory;
        $this->sessionManager = $sessionManager;
    }

    public function execute(Observer $observer)
    {
        if ($this->purchasesConfigModel->getType() == PurchasesConfig::P_T_CRON) {
            $this->deleteEventCookie(['success' => true]);
        }

        if (!$this->purchasesConfigModel->isHookActive($observer->getEvent()->getName())) {
            return false;
        }

        $this->setStoreViewForModel();
        if ($this->model->getUserSettings(null) == false) {
            return true;
        }

        $this->hookAct($observer);
    }

    public function hookAct(Observer $observer){}

    public function executePurchase($order = null) {
        try {
            if (empty($order)) {
                return false;
            }

            $contact = '';

            $billingAddress = $order->getBillingAddress();
            $customerEmail = $billingAddress->getEmail();
            $smClientCookie = $this->cookieManager->getCookie('smclient');

            $connectSalesManago = $this->getConnectSalesManago();

            if ($order->getCustomerId() == null
                && $order->getCustomerIsGuest()
            ) {
                $Contact = $this->modelContact->getContactByCustomerBillingAddress($billingAddress, $customerEmail);
                $Contact->getOptions()->setAdditional(
                    [HooksModel::SYNC_RULE => $this->model->getSynchronizeRule()]
                );

                $contact = $Contact->getDataOptions();

                $contact = $this->tagger
                    ->setModel($this->model)
                    ->setTags($contact, [Tagger::T_PURCHASE, Tagger::T_GUEST_PURCHASE]);

                $response = $this->upsertContact($contact, $connectSalesManago, SalesmanagoAbstractObserver::UPSERT_FLAG_ALL_DATA);

            } elseif ($order->getCustomerId() != null) {
                $customerId = $order->getCustomerId();
                $contact = $this->getCustomerById($customerId);

                $contact = $this->tagger
                    ->setModel($this->model)
                    ->setTags($contact, Tagger::T_PURCHASE);

                $response = $this->upsertContact($contact, $connectSalesManago, SalesmanagoAbstractObserver::UPSERT_FLAG_ALL_DATA);
            }

            if (isset($contact['data'])) {
                $contact = $contact['data'];
            } elseif ($smClientCookie != null && !isset($contact['email'])) {
                $contact = [
                    'contactId' => $smClientCookie
                ];
            }

            $products = $this->getProductsFromOrder($order, $this->quoteFactory);

            if (isset($products['description']) && (strpos($products['description'], 'klarna') !== false)) {
                return true;
            }

            $response = $connectSalesManago->contactExtEvent(
                ConnectSalesManagoService::EVENT_TYPE_PURCHASE,
                $products,
                $contact,
                ''
            );

            $this->deleteEventCookie($response);

            return true;
        } catch (\Exception $e) {
            $this->logger->critical($e->getMessage());
        }
    }

    /**
     * Set order Id to cookie;
     */
    protected function setOrderIdToCookie($value)
    {
        $this->session->setSmOrderId($value);

        $metadata = $this->cookieMetadataFactory
            ->createPublicCookieMetadata()
            ->setDuration(self::$cookieExpiredTime)
            ->setPath($this->sessionManager->getCookiePath())
            ->setDomain($this->sessionManager->getCookieDomain());

        $this->cookieManager->setPublicCookie(self::ORDER_ID_COOKIE_NAME, $value, $metadata);
    }

    /**
     * Gets order Id from cookie;
     */
    protected function getOrderIdFromCookie()
    {
        $sessionOrderId = $this->session->getSmOrderId();
        $cookieOrderId = $this->cookieManager->getCookie(self::ORDER_ID_COOKIE_NAME);

        $orderId = empty($sessionOrderId) ? $cookieOrderId : $sessionOrderId;

        return $orderId;
    }
}
