<?php

class MultiSafepay_Msp_Model_Servicecost_Quote_Address_Total_Servicecost extends Mage_Sales_Model_Quote_Address_Total_Abstract
{
    protected $_method = '';
    protected $_rate = '';
    protected $_collection = '';
    public $_configCode = 'msp';

    public function __construct()
    {
        $this->setCode('servicecost');
    }

    public function collect(Mage_Sales_Model_Quote_Address $address)
    {
        // Only run on shipping/billing address types, to prevent resetting servicecosts with 3rd party address types
        if ($address->getAddressType() != Mage_Sales_Model_Quote_Address::TYPE_BILLING
            && $address->getAddressType() != Mage_Sales_Model_Quote_Address::TYPE_SHIPPING) {
            return $this;
        }

        if (Mage::app()->getFrontController()->getRequest()->isSecure()) {
            $protocol = 'https://';
        } else {
            $protocol = 'http://';
        }

        if (isset($_SERVER["SERVER_NAME"]) && isset($_SERVER["REQUEST_URI"])) {
            $currentUrl = $protocol . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
        } else {
            $currentUrl = null;
        }

        if ($currentUrl != Mage::helper('checkout/cart')->getCartUrl()) {
            $quote = $address->getQuote();
            $code = $quote->getPayment()->getMethod();

            if ($code == '') {
                if (isset($_POST['payment']['method'])) {
                    $code = $_POST['payment']['method'];
                }
            }

            // Reset fee when already processed.
            $address->getQuote()->setData('servicecost_pdf', null);
            $address->setServicecostPdf(null);

            $address->getQuote()->setData('servicecost', null);
            $address->setServicecost(null);

            $address->getQuote()->setData('base_servicecost', null);
            $address->setBaseServicecost(null);

            $address->getQuote()->setData('servicecost_tax', null);
            $address->setServicecostTax(null);

            $address->getQuote()->setData('base_servicecost_tax', null);
            $address->setBaseServicecostTax(null);

            if (!empty($code)) {
                /** @var MultiSafepay_Msp_Model_Gateway_Abstract $paymentMethod */
                $paymentMethod = $quote->getPayment()->getMethodInstance();

                if (!$paymentMethod instanceof MultiSafepay_Msp_Model_Gateway_Abstract) {
                    return $this;
                }

                $configCode = $this->getConfigCode($paymentMethod);

                if ($paymentMethod->isAvailableMethod()) {
                    if (Mage::getStoreConfig($configCode . '/' . $code . '/fee', $quote->getStoreId())) {
                        $amount = $address->getShippingAmount();
                        if ($amount != 0 || $address->getShippingDescription()) {
                            $servicecostAmount = $this->getServicecostAmount($code, $address);
                            $servicecostTaxAmount = $this->getServicecostTaxAmount($code, $address);

                            $address->setServicecostAmount($servicecostAmount);
                            $address->setServicecostTaxAmount($servicecostTaxAmount);
                            $address->setBaseServicecost($servicecostAmount);
                            $address->setBaseServicecostTaxAmount($servicecostTaxAmount);

                            $address->getQuote()->setData('servicecost', $servicecostAmount);
                            $address->getQuote()->setData('base_servicecost', $servicecostAmount);
                            $address->getQuote()->setData('servicecost_tax', $servicecostTaxAmount);
                            $address->getQuote()->setData('base_servicecost_tax', $servicecostTaxAmount);

                            if (!Mage::getStoreConfig($configCode . '/' . $code . '/fee_incexc', $quote->getStoreId())) {
                                $address->getQuote()->setData('servicecost_pdf', $servicecostAmount - $servicecostTaxAmount);
                                $address->setServicecostPdf($servicecostAmount - $servicecostTaxAmount);
                            } else {
                                $address->getQuote()->setData('servicecost_pdf', $servicecostAmount);
                                $address->setServicecostPdf($servicecostAmount);
                            }

                            $address->setTaxAmount($address->getTaxAmount() + $address->getServicecostTaxAmount());
                            $address->setBaseTaxAmount($address->getBaseTaxAmount() + $address->getServicecostTaxAmount());
                            $address->setGrandTotal($address->getGrandTotal() + $servicecostAmount);
                            $address->setBaseGrandTotal($address->getBaseGrandTotal() + $servicecostAmount);
                        }
                    }
                    return $this;
                }
            }
        }
    }

    public function fetch(Mage_Sales_Model_Quote_Address $address)
    {
        $this->_method = $address->getQuote()->getPayment()->getMethod();
        $label = Mage::helper('msp')->getFeeLabel($this->_method);
        $quote = $address->getQuote();
        $code = $quote->getPayment()->getMethod();

        if (empty($code)) {
            $configCode = 'msp';
        } else {
            /** @var MultiSafepay_Msp_Model_Gateway_Abstract $paymentMethod */
            $paymentMethod = $quote->getPayment()->getMethodInstance();
            if (!$paymentMethod instanceof MultiSafepay_Msp_Model_Gateway_Abstract) {
                return $this;
            }

            $configCode = $this->getConfigCode($paymentMethod);
        }

        if (Mage::getStoreConfig($configCode . '/' . $code . '/fee', $quote->getStoreId())) {
            $amount = $address->getShippingAmount();
            if ($amount != 0 || $address->getShippingDescription()) {
                if ($address->getServicecostAmount()) {
                    $address->addTotal(array(
                        'code' => $this->getCode(),
                        'title' => $label,
                        'value' => $address->getServicecostPdf()
                    ));
                }
            }
        }
        return $this;
    }

