<?php

namespace FiloBlu\Flow\Model\From;

use Exception;
use FiloBlu\Flow\Helper\Data;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Registry;

/**
 * Class Eavs
 * @package FiloBlu\Flow\Model\From
 */
class Eavs extends AbstractFrom
{
    /**
     * Lookup values for meata executed on
     * @var array
     */
    const TYPE_MAP = [
        'product' => 'catalog_product',
        'attribute' => 'product_attribute',
        'customer' => 'customer'
    ];

    /**
     * @var int
     */
    const PRODUCT_NOT_FOUND_ERR_CODE = 1;
    /**
     * @var int
     */
    const SKU_ATTRIBUTE_ERR_CODE = 2;
    /**
     * @var int
     */
    const DROPDOWN_STORE_ERR_CODE = 3;
    /**
     * @var string
     */
    const ENTITY_MANAGER_CLASS_PREFIX = 'FiloBlu\Flow\Model\From\Entity\\';
    /**
     * @var string
     */
    const DEFAULT_ENTITY_TYPE_CODE = 'catalog_product';
    /**
     * @var string
     */
    const ATTRIBUTE_ENTITY_TYPE_SUFFIX = 'attribute';
    /**
     * @var string
     */
    const CUSTOMER_ENTITY_TYPE_SUFFIX = 'customer';
    /**
     * @var string
     */
    const PRODUCT_ATTRIBUTE_ENTITY_TYPE_CODE = 'product_attribute';
    /**
     * @var string
     */
    const EMAIL_FROM = 'Eavs processor <magenteam@.it>';
    /**
     * @var string
     */
    const EMAIL_TO = '';
    /**
     * @var integer
     */
    const PRODUCT_REF_ID = 0;
    /**
     * @var integer
     */
    const ATTRIBUTE_REF_ID = 1;
    /**
     * @var integer
     */
    const SPECIAL_REF_ID = 2;
    /**
     * @var string
     */
    const EXECUTED_ON_ATTRIBUTE = 'attribute';
    /**
     * @var string
     */
    const EXECUTED_ON_PRODUCT = 'product';
    /**
     * @var string
     */
    const EXECUTED_ON_CUSTOMER = 'customer';
    /**
     * @var bool
     */
    protected $_dontRetryErrorCodes = true;
    /**
     * @var int
     */
    protected $_productEntityTypeId = 4;

    /**
     * @var ScopeConfigInterface|null
     */
    protected $_scopeConfig;
    /**
     * @var ProductMetadataInterface
     */
    protected $_productMetadata;
    /**
     * @var ObjectManagerInterface
     */
    protected $objectManager;
    /**
     * @var Data
     */
    protected $helper_flow;
    /**
     * @var ResourceConnection
     */
    protected $resourceConnection;

    /**
     * Eavs constructor.
     * @param ScopeConfigInterface $scopeConfig
     * @param Context $context
     * @param Registry $registry
     * @param Data $helperFlow
     * @param ObjectManagerInterface $objectManager
     * @param ProductMetadataInterface $productMetadata
     * @param ResourceConnection $resourceConnection
     * @param AbstractResource|null $resource
     * @param AbstractDb|null $resourceCollection
     * @param array $data
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        Context $context,
        Registry $registry,
        Data $helperFlow,
        ObjectManagerInterface $objectManager,
        ProductMetadataInterface $productMetadata,
        ResourceConnection $resourceConnection,
        AbstractResource $resource = null,
        AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->helper_flow = $helperFlow;

        $this->_scopeConfig = $scopeConfig;
        $this->_productMetadata = $productMetadata;
        $this->objectManager = $objectManager;
        $this->resourceConnection = $resourceConnection;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }

    /**
     * @return void
     * @noinspection MagicMethodsValidityInspection
     */
    public function _construct()
    {
        $this->_init(\FiloBlu\Flow\Model\ResourceModel\From\Eavs::class);
    }

    /**
     * @return $this|bool|\FiloBlu\Flow\Model\From\Customer
     * @throws Exception
     */
    public function process()
    {
        $storesId = $this->getStoreId();
        $executedOn = $this->getExecutedOn();

        if (!isset(self::TYPE_MAP[$executedOn])) {
            $this->_logger->error("Unknown type code $executedOn");
            return $this;
        }

        $entityType = self::TYPE_MAP[$executedOn];
        $entityManagerClassName = $this->getEntityManagerClassName($entityType);

        try {
            foreach ($storesId as $storeId) {
                $this->objectManager->create(
                    $entityManagerClassName,
                    [
                        'data' => [
                            'entityIdentifier' => $this->getE(),
                            'attributeCode' => $this->getA(),
                            'attributeValue' => stripcslashes($this->getV()),
                            'entityTypeCode' => $entityType,
                            'storeId' => $storeId
                        ]
                    ]
                )->process();
            }
        } catch (Exception $e) {
            $this->_logger->info($e->getMessage());
            return $this->error(false, $e->getMessage());
        }

        return $this;
    }

    /**
     * @return array|bool
     */
    protected function getStoreId()
    {
        $storeView = $this->getS();
        $language = $this->getL();

        $allStore = $this->helper_flow->getAllStoreIds();
        /* storeview is in s tag with codename */
        if (!empty($storeView)) {
            if (strtolower(trim($storeView)) === 'default') {
                $stores[] = 0;
                return $stores;
            }
            if (isset($allStore[$storeView])) {
                $stores[] = $allStore[$storeView];
                return $stores;
            }
        } elseif (!empty($language)) {
            $languages = $this->helper_flow->getListLanguageForAllStores();
            if (isset($languages[strtolower($language)])) {
                return $languages[strtolower($language)];
            }
        }

        return [0];
    }

    /**
     * TODO : Can be simplified
     * @param $entityTypeCode
     * @return string
     */
    protected function getEntityManagerClassName($entityTypeCode)
    {
        if ((string)$entityTypeCode === self::DEFAULT_ENTITY_TYPE_CODE) {
            return self::ENTITY_MANAGER_CLASS_PREFIX . 'Product';
        }

        if (strpos($entityTypeCode, self::ATTRIBUTE_ENTITY_TYPE_SUFFIX) !== false) {
            return self::ENTITY_MANAGER_CLASS_PREFIX . 'Attribute';
        }

        if (strpos($entityTypeCode, self::CUSTOMER_ENTITY_TYPE_SUFFIX) !== false) {
            return self::ENTITY_MANAGER_CLASS_PREFIX . 'Customer';
        }

        return self::ENTITY_MANAGER_CLASS_PREFIX . 'AbstractEntity';
    }

    /**
     * @param $file
     * @return bool
     */
    public function sendErrorNotifications($file)
    {
        return true;
    }

    /**
     * @return string
     */
    protected function getEntityField()
    {
        $edition = $this->_productMetadata->getEdition();
        return ($edition === 'Enterprise' || $edition === 'B2B') ? 'row_id' : 'entity_id';
    }
}
