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

namespace Magediary\ProductQuestion\Ui\Component\Listing;

use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Store\Model\Store;
use Magento\Eav\Model\Config;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Framework\DB\Select;

class ActivityLogDataProvider extends SearchResult
{
    /**
     * @var ProductMetadataInterface
     */
    protected $productMetadata;

    /**
     * Add filter
     */
    protected function _construct()
    {
        parent::_construct();
        $this->addFilterToMap(
            'created_at',
            'main_table.created_at'
        );
    }

    /**
     * Get object
     *
     * @return ProductMetadataInterface
     */
    private function getProductMetadata()
    {
        if ($this->productMetadata == null) {
            $this->productMetadata = ObjectManager::getInstance()->get(ProductMetadataInterface::class);
        }
        return $this->productMetadata;
    }

    /**
     * @inheritdoc
     *
     * @return $this|QuestionDataProvider|void
     * @throws LocalizedException
     */
    protected function _initSelect()
    {
        parent::_initSelect();

        $productNameAttributeId = ObjectManager::getInstance()->get(Config::class)
            ->getAttribute(Product::ENTITY, ProductInterface::NAME)
            ->getAttributeId();

        $tableAnswer = $this->getResource()->getTable('magediary_question_answer');
        $tableProductVarchar = $this->getResource()->getTable('catalog_product_entity_varchar');
        $tableProductEntity = $this->getResource()->getTable('catalog_product_entity');
        $storeId = Store::DEFAULT_STORE_ID;

        $this->getSelect()
            ->joinLeft(
                ['a' => $tableAnswer],
                'a.answer_id = main_table.answer_id',
                ['answer_detail' => 'a.detail', 'answer_id' => 'a.answer_id']
            )
        ;

        if (in_array($this->getProductMetadata()->getEdition(), ['Enterprise', 'B2B'])) {
            $this->addExpressionFieldToSelect(
                'name',
                '(SELECT product_varchar.value
                    FROM ' . $tableProductVarchar . ' product_varchar
                    WHERE product_varchar.attribute_id = ' . $productNameAttributeId . ' AND {{entity_id}} =
                        (SELECT row_id FROM ' . $tableProductEntity . ' nc
                            INNER JOIN (SELECT MIN(row_id) min_row_id FROM ' . $tableProductEntity .
                            ' GROUP BY entity_id) nb ON nc.row_id = nb.min_row_id
                            WHERE nc.entity_id = main_table.product_id
                        ) AND store_id = ' . $storeId . '
                    )',
                ['entity_id' => 'product_varchar.row_id']
            );

            $this->addExpressionFieldToSelect(
                'sku',
                '(SELECT s.sku
                    FROM ' . $tableProductEntity . ' s
                    WHERE {{entity_id}} =
                        (SELECT row_id FROM ' . $tableProductEntity . ' nc
                            INNER JOIN (SELECT MIN(row_id) min_row_id FROM ' . $tableProductEntity . '
                            GROUP BY entity_id) nb ON nc.row_id = nb.min_row_id
                            WHERE nc.entity_id = main_table.product_id
                        )
                    )',
                ['entity_id' => 's.row_id']
            );
        } else {
            $this->addExpressionFieldToSelect(
                'name',
                '(SELECT product_varchar.value
                    FROM ' . $tableProductVarchar . ' product_varchar
                    WHERE product_varchar.attribute_id = ' . $productNameAttributeId . ' AND
                    {{entity_id}} = main_table.product_id AND store_id = ' . $storeId . '
                    )',
                ['entity_id' => 'product_varchar.entity_id']
            );

            $this->addExpressionFieldToSelect(
                'sku',
                '(SELECT s.sku
                    FROM ' . $tableProductEntity . ' s
                    WHERE {{entity_id}} = main_table.product_id
                    )',
                ['entity_id' => 's.entity_id']
            );
        }

        return $this;
    }

    /**
     * Get total records
     *
     * @return int
     */
    public function getSize()
    {
        if ($this->_totalRecords === null) {
            $sql = $this->getSelect();
            $sql->reset(\Magento\Framework\DB\Select::LIMIT_COUNT);
            $this->_totalRecords = count($this->getConnection()->fetchAll($sql, $this->_bindParams));
        }
        return (int) $this->_totalRecords;
    }

    /**
     * Add custom filter conditions
     *
     * @param array|string $field
     * @param mixed $condition
     * @return $this|SearchResult
     */
    public function addFieldToFilter($field, $condition = null)
    {
        if (is_array($field)) {
            $conditions = [];
            foreach ($field as $key => $value) {
                $conditions[] = $this->_translateCondition($value, isset($condition[$key]) ? $condition[$key] : null);
            }
            $resultCondition = '(' . implode(') ' . Select::SQL_OR . ' (', $conditions) . ')';
        } else {
            $resultCondition = $this->_translateCondition($field, $condition);
        }

        if ($field=='sku' || $field=='name' || $field=='answer_detail') {
            $this->_select->having($resultCondition, null, Select::TYPE_CONDITION);
        } else {
            $this->_select->where($resultCondition, null, Select::TYPE_CONDITION);
        }

        return $this;
    }
}
