<?php

namespace FiloBlu\Flow\Model\From;

use Exception;
use FiloBlu\Flow\Helper\Data;
use Magento\Catalog\Model\Product\Action;
use Magento\Catalog\Model\ProductFactory;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Model\Context;
use Magento\Framework\Registry;
use Magento\Store\Model\StoreManagerInterface;
use Monolog\Logger;

/**
 * Class Price
 * @package FiloBlu\Flow\Model\From
 * @method getSku()
 * @method getPaese()
 */
class Price extends AbstractFrom
{
    /**
     * @var ProductFactory
     */
    protected $_productFactory;
    /**
     * @var mixed
     */
    protected $_productAction;
    /**
     * @var mixed
     */
    protected $_configurableAction;
    /**
     * @var StoreManagerInterface
     */
    protected $_storeManager;
    /**
     * @var Data
     */
    protected $_helper_flow;

    /**
     * Price constructor.
     * @param Context $context
     * @param Registry $registry
     * @param Data $helper_flow
     * @param StoreManagerInterface $storeManager
     * @param ProductFactory $productFactory
     * @param array $data
     */
    public function __construct(
        Context               $context,
        Registry              $registry,
        Data                  $helper_flow,
        StoreManagerInterface $storeManager,
        ProductFactory        $productFactory,
        array                 $data = []
    )
    {
        $this->_helper_flow = $helper_flow;
        $this->_storeManager = $storeManager;
        $this->_productFactory = $productFactory;
        $this->_productAction = ObjectManager::getInstance()->get(Action::class);
        $this->_configurableAction = ObjectManager::getInstance()->create(Configurable::class);
        parent::__construct($context, $registry, null, null, $data);
    }

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

    /**
     * @return $this
     * @throws Exception
     */
    public function process()
    {
        // Floatval will return zero if fails (even with ctype_space)
        // With zero this process will skip the import
        $price = (float)($this->getData('prezzo'));
        $specialPrice = (float)($this->getData('special_price'));


        // Do not allow prices below zero
        $price = (max($price, 0));

        $priceImported = $this->setPriceByPriceAttributeName($price, 'price');
        $specialPriceImported = $this->setPriceByPriceAttributeName($specialPrice, 'special_price');

        $channelConfig = $this->getChannel()->getChannelConfig();

        if ($channelConfig->getAllowProcessZeroPrices()) {
            return $this;
        }

        // Write error only if both fails
        if (!$priceImported && !$specialPriceImported) {
            $message = sprintf("Price is zero or not valid! Skipping! product_code: '%s'", $this->getSku());
            $this->error(false, $message);
        }

        return $this;
    }

    /**
     * @param $prezzo
     * @param $price_name
     * @return $this
     * @throws Exception
     */
    public function setPriceByPriceAttributeName($prezzo, $price_name)
    {
        $productSku = $this->getData('sku');
        $productId = $this->_productFactory->create()->getIdBySku($productSku);

        if (!$productId) {
            $message = sprintf("Product not found! product_code: '%s'", $productSku);
            $this->error(false, $message);
        }

        if(!is_numeric($prezzo)) {
            return $this;
        }

        $channelConfig = $this->getChannel()->getChannelConfig();

        if (!$channelConfig->getAllowProcessZeroPrices() && $prezzo == 0) {
            return $this;
        }

        $paese = $this->getData('paese') ?? 'admin';

        $allStore = $this->_helper_flow->getStoreInWebsiteId();

        if (!isset($allStore[$paese]['store_id'])) {
            $this->_logger->warning("Filoblu_from_price: '$paese' does not exist");
            return $this;
        }

        $storeId = $allStore[$paese]['store_id'];

        $pids[] = $productId;

        // Salvo il prezzo sul prodotto configurabile padre
        $parentProductId = $this->_configurableAction->getParentIdsByChild($productId);

        if (!empty($parentProductId)) {
            $pids = array_merge($pids, $parentProductId);
        }

        try {
            // If special price is less or equal than zero then I need to remove it from Magento passing '' as value
            $prezzo = ($prezzo <= 0 ? '' : $prezzo);
            $this->_productAction->updateAttributes($pids, [$price_name => $prezzo], $storeId);
        } catch (Exception $e) {
            throw new Exception(
                sprintf(
                    "%s .Problem while processing price. Store Id '%s, Product Ids '%s',  Attribute data '%s'",
                    $e->getMessage(),
                    $storeId,
                    implode(',', $pids),
                    print_r($prezzo, true)
                )
            );
        }

        return $this;
    }

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