<?php

use KupShop\BankAutoPaymentBundle\PaymentSources\FioBankApi;
use KupShop\KupShopBundle\Context\ContextManager;
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
use KupShop\KupShopBundle\Util\StringUtil;
use KupShop\ReturnsBundle\Util\ReturnsUtil;
use Query\Operator;

include_once __DIR__.'/ReturnsList.php';

class ReturnsMassModificationList extends ReturnsList
{
    protected $template = 'list/ReturnsMassModificationList.tpl';
    protected $paymentsResult = '';

    public function customizeTableDef($tableDef)
    {
        $tableDef = parent::customizeTableDef($tableDef);

        // $tableDef['id'] = '';

        $field = [
            'Vybrat' => [
                'field' => 'r.code',
                'size' => '55px',
                'render' => 'renderReturnCheckbox',
                'label' => 'check',
                'type' => '',
                'class' => 'hiddenTooltip overflow-visible hidden-label',
            ],
            'Číslo' => [
                'field' => 'r.id',
                'type_id' => 'r.id',
                'type' => 'Returns',
                'render' => 'renderCode',
            ],
            'Částka' => [
                'field' => 'ro.total_price',
                'spec' => function (Query\QueryBuilder $qb) {
                    $qb->addSelect('ABS(ro.total_price) as total_price, ro.currency as currency')
                        ->leftJoin('r', 'orders', 'ro', 'ro.id = r.id_order');
                },
                'render' => 'renderPrice',
            ],
        ];

        $tableDef['fields'] = $field + $tableDef['fields'];

        return $tableDef;
    }

    public function renderReturnCheckbox(&$values)
    {
        $values['return'] = $this->canReturnMoney($values['id']);
        $values['price'] = $values['return'] ? $values['return']['order']->total_price->abs()->asFloat() : null;

        return $this->getCheckbox('return_ids', $values['id'], $values['return']);
    }

    public function handleMoneyReturned()
    {
        $returnIds = getVal('return_ids', getVal('data'), []);

        foreach ($returnIds as $id) {
            $this->returns->markReturnFinished($this->returns->getReturn($id), ReturnsUtil::FINISHED_PAYMENT);
        }
    }

    public function handleBankCommand()
    {
        $dbcfg = Settings::getDefault();
        $returnIds = getVal('return_ids', getVal('data'), []);

        if (empty($dbcfg->returns['bank_account_number']) || empty($dbcfg->returns['bank_account_code'])) {
            $this->returnError(translate('return_missing_account', 'returnsSettingsTab'));
        }

        $abo = new \snoblucha\Abo\Abo();
        $abo->setComittentNumer(0);
        $abo->setOrganization($dbcfg->shop_firm_name);
        $abo->setDate();

        $account = $abo->addAccountFile(\snoblucha\Abo\Account\File::UHRADA);
        $account->setBank($dbcfg->returns['bank_account_code']); // banka prikazce
        $account->setBankDepartment(0);
        $group = $account->addGroup();

        $group->setAccount($dbcfg->returns['bank_account_number']);
        $group->setDate();

        foreach ($returnIds as $returnId) {
            if ($info = $this->canReturnMoney($returnId)) {
                $group->addItem($info['account'], $info['order']->total_price->abs()->asFloat(), $info['order']->order_no)
                    ->setMessage(StringUtil::removeAccents($dbcfg['shop_firm_name']).'-'.$info['order']->order_no);
            }
        }

        header('Content-type: application/txt');
        header('Content-Disposition: attachment; filename="ABO-'.date('Y-m-d_H-i').'_'.time().'.txt"');
        echo $abo->generate();
        exit;
    }

