<?php


namespace Oney\ThreeByFour\Gateway\Request;


use Magento\Checkout\Model\Session;
use Magento\Directory\Model\Country;
use Magento\Framework\Filter\FilterManager;
use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Quote\Api\Data\CartInterfaceFactory;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Sales\Api\Data\OrderInterfaceFactory;
use Oney\ThreeByFour\Helper\Config;
use Oney\ThreeByFour\Logger\Logger;

class PurchaseDataBuilder implements BuilderInterface
{
    /**
     * @var Config
     */
    protected $_helperConfig;
    /**
     * @var Logger
     */
    protected $_logger;
    /**
     * @var Session
     */
    protected $_checkoutSession;
    /**
     * @var Country
     */
    protected $_country;
    /**
     * @var OrderRepositoryInterface
     */
    protected $orderRepository;

    public function __construct(
        Session $checkoutSession,
        Config $config,
        Logger $logger,
        Country $country,
        OrderRepositoryInterface $orderRepository
    )
    {
        $this->_helperConfig = $config;
        $this->_country = $country;
        $this->_logger = $logger;
        $this->_checkoutSession = $checkoutSession;
        $this->orderRepository = $orderRepository;
    }

    /**
     * @inheritDoc
     */
    public function build(array $buildSubject)
    {
        if (!isset($buildSubject['payment']) || !$buildSubject['payment'] instanceof PaymentDataObjectInterface) {
            throw new \InvalidArgumentException('Payment data object should be provided');
        }

        /** @var PaymentDataObjectInterface $payment */
        $payment = $buildSubject['payment'];
        $order = $payment->getOrder();
        $shippingAddress = $order->getShippingAddress();
        $this->_country->loadByCode($shippingAddress->getCountryId());
        $carrierCode = $this->getCarrierCode();
        $deliveryModeCode = $this->_helperConfig->getCarrierConfig($carrierCode, 'deliverymodecode');
        $expressDeliveryFlag = $this->_helperConfig->getCarrierConfig($carrierCode, 'expressdeliveryflag');
        $orderFullPrice = 0;

        $itemList = [];
        $maxPrice = 0;
        $qtyOrdered = 1;

        foreach ($order->getItems() as $item) {
            if ($item->getParentItem()) continue;
            if ($maxPrice < $item->getPriceInclTax()) $maxPrice = $item->getPriceInclTax();
            $orderFullPrice += $item->getPriceInclTax() * (int)$item->getQtyOrdered();
            $itemList[] = [
                "type" => 1,
                "label" => $item->getName(),
                "item_external_code" => $item->getSku(),
                "quantity" => (int)$item->getQtyOrdered(),
                "price" => $item->getPriceInclTax()
            ];
            $qtyOrdered += $item->getQtyOrdered();
        }

        $deliveryAddress = [
            "postal_code" => $shippingAddress->getPostCode(),
            "municipality" => $shippingAddress->getCity(),
            "country_code" => $this->_country->getData('iso3_code'),
        ];

        if ($deliveryModeCode == "1") {
            $deliveryAddress = [
                "postal_code" => $this->_helperConfig->getConfigValue('general/store_information/postcode'),
                "municipality" => $this->_helperConfig->getConfigValue('general/store_information/city'),
                "country_code" => $this->_country->loadByCode($this->_helperConfig->getConfigValue('general/store_information/country_id'))->getData('iso3_code'),
                "delivery_point_name" => $this->_helperConfig->getConfigValue('general/store_information/name')
            ];
        }

        if ($deliveryModeCode == "3") {
            $delivery['recipient'] = [
                "last_name" => $shippingAddress->getLastname(),
                "first_name" => $shippingAddress->getFirstname(),
                "phone_number" => $this->phoneFormat($shippingAddress->getTelephone(), $this->_country->getId())
            ];
        }

        // $address_type = $this->_helperConfig->getCarrierConfig($carrierCode, 'addresstype');
        
        $delivery = [
            "delivery_mode_code" => $deliveryModeCode,
            "express_delivery_flag" => $expressDeliveryFlag,
            "delivery_address" => $deliveryAddress,
            "delivery_point_name" => $this->_helperConfig->getConfigValue('general/store_information/name')
        ];

        
        $orderFullPrice += $this->_checkoutSession->getQuote()->getShippingAddress()->getTotals()['shipping']->getValue();
        $quote = $this->_checkoutSession->getQuote();

        $itemList[] = [
            "type" => 3,
            "label" => "TRANSPORT",
            "item_external_code" => 'shipping_fees',
            "quantity" => 1,
            "price" => $quote->getShippingAddress()->getTotals()['shipping']->getValue()
        ];
        $response = [
            "purchase" => [
                "external_reference_type" => "CMDE",
                "external_reference" => $order->getOrderIncrementId(),
                "purchase_amount" => $orderFullPrice,
                "currency_code" => $order->getCurrencyCode(),
                "number_of_items" => $qtyOrdered,
                "item_list" => $itemList,
                "delivery" => $delivery
            ],
            "merchant_request_id" => $order->getOrderIncrementId() . "_" . date('YmdHms')
        ];
        
        $this->_logger->info("[SUCCESS] [JSON] Create Purchase object (PurchaseDataBuilder): ", [
            'purchase' => $response
        ]);
        return $response;
    }

    protected function getCarrierCode()
    {
        $code = $this->_checkoutSession->getQuote()->getShippingAddress()->getShippingMethod();
        // Cut the code in half like : flatrate_flatrate => flatrate
        return substr($code, 0, (int)(strlen($code) / 2)); 
    }

    /**
     * @param string  $phone
     * @param integer $country
     *
     * @return int|null
     */
    protected function phoneFormat($phone, $country)
    {

        $countryCode = $this->_helperConfig->getPhonePrefixByCountry($country);

        if (preg_match("/^\\+" . $countryCode . "/", $phone)) { //If international Format (+33XXXXXXXXXXX)
            return "00" . ltrim($phone, "+");
        }

        if (preg_match("/^00" . $countryCode . "/", $phone)) { //If international Format with 00 (0033XXXXXXXXXXX)
            return $phone;
        }

        return '00' . $countryCode . ltrim($phone, "0"); // If national format (0XXXXXXXXXX)
    }
}
