<?php
/**
 * @author  Magediary
 * @package Magediary_ProductQuestion
 */

namespace Magediary\ProductQuestion\Model\ResourceModel;

use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class Answer extends AbstractDb
{
    /**
     * @var ActivityLog
     */
    protected $resourceLog;

    /**
     * @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory
     */
    protected $_orderCollectionFactory;

    /**
     * Customer session model
     *
     * @var \Magento\Customer\Model\Session
     */
    protected $customerSession;

    /**
     * Catalog product model
     *
     * @var \Magento\Catalog\Api\ProductRepositoryInterface
     */
    protected $productRepository;

    /**
     * @var \Magento\Framework\Event\ManagerInterface
     */
    protected $_eventManager;

    /**
     * @param ActivityLog $resourceLog
     * @param \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory
     * @param \Magento\Customer\Model\Session $customerSession
     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
     * @param null|string $connectionName
     */
    public function __construct(
        \Magediary\ProductQuestion\Model\ResourceModel\ActivityLog $resourceLog,
        \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Framework\Model\ResourceModel\Db\Context $context,
        $connectionName = null
    ) {
        $this->_orderCollectionFactory = $orderCollectionFactory;
        $this->customerSession = $customerSession;
        $this->resourceLog = $resourceLog;
        $this->productRepository = $productRepository;
        $this->_eventManager = $eventManager;

        parent::__construct($context, $connectionName);
    }

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('magediary_question_answer', 'answer_id');
    }

    /**
     * Get like and dislike count
     *
     * @param int $id
     * @return $this
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function updateLikeDislikeCount($id)
    {
        $table = $this->getMainTable();

        $likes = (int)$this->resourceLog->getLikeCount($id);
        $dislikes = (int)$this->resourceLog->getDislikeCount($id);

        $this->getConnection()->update(
            $table,
            ['likes' => $likes, 'dislikes' => $dislikes],
            ['answer_id = ?' => (int)$id]
        );

        return $this;
    }

    /**
     * Set is certified flag
     *
     * @param AbstractModel $object
     * @return AbstractDb|void
     */
    protected function _beforeSave(AbstractModel $object)
    {
        $email = $object->getEmail();
        $productId = $object->getProductId();
        $customerId = $this->customerSession->getCustomerId();

        if (($email || $customerId) && $productId) {
            $collection = $this->_orderCollectionFactory->create();

            $collection->getSelect()->join(
                ['oi'=>'sales_order_item'],
                "main_table.entity_id = oi.order_id AND (oi.parent_item_id = $productId OR oi.product_id = $productId)",
                'oi.item_id'
            );

            if ($customerId) {
                $collection->addFieldToFilter('main_table.customer_id', $customerId);

                $collection->getSelect()->join(
                    ['o'=>'sales_order'],
                    "o.entity_id = oi.order_id AND (o.customer_id = $customerId)",
                    'o.customer_id'
                );
            } elseif ($email) {
                $collection->addFieldToFilter('main_table.customer_email', $email);

                $collection->getSelect()->join(
                    ['o'=>'sales_order'],
                    "o.entity_id = oi.order_id AND (o.customer_email = '$email')",
                    'o.customer_id'
                );
            }

            if ($collection->count()) {
                $object->setIsCertified(1);
            }
        }

        parent::_beforeSave($object);
    }

    /**
     * Clear product cache after save the answer
     *
     * @param AbstractModel $object
     * @return AbstractDb
     */
    protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
    {
        $product = $this->loadProduct($object->getProductId());
        if ($product) {
            $this->_eventManager->dispatch('clean_cache_by_tags', ['object' => $product]);
        }

        return parent::_afterSave($object);
    }

    /**
     * Load product model with data by passed id.
     *
     * Return false if product was not loaded or has incorrect status.
     *
     * @param int $productId
     * @return bool|CatalogProduct
     */
    protected function loadProduct($productId)
    {
        if (!$productId) {
            return false;
        }

        try {
            $product = $this->productRepository->getById($productId);
        } catch (NoSuchEntityException $noEntityException) {
            return false;
        }

        return $product;
    }
}
