<?php
/**
 * Copyright 2018-2019 © Intelligent IT SRL. All rights reserved.
 */

namespace Leadlion\SmartBill\Helper;
use Magento\Framework\App\Helper\Context;
use Magento\Directory\Model\CountryFactory;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Framework\App\ProductMetadata;
use Magento\Catalog\Model\ProductRepository;
use Magento\Quote\Model\Quote\Item as QuoteItem;

use SmartBill\Integration\Helper\Settings;
use SmartBill\Integration\Model\ANAFAPIClient;
use Leadlion\Autogedal\Helper\Data;

class DataOrder extends \SmartBill\Integration\Helper\DataOrder
{
    private $quoteItemFactory;
    private $customHelper;

    private $productMU = null;
    public OrderRepositoryInterface $orderRepository;
    public ProductRepository $productRepository;

    public function __construct(
        Context $context,
        CountryFactory $countryFactory,
        Settings $settings,
        ANAFAPIClient $anafClient,
        ProductMetadata $magentoInfo,
        OrderRepositoryInterface $orderRepository,
        ProductRepository $productRepository,
        QuoteItem $quoteItemFactory,
        Data $customHelper
    ) {
        parent::__construct($context, $countryFactory, $settings, $anafClient, $magentoInfo, $orderRepository);
        $this->orderRepository = $orderRepository;
        $this->productRepository = $productRepository;
        $this->quoteItemFactory = $quoteItemFactory;
        $this->customHelper = $customHelper;
    }

    /**
     * @return array
     */
    private function getProductMUs(): array
    {
        if (!$this->productMU) {
            $this->productMU = $this->getInvoiceItemsMeasureUnits();
        }
        return $this->productMU;
    }

    //returns Magento\Sales\Model\Order
    public function getMagentoOrder($orderId = null)
    {
        if (is_numeric($orderId)) return $this->orderRepository->get($orderId);
        //se poate ajunge sa se paseze direct un obiect
        else if (!$orderId) {
            return $orderId;
        } else return false;

    }

    /**
     * Functia construieste array-ul necesar pentru entitatea client, care va fi pasat catre SmartBill Cloud API
     *
     * @return array $smartBillClient
     * @throws \Exception
     */
    public function buildSmartBillClientDetails($orderId = null)
    {

        if (is_numeric($orderId)) {
            $order = $this->getMagentoOrder($orderId);
        } else if ($orderId) {
            $order = $orderId;
            $orderId = $order->getId();
        }
        $billingAddress = $order->getBillingAddress();

        $smartBillClient = $this->buildSmartBillClientDetailsByAddress($billingAddress);
        return $smartBillClient;

    }

    /**
     * Functia construieste array-ul necesar pentru entitatea client, care va fi pasat catre SmartBill Cloud API
     *
     * @return array $productData
     */
    public function buildProductData($orderId = null, $taxDetails = null)
    {
        if (is_numeric($orderId)) {
            $order = $this->getMagentoOrder($orderId);
        } else if ($orderId) {
            $order = $orderId;
            $orderId = $order->getId();
        } else {
            return false;
        }
        $smartBillItems = null;

        $items = $order->getAllItems();
        foreach ($items as $item) {
            if ($item->getProductType() == 'bundle') {
                continue;
            }
            // if ($item->getParentItem()) {
            //     //skip produse cu parents
            //     continue;
            // }
            //if ($item->getBasePrice() > 0 ){
            //verificam sa fie mai mare decat zero, mai ales pentru calcularea discount-ului
            //sau pentru calcularea cotei TVA in caz ca este setata sa vina din Magento
            $smartBillItem = $this->buildOrderItem($item, $taxDetails);
            $smartBillItems[] = $smartBillItem;
            if ((float)$item->getDiscountAmount() > 0) {
                $discountItem = $this->buildDiscountItem($item, $taxDetails);
                $smartBillItems[] = $discountItem;
            }
            //}
        }
        $includeTransport = $taxDetails['includeTransport'];

        if ($includeTransport) {
            $transportItem = $this->buildOrderTransportData($order, $taxDetails);
            if ($transportItem) $smartBillItems[] = $transportItem;
            else throw new \Exception(__("Eroare la includerea transportului in factura."));

        }
        return $smartBillItems;

    }

