<?php
namespace Modules\Invoices\BalanceCreate;

class Controller extends \App\Mvc\Controller\Form\PopupAbstract
{

    /**
     * @param $R
     * @return Array
     */
    protected function getDefaultFormData($R)
    {
        global $S;
        $formData = $R;

        // defaults
        $formData['status'] = 'final';
        $formData['idUser'] = CURRENT_ID_USER;

        // balance services
        if ($R['src']=="ses") {  // manual balance
            $formData['idReservationServices'] = implode("|", array_keys((Array)$S['manualBalance']['idServices']));
            $formData['idSupplierInvoiceRows'] = implode("|", array_keys((Array)$S['manualBalance']['idSupplierRows']));
        }
        elseif ($R['src']=="req") { // auto balance
            $formData['idReservationServices'] = implode("|", array_keys($R['c']));
            $formData['idSupplierInvoiceRows'] = implode("|", array_keys($R['s']));
        }

        return $formData;
    }

    /**
     * @param Array $R
     * @param \App\MessagesCollector $msgs
     * @return bool
     */
    protected function processFormData(Array $R, \App\MessagesCollector $msgs)
    {
        try {
            \DB::startTransaction();

            $balanceEnt = \Entity\Balance::insert();

            // set balance details
            $balanceEnt->balanceStatus = $R['status'];
            $balanceEnt->balanceName = $R['name'];
            $balanceEnt->balanceCode = $R['code'];
            $balanceEnt->comments = $R['comments'];
            $balanceEnt->remarks = $R['remarks'];

            // set balance generation
            if ($R['parent']=="balancesAuto") {
                $balanceEnt->generation = 'auto';
            } else {
                $balanceEnt->generation = 'manual';
            }

            // responsible user and office
            $balanceEnt->idUser = $R['idUser']['id'];
            $balanceEnt->idOffice = \Entity\User::select($R['idUser']['id'])->idOffice;

            // client invoice services
            $idReservationServices = array_filter(explode("|", $R['idReservationServices']));
            if ($idReservationServices) {
                $balanceEnt ->idReservationServices = $idReservationServices;
            }

            // supplier invoice rows
            $idSupplierInvoiceRows = array_filter(explode("|", $R['idSupplierInvoiceRows']));
            if ($idSupplierInvoiceRows) {
                $balanceEnt ->idSupplierInvoiceRows = $idSupplierInvoiceRows;
            }

            // save balance
            $balanceEnt->save();

            // empty session
            if ($R['src']=="ses") {
                global $S;
                unset($S['manualBalance']);
            }

            \DB::commitTransaction();

            $msgs->addSuccess($this->lang['messages']['success']);
            return true;
        }
        catch (\App\Entity\Exception $e) {
            \DB::rollbackTransaction();
            $msgs->appendMessages($e->getMessagesCollector());
            return false;
        }

    }