    public function handleFioCommand()
    {
        /** @var FioBankApi $fio */
        $fio = ServiceContainer::getService(FioBankApi::class);
        /** @var ContextManager $manager */
        $manager = ServiceContainer::getService(ContextManager::class);
        $returnIds = getVal('return_ids', getVal('data'), []);
        $paymentsCZK = [];
        $paymentsEUR = [];

        $amountCZK = 0.0;
        $amountEUR = 0.0;

        foreach ($returnIds as $returnId) {
            if ($info = $this->canReturnMoney($returnId, true)) {
                /* @var Order $order */
                $order = $info['order'];
                $manager->activateOrder($order, function () use ($order, $info, $returnId, &$amountCZK, &$amountEUR, &$paymentsCZK, &$paymentsEUR) {
                    $amount = abs($order->getTotalPrice()->getPriceWithVat()->asFloat());
                    if ($order->getCurrency() == 'CZK') {
                        @[$accountTo, $bankCode] = explode('/', $info['account']);
                        $amountCZK += $amount;
                        $paymentsCZK[$returnId] = [
                            'currency' => 'CZK',
                            'amount' => $amount,
                            'accountTo' => $accountTo,
                            'bankCode' => $bankCode,
                            'vs' => $order->order_no,
                            'date' => date('Y-m-d'),
                            'messageForRecipient' => translate('bankComment')." {$order->order_no}",
                            'comment' => translate('bankComment')." {$order->order_no}",
                            'paymentType' => '431001',
                        ];
                    } elseif ($order->getCurrency() == 'EUR') {
                        /** @var \PHP_IBAN\IBAN $iban */
                        $iban = $info['iban'];
                        $amountEUR += $amount;
                        $paymentsEUR[$returnId] = [
                            'currency' => 'EUR',
                            'amount' => $amount,
                            'accountTo' => $iban->MachineFormat(),
                            'vs' => $order->order_no,
                            'date' => date('Y-m-d'),
                            'comment' => $this->convertToASCII(translate('bankComment')." {$order->order_no}"),
                            'benefName' => $this->convertToASCII("{$order->invoice_name} {$order->invoice_surname}"),
                            'remittanceInfo1' => $this->convertToASCII(translate('bankComment')." {$order->order_no}"),
                        ];
                    }
                });
            }
        }
        try {
            $payments = $fio->sendPayments($paymentsCZK, $paymentsEUR);
        } catch (\KupShop\BankAutoPaymentBundle\Exceptions\FioPaymentExeption $exception) {
            $text = '<h5>Při odesílání do FIO nastala následující chyba: </h5>'.$exception->getMessage().'<br>Zamítněte převody v aplikaci banky a zkuste znovu.';
            echo json_encode(['text' => $text, 'ids' => []]);
            exit;
        }

        $this->paymentsResult = '<h5>Platby odeslány do Fio.</h5> <h6>Potvrďte převody v bance a klikněte na tlačítko <strong>"Peníze vráceny"</strong></h6>';
        $failed = [];
        foreach ($payments as $type => $values) {
            foreach ($values as $returnId => $payment) {
                if (!$payment['success']) {
                    $failed[] = $returnId;
                }
            }

            $this->paymentsResult .= "<strong>{$type}:</strong><br>";
            $this->paymentsResult .= '<strong>Očekávaná částka:</strong> '.${'amount'.$type}.'<br>';
        }

        if (!empty($failed)) {
            $this->paymentsResult .= '<strong>Při zpracování těchto vratek došlo k chybě: </strong>'.implode(', ', $failed).'<br>';
        }

        echo json_encode(['text' => $this->paymentsResult, 'ids' => $failed]);
        exit;
    }

    protected function canReturnMoney($returnId, $fio = false)
    {
        $return = $this->returns->getReturn($returnId);

        if ($orderId = $return->getIdOrder()) {
            $orderObj = new Order();
            $exists = $orderObj->createFromDB($orderId);
            if ($exists && $orderObj->total_price->isNegative()) {
                if ($orderObj->status_storno == 1) {
                    return false;
                }

                $accountNo = $return->getBankAccount();
                if (!empty($accountNo)) {
                    $iban = new \PHP_IBAN\IBAN($accountNo);
                    if ($iban->Verify()) {
                        // ABO nepodporuje zahranicni platbu
                        if ($orderObj->delivery_country == 'SK' && !$fio) {
                            return false;
                        } else {
                            // Do FIO aktuálně jde jen CZK a EUR
                            if (!in_array($orderObj->getCurrency(), ['EUR', 'CZK'])) {
                                return false;
                            }

                            // Koruny lze poslat jen na českej účet
                            if ($orderObj->currency == 'CZK' && $iban->Country() != 'CZ') {
                                return false;
                            }
                        }

                        $accountNo = $iban->Branch().'-'.$iban->Account().'/'.$iban->Bank();
                    } elseif (!preg_match('/^((\d{1,6})-)?\d{1,10}\/\d{4}$/', $accountNo)) {
                        return false;
                    }

                    return ['order' => $orderObj, 'account' => $accountNo, 'iban' => $iban];
                }
            }
        }

        return false;
    }

    public function getFilterQuery(): Query\QueryBuilder
    {
        $qb = parent::getFilterQuery();

        $qb->andWhere(Operator::inIntArray($this->returns->getAcceptedStatuses(), 'r.status'));

        return $qb;
    }

    private function convertToASCII(string $input): string
    {
        $transiterator = \Transliterator::createFromRules(':: Any-Latin; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC; ł > l;');

        return $transiterator->transliterate($input);
    }
}

return ReturnsMassModificationList::class;