    /**
     * Functia construieste datele necesare pentru o inregistrare in produse
     *
     * @return bool
     */
    public function buildOrderItem($item, $taxDetails)
    {
        if (!$item || !$taxDetails) throw new \Exception(__("Date invalide furnizate in momentul citirii inregistrarilor din Magento"));
        $product = $this->getProduct($item);
        $um = '';
        if ($product) {
            $um = $item->getProduct()->getData('measuringUnitName');
        }
        if (!$um) {
            $um = $taxDetails['measuringUnitName'];
        }

        $productMU = $this->getProductMUs();

        $sku = $product->getSku();
        $skuFz = $product->getSkuFz();
        $liveMeasureUnits = array_filter(
            $productMU,
            static function ($key) use ($sku, $skuFz)
            {
                return(strpos($key, $sku) !== false || strpos($key, $skuFz) !== false);
            },
            ARRAY_FILTER_USE_KEY
        );

        if (count($liveMeasureUnits) && !in_array($um, $liveMeasureUnits)) {
            $um = current($liveMeasureUnits) ?? $um;
        }

        $result['name'] = $product->getSkuFz(). ' | '.$item->getName();
        $result['code'] = $product->getSkuFz();
        $result['isDiscount'] = false;
        $result['measuringUnitName'] = $um ?: 'BUC';
        $result['currency'] = isset($taxDetails['currency']) ? $taxDetails['currency'] : 'RON';
        $result['quantity'] =  $item->getQtyOrdered();

        $customPrice = $item->getBuyRequest()->getCustomPrice();
        if ($customPrice) {
            $result['price'] = round($customPrice, 2);
            $result['isTaxIncluded'] = true;
        } elseif (isset($taxDetails['isTaxIncluded']) && $taxDetails['isTaxIncluded'] && $item->getDiscountAmount() > 0) {
            $result['price'] = round($item->getPriceInclTax(),2);
            $result['isTaxIncluded'] = true;
        } elseif (isset($taxDetails['isTaxIncluded']) && $taxDetails['isTaxIncluded']) {
            $result['price'] = round($item->getRowTotalInclTax()/$item->getQtyOrdered(),2);
            $result['isTaxIncluded'] = true;
        } else {
            $result['price'] = round($item->getBasePrice(), 2);
            $result['isTaxIncluded'] = false;
        }
        $taxNameDetails = $this->getTaxNameDetailsForItem($item, $taxDetails);
        $result['taxName'] = $taxNameDetails['taxName'];
        $result['taxPercentage'] = $taxNameDetails['taxPercentage'];
        if (isset($taxDetails['useStock']) && $taxDetails['useStock']) {
            $attributeSetsIds = $this->customHelper->getAttributesSetsIdsForShowingSku() ?
                                    explode(',', $this->customHelper->getAttributesSetsIdsForShowingSku()) : [];
            if (!in_array($product->getSku(), ['HV0899','M0420-01']) &&
                (
                    in_array($product->getAttributeSetId(), $attributeSetsIds) ||
                    in_array($product->getSku(), ['158005','160675','160661','160850','160514-2','160514-3','160514-4'])
                )
            ) {
                $result['warehouseName'] = "BARE TRANSVERSALE";
            } elseif ($product->getAttributeText('manufacturer') == 'ART') {
                $result['warehouseName'] = "PARAVANTURI AUTO";
            } else {
                $result['warehouseName'] = $taxDetails['warehouseName'];
            }
        }

        $result['isService'] = isset($taxDetails['isService']) ? $taxDetails['isService'] : false;
        $result['saveToDb'] = isset($taxDetails['saveProductToDb']) ? $taxDetails['saveProductToDb'] : false;
        return $result;
    }

    /**
     * Functia returneaza obiectul care determina daca factura este deja platita la emitere, conform setarilor din baza
     * de date
     *
     * @return array
     */
    public function buildOrderAlreadyPaidData($orderId = null, $taxDetails = null)
    {
        //util pentru teste
        if (is_numeric($orderId)) {
            $order = $this->getMagentoOrder($orderId);
        } else if ($orderId) {
            $order = $orderId;
            $orderId = $order->getId();
        }

        $value = $order->getBaseGrandTotal();
        $data = [];
        $data['value'] = $value;
        $data['paymentSeries'] = $taxDetails['paymentSeries'];
        $data['type'] = $taxDetails['paymentType'];
        $data['isCash'] = false;
        return $data;
    }

    /**
     * Functia returneaza valorile necesare pentru includerea transportului
     *
     * @return array|null
     */
    public function buildOrderTransportData($order = null, $taxDetails = null)
    {
        if (!$order || !$taxDetails) return null;
        $result['name'] = $taxDetails['transportLabel'] ? $taxDetails['transportLabel'] : 'Transport';
        $result['code'] = 'Transport';
        $result['isDiscount'] = false;
        //$result['measuringUnitName'] = isset($taxDetails['measuringUnitName']) ? $taxDetails['measuringUnitName'] : 'buc';
        $result['measuringUnitName'] = 'BUC';
        $result['currency'] = isset($taxDetails['currency']) ? $taxDetails['currency'] : 'RON';
        $result['quantity'] = 1;
        //inclusiv tax si apoi setam taxIncluded
        $priceWithTax =  round($order->getShippingInclTax(),2);
        $result['price'] = $priceWithoutTax = round($order->getShippingInclTax(),2);
        $result['isTaxIncluded'] = isset($taxDetails['isTransportTaxIncluded']) ? $taxDetails['isTransportTaxIncluded'] : false;

        //suprascriere valori pentru a returna cota TVA pentru transport
        $taxDetails['taxName'] = $taxDetails['transportTaxName'];
        $taxDetails['taxPercentage'] = $taxDetails['transportTaxPercentage'];
        $taxNameDetails = $this->getTaxNameDetailsForValues($priceWithTax, $priceWithoutTax, $taxDetails);
        $result['taxName'] = $taxNameDetails['taxName'];
        $result['taxPercentage'] = $taxNameDetails['taxPercentage'];
        $result['isService'] = true;
        $result['saveToDb'] = false;
        return $result;

    }
    public function getProductBySku($sku)
	{
		return $this->productRepository->get($sku);
	}

    public function getProduct($item)
    {
        return $this->productRepository->getById($item->getProductId());
    }

    public function getInvoiceItemsMeasureUnits($data = [])
    {
        $finalValues = [];
        try{
            $connector = $this->getSmartBillConnector();
            $data += [
                "cif" => $this->settings->getSettingsValue(Settings::VAT_SETTINGS_KEY),
                "date" => date('Y-m-d'),
                "warehouseName" => $this->settings->getSettingsValue(Settings::INVOICE_WHICH_STOCK_SETTINGS_KEY)
            ];
            $items = $connector->productsStock($data);
            foreach($items[0]['products'] as $item) {
                $finalValues[$item['productName']] = $item['measuringUnit'];
                if (!empty($item['productCode'])) {
                    $finalValues[$item['productCode']] = $item['measuringUnit'];
                }
            }
            return $finalValues;

        }
        catch (\Exception $e){
            $this->_logger->error($e->getMessage(), ['exception' => $e]);
            return $finalValues;
        }
    }
}


