<?php

namespace MageArray\LowerPrice\Model;

/**
 * Class ManageCoupon
 * @package MageArray\LowerPrice\Model
 */
class ManageCoupon extends \Magento\Framework\Model\AbstractModel
{
    /**
     * @var \Magento\SalesRule\Helper\Coupon
     */
    protected $salesRuleCoupon;

    /**
     * ManageCoupon constructor.
     * @param \Magento\Framework\ObjectManagerInterface $objectmanager
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \MageArray\LowerPrice\Helper\Data $helper
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
     * @param \Magento\SalesRule\Helper\Coupon $salesRuleCoupon
     * @param \Magento\SalesRule\Model\CouponFactory $couponFactory
     * @param \Psr\Log\LoggerInterface $logger
     */
    public function __construct(
        \Magento\Framework\ObjectManagerInterface $objectmanager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \MageArray\LowerPrice\Helper\Data $helper,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
        \Magento\SalesRule\Helper\Coupon $salesRuleCoupon,
        \Magento\SalesRule\Model\CouponFactory $couponFactory,
        \Magento\Framework\Json\Helper\Data $jsonHelper,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->_objectManager = $objectmanager;
        $this->_storeManager = $storeManager;
        $this->helper = $helper;
        $this->_eventManager = $eventManager;
        $this->_dateFilter = $dateFilter;
        $this->salesRuleCoupon = $salesRuleCoupon;
        $this->couponFactory = $couponFactory;
        $this->jsonHelper = $jsonHelper;
        ;
        $this->logger = $logger;
    }

    /**
     * @return mixed
     */
    public function getWebsiteId()
    {
        return $this->_storeManager->getStore()->getWebsiteId();
    }

    /**
     * @param $post
     * @param $product
     * @return array|void
     */
    public function checkThresholdLimit($post, $product)
    {
        $newFigure = $post['price']; // user price
        $oldFigure = $post['product_price'];
        $amount = $oldFigure - $newFigure;

        if ($product->getAutoApprovedInquiries()) {

            $priceType = $product->getThresholdPriceType() != '' ?
                $product->getThresholdPriceType() : $this->helper->getPriceType();
            $thresholdPrice = $product->getThresholdLimit() > 0 ?
                $product->getThresholdLimit() : $this->helper->getThresholdPrice();
            $createRule = true;
        } else {
            $priceType = $this->helper->getPriceType();
            $thresholdPrice = $this->helper->getThresholdPrice();
            $createRule = false;
        }

        if ($priceType == 'percentage') {
            $finalAmount = ((1 - $newFigure / $oldFigure) * 100);
        } else {
            $finalAmount = $oldFigure - $newFigure;
        }

        if ($thresholdPrice >= $finalAmount &&
            $oldFigure > $newFigure &&
            $finalAmount != 0 &&
            $createRule == true
        ) {
            return $this->createCartPriceRules($amount, $product); // Create Coupon code here
        } else {
            return ['', $amount];
        }
    }

    /**
     * @param $amount
     * @return array|void
     */
    public function createCartPriceRules($amount, $product)
    {
        try {
            $model = $this->_objectManager->create(\Magento\SalesRule\Model\Rule::Class);

            $data = $this->getRuleData($amount, $product);
            /* $this->_eventManager->dispatch(
                'adminhtml_controller_salesrule_prepare_save',
                ['request' => $data]
            ); */

            /* $inputFilter = new \Zend_Filter_Input(
                ['from_date' => $this->_dateFilter, 'to_date' => $this->_dateFilter],
                [],
                $data
            );
            $data = $inputFilter->getUnescaped();
            $validateResult = $model->validateData(new \Magento\Framework\DataObject($data));
            if ($validateResult !== true) {
                foreach ($validateResult as $errorMessage) {
                    $this->messageManager->addError($errorMessage);
                }
                return;
            } */

            $model->setData($data);
            $model->save();

            $code = $this->codeGenerator(
                [
                    'rule_id' => $model->getRuleId(),
                    'qty' => 1,
                    'length' => 12,
                    'format' => 'alphanum',
                    'prefix' => '',
                    'suffix' => '',
                    'dash' => 0,
                ]
            );

            $code[] = $amount;
            return $code;
        } catch (\Exception $e) {
            $this->logger->info($e->getMessage());
        }
    }

