<?php
/**
 * Webkul Software.
 *
 * @category  Webkul
 * @package   Webkul_MpPayPal
 * @author    Webkul
 * @copyright Copyright (c) Webkul Software Private Limited (https://webkul.com)
 * @license   https://store.webkul.com/license.html
 */
namespace Webkul\MpPayPal\Helper;

use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Customer\Model\Session;
use Magento\Framework\Data\Form\FormKey\Validator as FormKeyValidator;
use Magento\Framework\Pricing\PriceCurrencyInterface;

/**
 * Stripe data helper.
 */
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
    const METHOD_CODE = \Webkul\MpPayPal\Model\Ui\ConfigProvider::CODE;

    /**
     * @var Magento\Framework\Stdlib\DateTime\DateTime
     */
    protected $_date;

    /**
     * Customer session.
     *
     * @var \Magento\Customer\Model\Session
     */
    protected $_customerSession;

    /**
     * @var ObjectManagerInterface
     */
    protected $_objectManager;

    /**
     * @var \Magento\Framework\Data\Form\FormKey\Validator
     */
    protected $_formKeyValidator;

    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;

    /**
     * @var \Magento\Catalog\Api\ProductRepositoryInterface
     */
    protected $_productRepository;

    /**
     * @var \Magento\Directory\Model\Config\Source\Country
     */
    protected $_country;

    /**
     * @var \Magento\Directory\Model\RegionFactory
     */
    protected $_regionFactory;

    /**
     * $_newvar variable to check if seller shipping used.
     *
     * @var string
     */
    protected $_newvar;
    
    /**
     * @param Magento\Framework\App\Helper\Context        $context
     * @param Magento\Directory\Model\Currency            $currency
     * @param Magento\Customer\Model\Session              $customerSession
     * @param Magento\Framework\UrlInterface              $url
     * @param Magento\Catalog\Model\ResourceModel\Product $product
     * @param Magento\Store\Model\StoreManagerInterface   $_storeManager
     */
    public function __construct(
        Session $customerSession,
        \Magento\Framework\App\Helper\Context $context,
        FormKeyValidator $formKeyValidator,
        DateTime $date,
        \Magento\Framework\ObjectManagerInterface $objectManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        \Webkul\Marketplace\Model\ResourceModel\Product\CollectionFactory $sellerProductCollectionFactory,
        \Webkul\Marketplace\Model\ResourceModel\Saleperpartner\CollectionFactory $saleperpartnerCollectionFactory,
        \Webkul\Marketplace\Helper\Data $marketplaceHelperData,
        \Magento\Directory\Model\Config\Source\Country $country,
        \Magento\Framework\Json\Helper\Data $jsonHelper,
        \Magento\Framework\Pricing\PriceCurrencyInterface $priceInterface,
        \Magento\Framework\Session\SessionManager $sessionManager,
        \Magento\Quote\Model\Quote\Item\Option $options,
        \Webkul\Marketplace\Model\ProductFactory $mpProductFactory,
        \Magento\Framework\App\ProductMetadataInterface $productMetadata,
        PriceCurrencyInterface $priceCurrency,
        \Webkul\MpPayPal\Logger\Logger $logger,
        \Magento\Framework\Event\Manager $eventmanager,
        \Magento\Shipping\Model\Config $shippingConfig,
        \Magento\Customer\Model\CustomerFactory $customerFactory,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Directory\Model\RegionFactory $regionFactory
    ) {
        $this->_date = $date;
        $this->_customerSession = $customerSession;
        $this->priceInterface = $priceInterface;
        $this->eventmanager = $eventmanager;
        $this->_objectManager = $objectManager;
        $this->shippingConfig = $shippingConfig;
        $this->sessionManager = $sessionManager;
        $this->mpProductFactory = $mpProductFactory;
        $this->options = $options;
        $this->_formKeyValidator = $formKeyValidator;
        $this->_storeManager = $storeManager;
        $this->_productRepository = $productRepository;
        $this->_sellerProductCollectionFactory = $sellerProductCollectionFactory;
        $this->_saleperpartnerCollectionFactory = $saleperpartnerCollectionFactory;
        $this->_marketplaceHelperData = $marketplaceHelperData;
        $this->_country  = $country;
        $this->_productMetadata = $productMetadata;
        $this->_regionFactory = $regionFactory;
        $this->jsonHelper = $jsonHelper;
        $this->_priceCurrency = $priceCurrency;
        $this->customerFactory = $customerFactory;
        $this->logger = $logger;
        $this->checkoutSession = $checkoutSession;
        parent::__construct($context);
    }

    public function logDataInLogger($data)
    {
        $this->logger->info($data);
    }

    /**
     * [getAssignSellerId function to get assign seller id from order item.
     *
     * @param object $item
     *
     * @return int
     */
    public function getAssignSellerId($item)
    {
        // Get Info Buy Request from quote item,
        $itemOption = $this->options
            ->getCollection()
            ->addFieldToFilter('item_id', $item->getId())
            ->addFieldToFilter('code', 'info_buyRequest');

        foreach ($itemOption as $option) {
            $info = $option->getValue();
        }
        
        $info = $this->jsonHelper->jsonDecode($info, true);

        //Get mpassignproduct_id from $info
        $assignId = 0;
        $sellerId = 0;
        if (is_array($info)) {
            if (array_key_exists('mpassignproduct_id', $info)) {
                $assignId = $info['mpassignproduct_id'];
                $mpassignModel = $this->_objectManager
                    ->create(\Webkul\MpAssignProduct\Model\Items::class)
                    ->load($assignId);
                $sellerId = $mpassignModel->getSellerId();
            }
        }
        return $sellerId;
    }

    /**
     * getSellerDetail get seller commission details
     *
     * @param  string $sellerId
     * @return array
     */
    public function getSellerDetail($sellerId = '')
    {
        if ($sellerId) {
            $sellerdetails = $this->_saleperpartnerCollectionFactory
                ->create()
                ->addFieldToFilter('seller_id', $sellerId);
            if (count($sellerdetails)) {
                foreach ($sellerdetails as $temp) {
                    if ($temp->getCommissionRate() > 0) {
                        return [
                            'id' => $temp->getSellerId(),
                            'commission' => $temp->getCommissionRate(),
                        ];
                    } else {
                        return [
                            'id' => $temp->getSellerId(),
                            'commission' => $this->_marketplaceHelperData->getConfigCommissionRate(),
                        ];
                    }
                }
            } else {
                return [
                    'id' => $sellerId,
                    'commission' => $this->_marketplaceHelperData->getConfigCommissionRate(),
                ];
            }
        } else {
            return ['id' => 0,'commission' => 0];
        }
    }

    /**
     * create final cart for seller
     *
     * @param \Magento\Sales\Model\Order $order
     * @return array
     */
    public function createFinalCart($quoteData)
    {
        if ($quoteData) {
            $order = $quoteData;
            $cart = $this->getSellerCart($order);
            usort($cart, function ($a, $b) {
                // compare seller id(s)
                return $a['data']['seller_id'] - $b['data']['seller_id'];
            });
            $commission = 0;
            /**
             * $orderShippingTaxAmount get shipping tax amount if any.
             *
             * @var decimal
             */
            $orderShippingTaxAmount = $order->getShippingAddress()
              ->getData('shipping_tax_amount');
            $finalcart = [];
            $i = 0;
            $adminTaxAmount = 0;
            
            foreach ($cart as $item) {
                $accessToken = '';
                $publishKey = '';
                $temp = $item['data'];
                $commission += $temp['commission'];
                $paypalSubMerchantId = '';
                if ($temp['seller_id'] != 0) {
                    $paypalSubMerchantId = $this->getSubmerchantId($temp['seller_id']);
                }
                
                $adminTaxAmount += $temp['tax_amount'];
                
                if ($i == 0) {
                    $finalcart[$i]['shippingprice'] = $temp['shipping_price'];
                    $finalcart[$i]['commission'] = $temp['commission'];
                    $finalcart[$i]['price'] = $temp['price'];
                    $finalcart[$i]['qty'] = $temp['qty'];
                    $finalcart[$i]['products'] = $temp['product_id'];
                    $finalcart[$i]['taxamount'] = $temp['tax_amount'];
                    $finalcart[$i]['seller'] = $temp['seller_id'];
                    $finalcart[$i]['sub_merchant_id'] = $paypalSubMerchantId;
                    $finalcart[$i]['discount'] = $temp['discount_amount'];
                    ++$i;
                } else {
                    if ($temp['seller_id'] == $finalcart[$i - 1]['seller']) {
                        $finalcart[$i - 1]['price'] =
                        $this->priceInterface->round(
                            $finalcart[$i - 1]['price'] + $temp['price']
                        );

                        $finalcart[$i - 1]['commission'] = $finalcart[$i - 1]['commission'] + $temp['commission'];
                        $finalcart[$i - 1]['products'] =
                        $finalcart[$i - 1]['products'].','.$temp['product_id'];

                        $finalcart[$i - 1]['taxamount'] =
                        $finalcart[$i - 1]['taxamount'] +
                        $temp['tax_amount'];
                    } else {
                        $finalcart[$i]['shippingprice'] = $temp['shipping_price'];
                        $finalcart[$i]['commission'] = $temp['commission'];
                        $finalcart[$i]['price'] = $temp['price'];
                        $finalcart[$i]['qty'] = $temp['qty'];
                        $finalcart[$i]['products'] = $temp['product_id'];
                        $finalcart[$i]['taxamount'] = $temp['tax_amount'];
                        $finalcart[$i]['seller'] = $temp['seller_id'];
                        $finalcart[$i]['sub_merchant_id'] = $paypalSubMerchantId;
                        $finalcart[$i]['discount'] = $temp['discount_amount'];
                        ++$i;
                    }
                }
            }
            
            $status = 0;
            $index = 0;
            $counter = 0;
            foreach ($finalcart as $cart) {
                if (!isset($cart['seller']) || $cart['seller'] == 0) {
                    $status = 1;
                    $index = $counter;
                }
                ++$counter;
            }

            $quoteshipPrice = 0;
            if ($this->_newvar != 'webkul') {
                $quoteshipPrice = $order->getShippingAddress()->getBaseShippingAmount();
            }

            /**
             * if admin product
             */
            if ($status == 1) {
                $finalcart[$index]['price'] =
                $finalcart[$index]['price'] + $quoteshipPrice;

                $finalcart[$index]['shippingprice'] =
                $finalcart[$index]['shippingprice'] +
                $quoteshipPrice;
            } else {
                $marketplaceHelper = $this->_marketplaceHelperData;
                /**
                 * if tax to admin or admin shipping both are set
                 */
                if (!$marketplaceHelper->getConfigTaxManage() || $quoteshipPrice != 0) {
                    /**
                     * if admin shipping is used
                     */
                    if ($this->_newvar == '') {
                        $finalcart[$counter]['price'] =
                        $this->_priceCurrency->round(
                            $quoteshipPrice + $orderShippingTaxAmount
                        );
                    } elseif ($orderShippingTaxAmount !== 0) {
                        $finalcart[$counter]['price'] = $orderShippingTaxAmount;
                    } else {
                        $finalcart[$counter]['price'] = 0;
                    }

                    $finalcart[$counter]['seller'] = 0;
                    if (!$marketplaceHelper->getConfigTaxManage()) {
                        $finalcart[$counter]['price'] =  $this->_priceCurrency->round(
                            $finalcart[$counter]['price']+$order->getBaseTaxAmount()
                        );
                    }

                    $finalcart[$counter]['products'] = null;
                }
            }
        }

        return $finalcart;
    }

    /**
     * get submerchant id of transaction
     *
     * @param int $sellerId
     * @return string
     */
    public function getSubmerchantId($sellerId)
    {
        if ($sellerId) {
            $seller = $this->customerFactory->create()->load($sellerId);
            $merchantStatus = $seller->getMppaypalMerchantStatus();
            if ($seller->getMppaypalSubmerchantId() && $merchantStatus) {
                return $seller->getMppaypalSubmerchantId();
            } elseif ($seller->getMppaypalSubmerchantId()) {
                return $seller->getMppaypalSubmerchantId();
            }
        }
        return '';
    }

    /**
     * create seller wise cart data
     *
     * @param object $order
     * @return array
     */
    private function getSellerCart($order)
    {
        $finalCart = [];
        if ($order) {
            $cartItems = $order->getAllVisibleItems();
            $cart = [];
            $i = 0;
            $orderShippingTaxAmount = 0;
            $orderShippingAmount = 0;
            $customerAddressId = 0;
            $sellerId = 0;
            $commissionDetail = [];
            if (!empty($order->getShippingAddress())) {
                /**
                 * $shipmeth shipping method code.
                 *
                 * @var string
                 */
                $shipmeth = $order->getShippingAddress()->getShippingMethod();
                /**
                 * $orderShippingTaxAmount get shipping tax amount if any.
                 *
                 * @var decimal
                 */
                $orderShippingTaxAmount = $order->getShippingAddress()
                    ->getData('shipping_tax_amount');

                /**
                 * $orderShippingAmount order shipping amount.
                 *
                 * @var decimal
                 */
                $orderShippingAmount = $order->getShippingAddress()
                    ->getBaseShippingAmount();

                /**
                 * $customerAddressId customer shipping address id.
                 *
                 * @var int
                 */
                $customerAddressId = $order->getShippingAddress()
                    ->getCustomerAddressId();
            } else {
                /**
                 * $shipmeth if shipping address not set them shipping method is none.
                 */
                $shipmeth = '';
                /**
                 * [$customerAddressId billing address id.
                 */
                $customerAddressId = $order->getBillingAddress()
                    ->getCustomerAddressId();
            }
            /**
             * $customerAddressId if no shipping address id found then get billing address id.
             */
            if ($customerAddressId == null) {
                $customerAddressId = $order->getBillingAddress()
                    ->getCustomerAddressId();
            }
           
            $methods = $this->shippingConfig->getActiveCarriers();
            $options = [];
            $allmethods = [];
            $shipinf = [];
            foreach ($methods as $_code => $_method) {
                array_push($allmethods, $_code);
            }

            /**
             * $shipmeth if marketplace multishipping is set then seller wise shipping amount.
             */
            if ($shipmeth == 'mp_multi_shipping_mp_multi_shipping') {
                $this->_newvar = 'webkul';
                /**
                 * $shippinginfo get multi shipping details from sesssion.
                 *
                 * @var array
                 */
                $shippinginfo = $this->sessionManager->getData(
                    'selected_shipping'
                );
                foreach ($shippinginfo as $key => $val) {
                    $shipinf[] = ['seller' => $key,'amount' => $val['amount']];
                }
            } else {
                $shipmethod = explode('_', $shipmeth, 2);
                /**
                 * $shippinginfo get shipping info details from session no multi shipping.
                 *
                 * @var array
                 */
                $shippinginfo = $this->sessionManager->getShippingInfo();
                /*
                 * create seller wise shipping details array
                 */
                if (in_array($shipmethod[0], $allmethods)) {
                    if (!empty($shippinginfo[$shipmethod[0]])) {
                        $shipinf[] = $this->createSellerWiseShipping($shippinginfo[$shipmethod[0]], $shipinf);
                    }
                }
            }
            /**
             * $marketplaceHelper get marketplace helper.
             *
             * @var Webkul\Marketplace\Helper\Data
             */
            $marketplaceHelper = $this->_marketplaceHelperData;
            /*
             * dispatch event for advance commission module
             */
            $this->eventmanager->dispatch(
                'mp_advance_commission_rule',
                ['order' => $order]
            );

            /**
             * $advanceCommissionRule advance commssion rule from session if set.
             */
            $advanceCommissionRule = $this->_customerSession->getData(
                'advancecommissionrule'
            );

            /*
             * iterate through cart items to create seller wise payment details
             */
            foreach ($cartItems as $item) {
                $invoiceprice = 0;
                $itemId = $item->getProductId();
                $sellerId = 0;
                /**
                 * $assignSellerId variable to store assign seller id.
                 *
                 * @var int
                 */
                $assignSellerId = $this->getAssignSellerId($item);

                $seller = $this->mpProductFactory->create()->getCollection();

                /*
                 * check if assign seller id exists then add filter for seller id else product id
                 */
                if ($assignSellerId) {
                    $sellerId = $assignSellerId;
                } else {
                    $seller->addFieldToFilter('mageproduct_id', $itemId);
                    if ($seller->getSize() > 0) {
                        foreach ($seller as $obj) {
                            $sellerId = $obj->getSellerId();
                        }
                    }
                }

                $tempcoms = 0;
                /*
                 * get advance commission rule
                 */
                if (!$marketplaceHelper->getUseCommissionRule()) {
                    /*
                     * dispatch event for the calculation of advance commission
                     */
                    $this->eventmanager->dispatch(
                        'mp_advance_commission',
                        ['id' => $itemId]
                    );
                    /**
                     * [$advancecommission get Advance commission from the session.
                     *
                     * @var decimal
                     */
                    $advancecommission = $this->_customerSession->getData(
                        'commission'
                    );
                    /*
                     * check if advance commission is set then calculate commission
                     */
                    if ($advancecommission != '') {
                        $percent = $advancecommission;
                        $commType = $marketplaceHelper->getCommissionType();
                        if ($commType == 'fixed') {
                            $tempcoms = $percent;
                        } else {
                            $tempcoms = ($item->getBaseRowTotal() * $advancecommission) / 100;
                        }
                        if ($tempcoms > $item->getBaseRowTotal()) {
                            $tempcoms = $item->getBaseRowTotal() * $marketplaceHelper->getConfigCommissionRate() / 100;
                        }

                        $commissionDetail['id'] = $sellerId;
                    }
                } else {
                    /*
                     * check if advance commission is not set then set calculate advance commission
                     */
                    if (count($advanceCommissionRule)) {
                        if ($advanceCommissionRule[$item->getId()]['type'] == 'fixed') {
                            $tempcoms = $advanceCommissionRule[$item->getId()]['amount'];
                        } else {
                            $tempcoms =
                                ($item->getRowTotal() * $advanceCommissionRule[$item->getId()]['amount']) / 100;
                        }

                        $commissionDetail['id'] = $sellerId;
                    }
                }

                /*
                 * if there is no advance commission then calculate normal commission
                 */
                if (!$tempcoms) {
                    $commissionDetail = $this->getSellerDetail($sellerId);

                    if ($commissionDetail['id'] !== 0
                        && $commissionDetail['commission'] !== 0
                    ) {
                        $tempcoms = $this->priceInterface->round(
                            ($item->getRowTotal() * $commissionDetail['commission']) / 100,
                            2
                        );
                    }
                }

                /**
                 * $price price after commission.
                 *
                 * @var decimal
                 */
                $price = $this->priceInterface->round($item->getBaseRowTotal());
                /**
                 * $invoiceprice row total of product.
                 *
                 * @var decimal
                 */
                $invoiceprice = $item->getBaseRowTotal();
                /**
                 * include tax amount if tax management done by seller
                 */
                if ($sellerId && $marketplaceHelper->getConfigTaxManage()) {
                    $price = $this->priceInterface->round($price+$item->getBaseTaxAmount());
                } elseif (!$sellerId) {
                    /**
                     * else tax managed by admin
                     */
                    $price = $this->priceInterface->round(
                        $item->getBaseRowTotal() + $item->getBaseTaxAmount() + $orderShippingTaxAmount
                    );
                }
                $shippingprice = 0;
                if ($this->_newvar == 'webkul') {
                    $custid = 0;

                    $custid = $sellerId;

                    foreach ($shipinf as $k => $key) {
                        if ($key['seller'] == $custid) {
                            $price = $price + $key['amount'];
                            $shippingprice = $key['amount'];
                            $shipinf[$k]['amount'] = 0;
                        }
                    }
                }
                /*
                 * create seller wise array for payment
                 */
                if ($orderShippingTaxAmount !== 0
                    && ($commissionDetail['id'] == 0)
                ) {
                    $this->_adminShipTaxAmt = 1;
                    $cart[$i]['data'] = [
                        'seller_id' => $commissionDetail['id'],
                        'commission' => $tempcoms,
                        'qty' => $item->getQty(),
                        'product_id' => $item->getProductId(),
                        'price' => $price,
                        'shipping_price' => $shippingprice,
                        'tax_amount' => $this->priceInterface->round(
                            $item->getBaseTaxAmount() + $orderShippingTaxAmount
                        ),
                        'discount_amount' => $this->priceInterface->round($item->getBaseDiscountAmount())
                    ];
                } else {
                    $cart[$i]['data'] = [
                        'seller_id' => $commissionDetail['id'],
                        'commission' => $tempcoms,
                        'qty' => $item->getQty(),
                        'product_id' => $item->getProductId(),
                        'price' => $price,
                        'shipping_price' => $shippingprice,
                        'tax_amount' => $item->getBaseTaxAmount(),
                        'discount_amount' => $this->priceInterface->round($item->getBaseDiscountAmount())
                    ];
                }
                ++$i;
            }
            return $cart;
        } else {
            throw new \Magento\Framework\Exception\LocalizedException(
                _(
                    'There was an error capturing the transaction: Please contact admin'
                )
            );
        }
    }

    /**
     * to get paypal merchant ids in cart.
     *
     * @return array
     */
    public function getSellerPayPalMerchantIds()
    {
        $quote = $this->checkoutSession->getQuote();
        $sellerMerchantIds = [];
        if ($quote) {
            $cartItems = $quote->getAllVisibleItems();

            /*
             * iterate through cart items to create seller wise payment details
             */
            foreach ($cartItems as $item) {
                $itemId = $item->getProductId();
                $sellerId = 0;

                /**
                 * $assignSellerId variable to store assign seller id.
                 *
                 * @var int
                 */
                $assignSellerId = $this->getAssignSellerId($item);

                $seller = $this->mpProductFactory->create()->getCollection();

                /*
                 * check if assign seller id exists then add filter for seller id else product id
                 */
                if ($assignSellerId) {
                    $sellerId = $assignSellerId;
                } else {
                    $seller->addFieldToFilter('mageproduct_id', $itemId);
                    if ($seller->getSize() > 0) {
                        foreach ($seller as $obj) {
                            $sellerId = $obj->getSellerId();
                        }
                    }
                }
                $sellerMerchantIds[] = $this->getSubmerchantId($sellerId);
            }
            return $sellerMerchantIds;
        }
    }
    
    public function createSellerWiseShipping($shippinginfo, $shipinf)
    {
        foreach ($shippinginfo as $key) {
            $this->_newvar = 'webkul';
            foreach ($key['submethod'] as $k => $v) {
                if ($k == $shipmethod[1]) {
                    $shipinf[] = [
                            'seller' => $key['seller_id'],
                            'amount' => $v['cost'],
                        ];
                }
            }
        }
        return $shipinf;
    }

    /**
     * get item discount amount
     *
     * @param Magento\Sales\Model\Order\Item $item
     * @return float
     */
    public function getItemDiscount($item)
    {
        //TO-DO calculate marketplace seller coupons discount
        if ($item->getBaseDiscountAmount() > 0) {
            return $item->getBaseDiscountAmount();
        }
        return 0;
    }

    public function checkSellerInCart()
    {
        $quote = $this->checkoutSession->getQuote();
        $quoteItems = $quote->getAllVisibleItems();
        $sellerIds = [];
        foreach ($quoteItems as $item) {
            $invoiceprice = 0;
            $itemId = $item->getProductId();
            
            /**
             * $assignSellerId variable to store assign seller id.
             *
             * @var int
             */
            $assignSellerId = $this->getAssignSellerId($item);

            $seller = $this->mpProductFactory->create()->getCollection();

            /*
             * check if assign seller id exists then add filter for seller id else product id
             */
            if ($assignSellerId) {
                $sellerIds[] = $assignSellerId;
            } else {
                $seller->addFieldToFilter('mageproduct_id', $itemId);
                if ($seller->getSize() > 0) {
                    foreach ($seller as $obj) {
                        $sellerIds[] = $obj->getSellerId();
                    }
                }
            }
        }
        if (!empty($sellerIds)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * set quote for guest checkout order submit
     *
     * @return void
     */
    public function setGuestQuote($quote)
    {
        $quote->setCustomerId(null)
            ->setCustomerEmail($quote->getBillingAddress()->getEmail())
            ->setCustomerIsGuest(true)
            ->setCustomerGroupId(\Magento\Customer\Model\Group::NOT_LOGGED_IN_ID);
    }
}