    /**
     * @param \App\Mvc\ViewAbstract $view
     * @param array $formData
     * @return void
     * @throws \App\Config\MessageException
     */
    protected function preRenderOperations(\App\Mvc\ViewAbstract $view, array $formData)
    {
        if ($view->getClosePopup()) {
            return;
        }

        global $S;

        $clientServicesIds = [];
        $supplierRowsIds = [];

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // IF SOURCE IS SESSSION (MANUAL BALANCE) /////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        if ($formData['src']=="ses") {
            $clientServicesIds = (Array)$S['manualBalance']['idServices'];
            $supplierRowsIds = (Array)$S['manualBalance']['idSupplierRows'];
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // IF SOURCE IS REQUEST (AUTO BALANCE) ////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        elseif ($formData['src']=="req") {
            $clientServicesIds = $formData['c'];
            $supplierRowsIds = $formData['s'];
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // GET BULK INFO FOR EACH CLIENT SERVICE //////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        $clientData = [];
        foreach ($clientServicesIds as $idServiceBulk=>$active) {

            // separate normal/refund
            if (is_numeric($idServiceBulk)) {
                $idService = $idServiceBulk;
                $refund = false;
            }
            else {
                $idService = substr($idServiceBulk, 1);
                $refund = true;
            }

            // get reservation service presence on invoice rows
            $invoiceRowsList = \Entity\Service::selectForUpdate($idService)->invoiceRowsList;

            // LOOP THROUGH EACH INVOICE ROW AND GROUP BY idService_idInvoice /////////////////////////////
            foreach ($invoiceRowsList as $idRow=>$rowDetails) {
                // skip the other refund/non refund rows
                if (($refund and !$rowDetails['special']) or (!$refund and $rowDetails['special'])) {
                    continue;
                }

                // collect info about this row
                $key = $rowDetails['idInvoice'].'_'.$idServiceBulk;

                // associate service/invoice/invoiceRow details
                if (!$clientData[$key]) {
                    // associate existing details
                    $clientData[$key]['idService'] = $idService;
                    $clientData[$key]['refund'] = $refund;
                    $clientData[$key]['idInvoice'] = $rowDetails['idInvoice'];
                    // associate invoice details
                    $invoiceDetails = \Entity\Invoice::select($rowDetails['idInvoice']);
                    $clientData[$key]['currency'] = $invoiceDetails->currency;
                    $clientData[$key]['idCorporate'] = $invoiceDetails->idCorporate;
                    $clientData[$key]['idCustomer'] = $invoiceDetails->idCustomer;

                }
                // associate value
                $clientData[$key]['value'] += $rowDetails['pricePrintValue']+$rowDetails['vatPrintValue'];
                // add invoice row id
                $clientData[$key]['invoiceRows'][] = $idRow;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // SUPPLIER DATA //////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////

        // supplier rows ids list
        if (!is_array($supplierRowsIds)) {
            $supplierRowsIds = [];
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // GET BULK INFO FOR EACH SUPPLIER INVOICE ROW ////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        $supplierData = [];
        foreach ($supplierRowsIds as $idRow=>$active) {

            // supplier invoice row details
            $rowDetails = \Entity\SupplierInvoiceRow::select($idRow);

            // the list key (the id invoice)
            $key = $rowDetails->idSupplierInvoice;

            // group by id invoice
            if (!$supplierData[$key]) {
                $supplierData[$key]['idInvoice'] = $rowDetails->idSupplierInvoice;
                $supplierData[$key]['currency'] = $rowDetails->supplierInvoice->currency;
                $supplierData[$key]['idSupplier'] = $rowDetails->supplierInvoice->idSupplier;
                $supplierData[$key]['serviceNamesList'] = [];
            }
            // associate service code
            if ($rowDetails->serviceName) {
                // if first service or a new one (not in the list)
                if (!$supplierData[$key]['serviceNamesList'] or !in_array($rowDetails->serviceName, $supplierData[$key]['serviceNamesList'])) {
                    $supplierData[$key]['serviceNamesList'][] = $rowDetails->serviceName;
                }
            }
            // associate the value
            $supplierData[$key]['value'] += $rowDetails->priceValue+$rowDetails->vatValue;
            // add invoice row id
            $supplierData[$key]['invoiceRows'][] = $idRow;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // COMPUTE EQUIVALENT VALUE AND BALANCE TOTALS ////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////

        // the list of used currencies
        $touchedCurrencies = [];

        // client/supplier arrays
        $balanceTotals = $supplierTotals = $clientTotals = [];

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // LOOP CLIENT DATA ///////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        foreach ($clientData as $id=>$thisRow) {

            $touchedCurrencies[$thisRow['currency']] = true;

            // equivalent value
            $clientData[$id]['_EQUIV_'] = \App\CurrencyExchange\Rates::getInstance($thisRow['invoiceDate'])->convert($thisRow['value'], $thisRow['currency'], \App\Config\Currencies::getInstance()->getDefaultCurrency());

            // compute client totals
            $clientTotals[$thisRow['currency']] += $thisRow['value'];
            $clientTotals['_EQUIV_'] += $clientData[$id]['_EQUIV_'];
            // compute balance totals
            $balanceTotals[$thisRow['currency']] += $thisRow['value'];
            $balanceTotals['_EQUIV_'] += $clientData[$id]['_EQUIV_'];
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////////
        // LOOP SUPPLIER DATA /////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        foreach ($supplierData as $id=>$thisRow) {

            $touchedCurrencies[$thisRow['currency']] = true;

            // equivalent value
            $supplierData[$id]['_EQUIV_'] = \App\CurrencyExchange\Rates::getInstance($thisRow['invoiceDate'])->convert($thisRow['value'], $thisRow['currency'], \App\Config\Currencies::getInstance()->getDefaultCurrency());

            // compute supplier totals
            $supplierTotals[$thisRow['currency']] += $thisRow['value'];
            $supplierTotals['_EQUIV_'] += $supplierData[$id]['_EQUIV_'];
            // compute balance totals
            $balanceTotals[$thisRow['currency']] -= $thisRow['value'];
            $balanceTotals['_EQUIV_'] -= $supplierData[$id]['_EQUIV_'];
        }

        // CREATE usedCurrencies - IN THE ORDER FROM CONFIGS //////////////////////////////////////////////
        // used currencies list
        $usedCurrencies = [];
        // list of all currencies
        $currList = \App\Config\Currencies::getInstance()->getSimple();
        foreach ($currList as $thisCurr) {
            if ($touchedCurrencies[$thisCurr])
                $usedCurrencies[$thisCurr] = 1;
        }

        // DISPLAY SPECIAL MESSAGES IF ONLY CLIENT OR SUPPLIER ELEMENTS CHOSEN ////////////////////////////
        if (!$clientServicesIds) {
            $view->getMessagesCollector()->addWarning($this->lang['warnings']['att_noClientMsg']);
        } elseif (!$supplierRowsIds) {
            $view->getMessagesCollector()->addWarning($this->lang['warnings']['att_noSupplierMsg']);
        }

        // CHECK IF THE CLIENT INVOICE ROWS HAVE DIFFERENT VAT QUOTAS /////////////////////////////////////
        $clientVatQuotas = [];
        foreach ($clientData as $thisRow) {
            foreach ($thisRow['invoiceRows'] as $idRow) {
                $thisVat = \Entity\InvoiceRow::select($idRow)->vatText;
                $clientVatQuotas[$thisVat] = true;
            }
        }
        if (count($clientVatQuotas)>1) {
            $view->getMessagesCollector()->addWarning($this->lang['warnings']['att_diffVatsOnClientRows']);
        }

        // CHECK IF THE SUPPLIER INVOICE ROWS HAVE DIFFERENT VAT QUOTAS ///////////////////////////////////
        $supplierVatQuotas = [];
        foreach ($supplierData as $row) {
            foreach ($row['invoiceRows'] as $idRow) {
                $thisVat = \Entity\SupplierInvoiceRow::select($idRow)->vatText;
                $supplierVatQuotas[$thisVat] = true;
            }
        }
        if (count($supplierVatQuotas)>1) {
            $view->getMessagesCollector()->addWarning($this->lang['warnings']['att_diffVatsOnSupplierRows']);
        }

        // CLIENT / SUPPLIER DATA - FOR BALANCE DISPLAY ---------------------------------------------------
        $view->setOutputVar('clientData', $clientData);
        $view->setOutputVar('supplierData', $supplierData);

        $view->setOutputVar('clientTotals', $clientTotals);
        $view->setOutputVar('supplierTotals', $supplierTotals);
        $view->setOutputVar('balanceTotals', $balanceTotals);

        $view->setOutputVar('usedCurrencies', $usedCurrencies);
        $view->setOutputVar('equivCurrency', \App\Config\Currencies::getInstance()->getDefaultCurrency());

        // AUTO CONFIRM FLAG - TO AUTOMATICALLY PRESS THE BUTTON //////////
        if (!$formData[$this->formSubmitButtonName]) {
            $view->setOutputVar('autoSubmit', $formData['noConfirm']);
        }

    }

}