    /**
     * @param $amount
     * @return array
     */
    public function getRuleData($amount, $product)
    {
        $groupOptions = $this->_objectManager->create(\Magento\Customer\Model\ResourceModel\Group\Collection::Class)
            ->toOptionArray();
        $groupIds = [];
        foreach ($groupOptions as $group) {
            $groupIds[] = $group['value'];
        }

        $fromDate = date('Y-m-d H:i:s');
        $days = $this->helper->getCouponExpiryDays() > 1 ? $this->helper->getCouponExpiryDays() : 1;
        $toDate = date('Y-m-d H:i:s', strtotime($fromDate . " +$days day"));

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $productMetadata = $objectManager->get(\Magento\Framework\App\ProductMetadataInterface::Class);
        $version = $productMetadata->getVersion();
        
        if (version_compare($version, '2.2', '>=')) {
            $conditionsSerialized = json_encode($this->getConditionsSerialized($product->getSku()));
            $actionsSerialized = json_encode($this->getActionsSerialized($product->getSku()));
        } else {
            $conditionsSerialized = \Magento\Framework\Serialize\SerializerInterface::serialize($this->getConditionsSerialized($product->getSku()));//phpcs:ignore
            $actionsSerialized = \Magento\Framework\Serialize\SerializerInterface::serialize($this->getActionsSerialized($product->getSku()));//phpcs:ignore
        }
        
        return [
            'is_active' => 1,
            'stop_rules_processing' => 0,
            'use_auto_generation' => 1, //0,
            'uses_per_coupon' => 1,
            'uses_per_customer' => 1,
            'is_rss' => 1,
            'is_advanced' => 1,
            'coupon_type' => 2,
            'coupon_code' => '',
            'name' => 'lower_price_code',
            'simple_action' => 'by_fixed',
            'discount_amount' => $amount,
            'website_ids' => [$this->getWebsiteId()],
            'customer_group_ids' => $groupIds,
            'from_date' => $fromDate,
            'to_date' => $toDate,
            'conditions_serialized' => $conditionsSerialized,
            'actions_serialized' => $actionsSerialized,
        ];
    }

    /**
     * @param $sku
     * @return mixed
     */
    public function getConditionsSerialized($sku)
    {
        $conditions = [
            'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::Class,
            'attribute' => '',
            'operator' => '',
            'value' => '1',
            'is_value_processed' => '',
            'aggregator' => 'all',
            'conditions' =>
                [
                    [
                        'type' => \Magento\SalesRule\Model\Rule\Condition\Product\Found::Class,
                        'attribute' => '',
                        'operator' => '',
                        'value' => '1',
                        'is_value_processed' => '',
                        'aggregator' => 'all',
                        'conditions' =>
                            [
                                [
                                    'type' => \Magento\SalesRule\Model\Rule\Condition\Product::Class,
                                    'attribute' => 'sku',
                                    'operator' => '==',
                                    'value' => $sku,
                                    'is_value_processed' => ''
                                ]
                            ]
                    ]
                ]
        ];
        return $conditions;
    }
    
    /**
     * @param $data
     * @return mixed
     */
    public function getActionsSerialized($sku)
    {
        $conditions = [
          "type" => \Magento\SalesRule\Model\Rule\Condition\Product\Combine::Class,
          "attribute" => '',
          "operator" => '',
          "value" => "1",
          "is_value_processed" => '',
          "aggregator" => "all",
          "conditions" => [
            [
              "type" => \Magento\SalesRule\Model\Rule\Condition\Product::Class,
              "attribute" => "sku",
              "operator" => "==",
              "value" => $sku,
              "is_value_processed" => false
            ]
          ]
        ];
        return $conditions;
    }

    /**
     * @param $data
     * @return mixed
     */
    public function codeGenerator($data)
    {
        $generator = $this->_objectManager->get(\Magento\SalesRule\Model\Coupon\Massgenerator::Class);
        if (!$generator->validateData($data)) {
            $this->logger->info('Invalid data provided');
        } else {
            $generator->setData($data);
            $generator->generatePool();
            return $generator->getGeneratedCodes();
        }
    }

    /**
     * @param $code
     * @return mixed
     */
    public function loadCouponByCode($code)
    {
        return $this->couponFactory->create()->load($code, 'code');
    }

    /**
     * @return string
     */
    public function generateCode()
    {
        $format = $this->getFormat();
        if (empty($format)) {
            $format = \Magento\SalesRule\Helper\Coupon::COUPON_FORMAT_ALPHANUMERIC;
        }

        $splitChar = '-';
        $charset = $this->salesRuleCoupon->getCharset($format);

        $code = '';
        $charsetSize = count($charset);
        $split = 0;
        $length = 16;
        for ($i = 0; $i < $length; ++$i) {
            $char = $charset[\Magento\Framework\Math\Random::getRandomNumber(0, $charsetSize - 1)];
            if (($split > 0) && (($i % $split) === 0) && ($i !== 0)) {
                $char = $splitChar . $char;
            }
            $code .= $char;
        }

        return $this->getPrefix() . $code . $this->getSuffix();
    }
}