    /**
     * Get the service cost amount
     *
     * @param string $code
     * @param Mage_Sales_Model_Quote_Address $address
     * @return float
     * @throws Mage_Core_Model_Store_Exception
     */
    public function getServicecostAmount($code, $address)
    {
        $quote = $address->getQuote();
        if (is_null($quote)) {
            return 0.0;
        }

        /** @var MultiSafepay_Msp_Model_Gateway_Abstract $paymentMethod */
        $paymentMethod = $quote->getPayment()->getMethodInstance();
        $configCode = $this->getConfigCode($paymentMethod);

        $total_fee = 0;
        $fee = Mage::getStoreConfig($configCode . '/' . $code . '/fee_amount');
        $fee_array = explode(':', $fee);

        // Fee is not configured
        if (empty($fee_array[0])) {
            $fixed_fee = 0.0;
        } else {
            $fixed_fee = (float) str_replace(',', '.', $fee_array[0]);
        }

        // Check for configured percentage value
        if (!empty($fee_array[1])) {
            $fee_array[1] = str_replace(',', '.', $fee_array[1]);
            $serviceCostPercentage = (float) str_replace('%', '', $fee_array[1]);
            $originalData = $address->getOrigData();
            $baseSubTotal = !empty($originalData['base_subtotal']) ? (float) $originalData['base_subtotal'] : 0.0;
            $fee_percentage = (
                !empty($quote->getBaseSubtotal())
                    ? $quote->getBaseSubtotal()
                    : $baseSubTotal
                ) * ($serviceCostPercentage / 100);
            $total_fee += $fee_percentage;
        }
        $total_fee += $fixed_fee;

        return $this->_convertFeeCurrency($total_fee, MultiSafepay_Msp_Helper_Data::CONVERT_TO_CURRENCY_CODE, Mage::app()->getStore()->getCurrentCurrencyCode());
    }

    public function getServicecostTaxAmount($code, $address)
    {
        $quote = $address->getQuote();
        /** @var MultiSafepay_Msp_Model_Gateway_Abstract $paymentMethod */
        $paymentMethod = $quote->getPayment()->getMethodInstance();
        $configCode = $this->getConfigCode($paymentMethod);

        $taxClass = Mage::getStoreConfig($configCode . '/' . $code . '/fee_tax_class');
        if ($taxClass == 0) {
            $this->_rate = 1;
            return 0.0;
        }

        $taxCalculationModel = Mage::getSingleton('tax/calculation');
        if ($taxCalculationModel === null) {
            return 0.0;
        }

        $request = $taxCalculationModel->getRateRequest(
            $quote->getShippingAddress(),
            $quote->getBillingAddress(),
            $quote->getCustomerTaxClassId(),
            Mage::app()->getStore()->getId()
        );
        $request->setStore(Mage::app()->getStore())->setProductClassId($taxClass);

        $globalTaxRate = (float) $taxCalculationModel->getRate($request);

        $serviceFee = $this->getServicecostAmount($code, $address);

        return $serviceFee * ($globalTaxRate / 100);
    }

    protected function _convertFeeCurrency($amount, $currentCurrencyCode, $targetCurrencyCode)
    {
        if ($currentCurrencyCode == $targetCurrencyCode) {
            return $amount;
        }

        $currentCurrency = Mage::getModel('directory/currency')->load($currentCurrencyCode);
        $rateCurrentToTarget = $currentCurrency->getAnyRate($targetCurrencyCode);

        if ($rateCurrentToTarget === false) {
            Mage::throwException(Mage::helper("msp")->__("Imposible convert %s to %s", $currentCurrencyCode, $targetCurrencyCode));
        }

        // Disabled check, fixes PLGMAG-10. Magento seems to not to update USD->EUR rate in db, resulting in wrong conversions.
        // Now we calculate the rate manually and and don't trust Magento stored rate.
        // if (strlen((string) $rateCurrentToTarget) < 12) {
        $revertCheckingCode = Mage::getModel('directory/currency')->load($targetCurrencyCode);
        $revertCheckingRate = $revertCheckingCode->getAnyRate($currentCurrencyCode);
        $rateCurrentToTarget = 1 / $revertCheckingRate;
        //}

        return round($amount * $rateCurrentToTarget, 2);
    }

    /**
     * @param MultiSafepay_Msp_Model_Gateway_Abstract $paymentMethod
     */
    protected function getConfigCode(MultiSafepay_Msp_Model_Gateway_Abstract $paymentMethod): string
    {
        if ($paymentMethod->isRegularGateway()) {
            return 'msp_gateways';
        } else {
            return 'msp_giftcards';
        }
    }
}
