<?php
namespace src\controllers;

use \core\Controller;
use \src\handlers\LoginHandler;
use \src\handlers\PermissionHandler;
use \src\controllers\UtilsController;
use \src\models\Bills_to_pay;
use \src\models\Bills_to_receive;
use \src\models\Client;
use \src\models\Deliverie;
use \src\models\Farm;
use \src\models\Product;
use \src\models\Provider;
use \src\models\Purchase;
use \src\models\Request;
use \src\models\Salesman;

class DeliveriesController extends Controller {
    private $loggedUser;
    private $pageActive;
    private $paramsName;
    private $arrayInfo;

    public function __construct() {
        date_default_timezone_set('America/Sao_Paulo');
        $this->loggedUser = LoginHandler::checkLogin();

        if($this->loggedUser == false) {
            $this->redirect('/login');
        }

        $this->pageActive = 'requests';
        $this->paramsName = PermissionHandler::getPermissions($this->loggedUser->group);

        if(!in_array('requests_view', $this->paramsName)) {
            $this->redirect('/');
        }
    }

    public function initDelivery($data = array()) {
        $obj_delivery = $data;

        if(empty($obj_delivery)) {
            $obj_delivery = filter_input(INPUT_POST, 'delivery', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
        }

        if($obj_delivery) {
            $info_delivery = array();
            $dateNow = date('Y-m-d');
            $obj_delivery['status_delivery'] = 1; // (status da entrega, na solicitação veio para mudar semelhante a com estoque)

            $requestInfo = Request::getRequest($obj_delivery['id_request']);
            $obj_delivery['id_provider'] = Product::getProduct($obj_delivery['id_product']);

            if($obj_delivery['type_delivery'] == 'single_delivery') {
                $obj_delivery['status_delivery'] = 1;
                $obj_delivery['qtd_deliveries'] = 1;
                $obj_delivery['daysPayment'] = 0;

                $info_delivery['quantity'] = Request::getAmountRequest($obj_delivery['id_request']);  
                $info_delivery['total'] = $requestInfo['total'];

            } else if($obj_delivery['type_delivery'] == 'separate_deliveries') {

                $info_delivery = Request::getAmountDelivery($obj_delivery['id_request'], $obj_delivery['id_product']);
            }

            $delivery['id_request'] = $obj_delivery['id_request'];
            $delivery['type_delivery'] = $obj_delivery['type_delivery'];
            $delivery['balance'] = $info_delivery['quantity'];
            $delivery['created_at'] = date('Y-m-d h:i:s'); // Novo campo criado para armazenar horário de criação da entrega

            $response['id_delivery'] = Deliverie::saveDeliverie($delivery);

            // Adicionar itens de entrega
            if($info_delivery) {
                $comission_salesman = Request::getOtherInformations('salesman_comission', $obj_delivery['id_request']);
                $other_expenses = Request::getOtherInformations('other_expenses', $obj_delivery['id_request']);
                $firstPayment = UtilsController::convertDate($obj_delivery['date_first_deliverie']);

                $amount = ($info_delivery['quantity'] / $obj_delivery['qtd_deliveries']);
                $value_delivery = ($info_delivery['total'] / $obj_delivery['qtd_deliveries']);

                // Objeto de salvamento
                $deliveryItem['status'] = $obj_delivery['status_delivery'];                
                $deliveryItem['id_deliverie'] = $response['id_delivery'];
                $deliveryItem['id_product'] = $obj_delivery['id_product'];
                $deliveryItem['id_client'] = $obj_delivery['id_client'];
                $deliveryItem['id_provider'] = $obj_delivery['id_provider']['id_provider'];
                $deliveryItem['product_group'] = $obj_delivery['product_group'];
                $deliveryItem['id_farm'] = $requestInfo['pre_select_farm'];                
                $deliveryItem['date_edition'] = $dateNow;
                $deliveryItem['amount'] = $amount;
                $deliveryItem['value_delivery'] = $value_delivery;
                $deliveryItem['shipping_invoice'] = $obj_delivery['shipping_invoice'];
                $deliveryItem['note_delivery'] = $obj_delivery['note'];

                for($i=0; $i<$obj_delivery['qtd_deliveries']; $i++) {
                    $delivery_number = $i + 1;
                    $days = $i * $obj_delivery['daysPayment'];
                    $dateDeliverie = date('Y-m-d', strtotime('+'.$days.'days', strtotime($firstPayment)));

                    $deliveryItem['delivery_number'] = $delivery_number;
                    $deliveryItem['date_deliverie'] = $dateDeliverie;
                    
                    $ref_delivery_item = Deliverie::saveItemsDelivery($deliveryItem);

                    if(!empty($other_expenses)) {
                        self::createAccountOtherExpenses($ref_delivery_item, $other_expenses, $obj_delivery, $dateDeliverie, $this->loggedUser->id);
                    }

                    if(!empty($comission_salesman)) {
                        $providerInfo = Provider::getProvider($obj_delivery['id_provider']['id_provider'], 'providers');
                        $newDateDeliverie = self::getNewDateFromBtr($providerInfo['payment_provider_day'], $dateDeliverie);

                        self::initComissionSalesman($ref_delivery_item, $response['id_delivery'], $obj_delivery, $newDateDeliverie, $comission_salesman, $requestInfo);
                    }

                    // Criação de contas grupo especial
                    if($deliveryItem['product_group'] == 3) {
                        self::createAccountPaymentProvider($ref_delivery_item, $response['id_delivery'], $deliveryItem, $dateDeliverie, $delivery['id_request'], $this->loggedUser->id);

                        self::accountReceiverSpecial($ref_delivery_item, $delivery, $dateDeliverie, $value_delivery, $i, $obj_delivery['qtd_deliveries']);
                    }

                    // Criação de contas grupo com estoque
                    if($obj_delivery['type_delivery'] == 'single_delivery') {
                        self::createAccountReceiverWithStock($obj_delivery['id_request'], $response['id_delivery'], $ref_delivery_item);
                    }

                    // Criação de contas grupo sem estoque
                    if($deliveryItem['product_group'] == 1) {
                        $providerInfo = Provider::getProvider($obj_delivery['id_provider']['id_provider'], 'providers');
                        $newDateDeliverie = self::getNewDateFromBtr($providerInfo['receiver_provider_day'], $dateDeliverie);

                        self::accountReceiverRepresentation($ref_delivery_item, $delivery, $newDateDeliverie, $obj_delivery['qtd_deliveries']);
                    }                  
                }
            }

            if($obj_delivery['type_delivery'] != 'single_delivery') {
                $response['status'] = true;
                echo json_encode($response);
            }
        }
    }

    public function deliveryItem() {
        $delivery = filter_input(INPUT_GET, 'd');

        if($delivery) {

            $this->arrayInfo['deliveryInfo'] = Deliverie::getDeliveryInfo($delivery);
            $this->arrayInfo['deliveryItems'] = Deliverie::getDeliveryItems($delivery);
            $this->arrayInfo['requestInfo'] = Request::getRequest($this->arrayInfo['deliveryInfo']['id_request']);
            $this->arrayInfo['paymentReceiver'] = Request::getOtherInformations('request_payment_receiver', $this->arrayInfo['deliveryInfo']['id_request']);
            $this->arrayInfo['otherExpenses'] = Request::getOtherInformations('other_expenses', $this->arrayInfo['deliveryInfo']['id_request']);
            $this->arrayInfo['requestInfo']['client_name'] = Client::getName($this->arrayInfo['requestInfo']['id_client']);

            $providerList = explode(',', $this->arrayInfo['requestInfo']['id_provider']);
            $count_pro = count($providerList);            

            foreach ($this->arrayInfo['deliveryItems'] as $key => $item) {
                $this->arrayInfo['deliveryItems'][$key]['situation_name'] = Deliverie::getSituationName($item['status']);                
                $this->arrayInfo['deliveryItems'][$key]['farm_name'] = Farm::getFarmName($item['id_farm']);
            }

            $this->arrayInfo['verify_deliveries'] = Deliverie::getDeliveriesCanceled($delivery);
            $product = Product::getProduct($this->arrayInfo['deliveryItems'][0]['id_product']);

            if($this->arrayInfo['deliveryInfo']['type_delivery'] == 'separate_deliveries') {
                
                $this->arrayInfo['provider'] = Provider::getProvider($product['id_provider'], 'providers');
                $this->arrayInfo['unit'] = Product::getProductUnit($product['id_unity']);

                $this->arrayInfo['provider_title'] = $this->arrayInfo['provider']['company_name'];

            } else {
                $this->arrayInfo['provider_title'] = '';

                foreach($providerList as $key => $provider) {
                    $this->arrayInfo['requestInfo']['providers'][] = Provider::getProviderName($provider);

                    $this->arrayInfo['provider_title'] .= ($key != $count_pro - 1)? $this->arrayInfo['requestInfo']['providers'][$key].' / ' : $this->arrayInfo['requestInfo']['providers'][$key] ;
                }

                $this->arrayInfo['unit'] = Product::getProductUnit($product['id_unity']);

            }

            if($this->arrayInfo['unit']['id'] == 4 || $this->arrayInfo['unit']['id'] == 7) {
                $this->arrayInfo['unit_value'] = number_format($this->arrayInfo['deliveryInfo']['balance'], 3, ',', '.').' '.$this->arrayInfo['unit']['name'];
            } else {
                $this->arrayInfo['unit_value'] = $this->arrayInfo['deliveryInfo']['balance'].' '.$this->arrayInfo['unit']['name'];
            }

            foreach ($this->arrayInfo['deliveryItems'] as $key => $dItem) {
                $this->arrayInfo['deliveryItems'][$key]['date_deliverie'] = UtilsController::convertDate($dItem['date_deliverie']);
                $this->arrayInfo['deliveryItems'][$key]['date_edition'] = UtilsController::convertDate($dItem['date_edition']);

                if(!empty($dItem['value_delivery_balance'])) {
                    $this->arrayInfo['deliveryItems'][$key]['value'] = UtilsController::convertToRealBr($dItem['value_delivery_balance']);
                } else {
                    $this->arrayInfo['deliveryItems'][$key]['value'] = UtilsController::convertToRealBr($dItem['value_delivery']);
                }                

                if($this->arrayInfo['unit']['id'] == 4 || $this->arrayInfo['unit']['id'] == 7) {
                    $this->arrayInfo['deliveryItems'][$key]['qtde'] = (!empty($dItem['amount_balance']))? number_format($dItem['amount_balance'], 3, ',', '.') : number_format($dItem['amount'], 3, ',', '.');
                } else {
                    $this->arrayInfo['deliveryItems'][$key]['qtde'] = (!empty($dItem['amount_balance']))? $dItem['amount_balance'] : $dItem['amount'];
                }
            }

            $this->render('delivery_item', [
                'loggedUser' => $this->loggedUser,
                'pageActive' => $this->pageActive,
                'permissions' => $this->paramsName,
                'array' => $this->arrayInfo,
                'titlePage' => 'Entrega(s) - Supporte Agronegócios'
            ]);

        } else {
            $this->redirect('/requests');
        }
    }

    // Requisição ajax, buscando informações de item de entega
    public function getDeliveryInfo() {
        $deliveryItem = filter_input(INPUT_POST, 'delivery');

        if($deliveryItem) {
            $response['itemInfo'] = Deliverie::getDeliveryItem($deliveryItem);
            $response['deliveryInfo'] = Deliverie::getDeliveryInfo($response['itemInfo']['id_deliverie']);
            $product = Product::getProduct($response['itemInfo']['id_product']);

            $response['itemInfo']['date_deliverie'] = UtilsController::convertDate($response['itemInfo']['date_deliverie']);
            $response['itemInfo']['date_edition'] = UtilsController::convertDate($response['itemInfo']['date_edition']);
            $response['itemInfo']['value_delivery'] = UtilsController::convertToRealBr($response['itemInfo']['value_delivery']);            

            if($response['itemInfo']['value_delivery_balance']) {
                $response['itemInfo']['value_delivery_balance'] = UtilsController::convertToRealBr($response['itemInfo']['value_delivery_balance']);
            }

            if($product['id_unity'] == 4 || $product['id_unity'] == 7) {

                if($response['itemInfo']['amount_balance']) {
                    $response['itemInfo']['amount_balance'] = number_format($response['itemInfo']['amount_balance'], 3, ',', '.');    
                }
                
                $response['itemInfo']['amount'] = number_format($response['itemInfo']['amount'], 3, ',', '.');
                $response['deliveryInfo']['balance'] = number_format($response['deliveryInfo']['balance'], 3, ',', '.');
            }

            echo json_encode($response);
        }
    }

    // Atualizar informações de Item de entrega
    public function updateDeliveryInfo() {
        $item = filter_input(INPUT_POST, 'deliveryInfo', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);

        if($item) {
            $ref = $item['id'];
            $itemUpdate['date_edition'] = date('Y-m-d');
            $itemUpdate['date_deliverie'] = UtilsController::convertDate($item['date_delivery']);
            $itemUpdate['shipping_invoice'] = $item['shipping_invoice'];
            $itemUpdate['note_delivery'] = $item['note'];

            Deliverie::updateItemDelivery($itemUpdate, $ref);
            self::updateDependencies($item['id'], false);
            echo json_decode(true);
        }
    }

    public function verifyDeliveryDate() {
        $date = filter_input(INPUT_POST, 'dateDelivery');

        if($date) {
            $response = false;

            if(UtilsController::isDate($date)) {
                $response = true;             
                // if(UtilsController::verifyFutureDate($date)) {
                //     $response = true;
                // }
            }

            echo json_encode($response);
        }
    }

    public function verifyShippingInvoice() {
        $number = filter_input(INPUT_POST, 'value');
        $provider = filter_input(INPUT_POST, 'provider');
        $response = false;

        if($number) {
            $data = Deliverie::existsShippingInvoice($number, $provider);

            if($data) {
                if($data['id_provider'] == $provider) {
                    $response = true;
                }
            }
        }

        echo json_encode($response);
    }

    public function getUpdatedValueDelivery() {
        $balance = filter_input(INPUT_POST, 'balance');
        $response['status'] = false;

        if(!empty($balance) && $balance > 0) {
            $refDeliveryItem = filter_input(INPUT_POST, 'item');
            $deliveryItem = Deliverie::getDeliveryItem($refDeliveryItem);
            $deliveryInfo = Deliverie::getDeliveryInfo($deliveryItem['id_deliverie']);

            $balance = UtilsController::convertPriceToDb($balance);
            $requestItem = Request::getRequestItem($deliveryInfo['id_request'], $deliveryItem['id_product']);

            $response['value'] = ($balance * $requestItem['price_sale']);

            $response['status'] = true;
            $response['value'] = UtilsController::convertToRealBr($response['value']);
        }

        echo json_encode($response);
    }

    public function cancelDeliverieItem() {
        $refDeliveryItem = filter_input(INPUT_POST, 'item');
        $text = filter_input(INPUT_POST, 'text');

        // Pegar informações do item de entrega
        $deliveryItem = Deliverie::getDeliveryItem($refDeliveryItem);

        // Deletando contas a pagar e receber
        Bills_to_pay::deleteAccounts('id_item_delivery', $refDeliveryItem);
        Bills_to_receive::deleteAccounts('id_item_delivery', $refDeliveryItem);

        // Atualizar saldo da entrega(Balança)
        $deliveryInfo = Deliverie::getDeliveryInfo($deliveryItem['id_deliverie']);
        $deliveryUpdate['balance'] = ($deliveryInfo['balance'] - $deliveryItem['amount']);
        Deliverie::updateDeliverie($deliveryUpdate, $deliveryInfo['id']);

        // Buscar informações do pedido
        $requestInfo = Request::getRequest($deliveryInfo['id_request']);
        $requestItem = Request::getRequestItem($deliveryInfo['id_request'], $deliveryItem['id_product']);

        $requestItemUpdate['quantity'] = ($requestItem['quantity'] - $deliveryItem['amount']);
        $requestItemUpdate['total'] = ($requestItemUpdate['quantity'] * $requestItem['price_sale']);
        Request::updateItems($requestItem['id'], $requestItemUpdate);

        $requestUpdate['total'] = ($requestInfo['total'] - $deliveryItem['value_delivery']);
        Request::requestUpdate($requestInfo['id'], $requestUpdate);

        // Atualização do item da entrega
        $itemUpdate['status'] = 7;
        $itemUpdate['date_edition'] = date('Y-m-d');

        if($text) {
            $itemUpdate['note_delivery'] = $text;
        }

        Deliverie::updateItemDelivery($itemUpdate, $refDeliveryItem);
        self::updateDependencies($refDeliveryItem, false);

        echo json_encode(true);
    }

    public function setDeliveryComplete() {
        $refDeliveryItem = filter_input(INPUT_POST, 'item');
        $pGroup = filter_input(INPUT_POST, 'p_group');
        $balance = filter_input(INPUT_POST, 'balance');
        $totalValue = filter_input(INPUT_POST, 'value');
        $shippingInvoice = filter_input(INPUT_POST, 'shipping_invoice');
        $deliveryDate = filter_input(INPUT_POST, 'dateDelivery');
        $note = filter_input(INPUT_POST, 'note');

        $balance = UtilsController::convertPriceToDb($balance);
        $deliveryDate = UtilsController::convertDate($deliveryDate);

        $itemUpdate['status'] = 6;
        $itemUpdate['date_deliverie'] = $deliveryDate;
        $itemUpdate['date_edition'] = date('Y-m-d');
        $itemUpdate['shipping_invoice'] = $shippingInvoice;
        $itemUpdate['note_delivery'] = $note;

        if($pGroup != 2) {
            $itemUpdate['amount_balance'] = $balance;
            $itemUpdate['value_delivery_balance'] = UtilsController::convertPriceToDb($totalValue);
        }

        Deliverie::updateItemDelivery($itemUpdate, $refDeliveryItem);
        self::updateDependencies($refDeliveryItem, true);

        echo json_encode(true);
    }

    // Função para atualizar tabelas após a entrega realizada (saldo, status de entrega e pedido, alteração de quantidade de entrega caso necessário)
    private static function updateDependencies($refDeliveryItem, $updateDelivery) {
        $deliveryItem = Deliverie::getDeliveryItem($refDeliveryItem); // Item que foi atualizado por ultimo
        $deliveryItems = Deliverie::getDeliveryItems($deliveryItem['id_deliverie']); // Todos os itens dessa entrega
        $deliveryInfo = Deliverie::getDeliveryInfo($deliveryItem['id_deliverie']); // Informações da entrega pai
        $requestInfo = Request::getRequest($deliveryInfo['id_request']);
        $requestItem = Request::getRequestItem($deliveryInfo['id_request'], $deliveryItem['id_product']);

        $qtdDeliveries = count($deliveryItems);
        $delivered = 0;
        $canceled = 0;
        $totalAmount = 0; // Variavel que contabiliza a real quantidade entregue dos itens da entrega em QT
        $totalDelivered = 0; // Variavel que contabiliza o valor real entregue dos itens da entrega em R$

        // Atualização  de status e numero da nota em contas a pagar
        $billsToPayUpdate['id_situation'] = 2;
        $billsToPayUpdate['document_number'] = $deliveryItem['shipping_invoice'];

        // Atualização  de status e numero da nota em contas a receber
        $billsToReceiverUpdate['id_situation'] = 2;
        $billsToReceiverUpdate['document_number'] = $deliveryItem['shipping_invoice'];

        // Verificação em data de entrega do item, para alterar data de recebimento de contas a receber e alteração em contas a pagar de comissão
        if($deliveryItem['product_group'] == 1) {
            $providerInfo = Provider::getProvider($deliveryItem['id_provider'], 'providers');
            $receiverForm = Request::getOtherInformations('request_payment_receiver', $deliveryInfo['id_request']);
            $billsToReceiverUpdate['expirate_date'] = date('Y-m-d', strtotime('+ '.$receiverForm['receiver_comission_days_after_delivery'].' days', strtotime($deliveryItem['date_deliverie'])));

            if(!empty($providerInfo['receiver_provider_day'])) {
                $billsToReceiverUpdate['expirate_date'] = self::getNewDateFromBtr($providerInfo['receiver_provider_day'], $deliveryItem['date_deliverie']);
            }

            $newValueToReceiver = ($requestInfo['percente_supporte'] * $deliveryItem['value_delivery_balance']) / 100;
            $billsToReceiverUpdate['main_value'] = $newValueToReceiver;
            $billsToReceiverUpdate['value_to_pay'] = $newValueToReceiver;
            $billsToReceiverUpdate['residual_value'] = $newValueToReceiver;

            // Verificando se possui comissão a ser paga para realizar as alterações
            $comissionSalesman = Request::getOtherInformations('salesman_comission', $deliveryInfo['id_request']);

            if($comissionSalesman) {
                $billsToPayUpdate['expirate_date'] = $billsToReceiverUpdate['expirate_date'];

                if(!empty($providerInfo['payment_provider_day'])) {
                    $billsToPayUpdate['expirate_date'] = self::getNewDateFromBtr($providerInfo['payment_provider_day'], $deliveryItem['date_deliverie']);
                }

                $newValueToPayComission = ($comissionSalesman['percentage'] * $deliveryItem['value_delivery_balance']) / 100;
                $billsToPayUpdate['main_value'] = $newValueToPayComission;
                $billsToPayUpdate['value_to_pay'] = $newValueToPayComission;
                $billsToPayUpdate['residual_value'] = $newValueToPayComission;
            }
        }

        Bills_to_pay::updateAccount('id_item_delivery', $deliveryItem['id'], $billsToPayUpdate);
        Bills_to_receive::updateAccount('id_item_delivery', $deliveryItem['id'], $billsToReceiverUpdate);

        // Fim Atualização em contas a pagar e receber

        // Iteração filtrando itens entregues e cancelados
        foreach ($deliveryItems as $key => $item) {
            
            if($item['status'] == 6) {
                $delivered++;
            }

            if($item['status'] == 7) {
                $canceled++;
            }
        }

        // Função usada em mais de um local, esse if(true ou false) validação é para verificar se é necessário atualizar a entrega e o item de entrega
        if($updateDelivery) {
            if($deliveryItem['product_group'] == 2) {
                $deliveryUpdate['status'] = 2;
                $deliveryUpdate['balance'] = 0;            
            } else {

                $deliveryUpdate['balance'] = ($deliveryInfo['balance'] - $deliveryItem['amount_balance']);
                $lastDeliverie = Deliverie::getLastDeliverieItemActive($deliveryItem['id_deliverie']);

                // Atualizar ultima carga se existir
                if($delivered != $qtdDeliveries) {
                    if($lastDeliverie) {

                        $valueReduce = ($deliveryItem['amount'] - $deliveryItem['amount_balance']);
                        $itemUpdate['amount'] = ($valueReduce + $lastDeliverie['amount']);

                        // Montar instrução para recalcular o valor da ultima entrega e atualizar contas a pagar e receber
                        $itemUpdate['value_delivery'] = ($itemUpdate['amount'] * $requestItem['price_sale']);

                        Deliverie::updateItemDelivery($itemUpdate, $lastDeliverie['id']);

                        // Fazendo alterações em contas a pagar e receber, referente a ultima entrega
                        if($deliveryItem['product_group'] == 1) {
                            
                            // Atualização do valor a receber em contas a receber, da ultima entrega
                            $vtrLastDelivery = ($requestInfo['percente_supporte'] * $itemUpdate['value_delivery']) / 100;
                            $btrUpdateLastDelivery['main_value'] = $vtrLastDelivery;
                            $btrUpdateLastDelivery['value_to_pay'] = $vtrLastDelivery;
                            $btrUpdateLastDelivery['residual_value'] = $vtrLastDelivery;

                            // Verificando se possui comissão a ser paga para realizar as alterações em contas a pagar
                            if($comissionSalesman) {                                

                                $newComissionValue = ($comissionSalesman['percentage'] * $itemUpdate['value_delivery']) / 100;
                                $btpUpdateLastDelivery['main_value'] = $newComissionValue;
                                $btpUpdateLastDelivery['value_to_pay'] = $newComissionValue;
                                $btpUpdateLastDelivery['residual_value'] = $newComissionValue;
                                
                                Bills_to_pay::updateAccount('id_item_delivery', $lastDeliverie['id'], $btpUpdateLastDelivery);
                            }
                            
                            Bills_to_receive::updateAccount('id_item_delivery', $lastDeliverie['id'], $btrUpdateLastDelivery);
                        }
                    }
                }

                if(!$lastDeliverie) {
                    // Irá entrar nesse if se não haver mais entregas para serem realizadas
                    // Reunir informações do pedido para atualização da quantidade e valor total do pedido

                    $totalAmount = array_sum(array_column($deliveryItems, 'amount_balance'));
                    $totalDelivered = array_sum(array_column($deliveryItems, 'value_delivery_balance'));

                    $requestUpdate['total'] = $totalDelivered;
                    $requestItemUpdate['quantity'] = $totalAmount;
                    $requestItemUpdate['total'] = $totalDelivered;

                    Request::updateItems($requestItem['id'], $requestItemUpdate); // Atualização do item do pedido
                }
            }

            Deliverie::updateDeliverie($deliveryUpdate, $deliveryItem['id_deliverie']);
        }

        if($delivered == $qtdDeliveries) {
            $requestUpdate['status'] = 4;
        } else if($canceled == $qtdDeliveries) {
            $requestUpdate['status'] = 6;
        } else if(($delivered + $canceled) == $qtdDeliveries) {
            $requestUpdate['status'] = 5;
        } else {
            $requestUpdate['status'] = 3;
        }

        Request::requestUpdate($deliveryInfo['id_request'], $requestUpdate);
    }

    public function createNewCharge() {
        $newDelivery = filter_input(INPUT_POST, 'delivery_charge', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);

        if($newDelivery) {
            $dateNow = date('Y-m-d');
            // Buscando lista de entregas para usar a ultima como referência
            $deliveryItems = Deliverie::getDeliveryItems($newDelivery['nc_id_delivery']);
            $itemToCopy = end($deliveryItems);

            // Informações do item do pedido, para calcular o valor da nova entrega e altera-lo junto com o pedido
            $requestItem = Request::getRequestItem($newDelivery['nc_id_request'], $newDelivery['nc_id_product']);

            // Equações para obter valor da entrega a ser criada.
            $amountReceived = UtilsController::convertPriceToDb($newDelivery['charge_quantity']);
            $valueNewDelivery = ($amountReceived * $requestItem['price_sale']);

            // Array de criaçao de novo item de entrega
            unset($itemToCopy['id']);
            $itemToCopy['status'] = 1;
            $itemToCopy['delivery_number'] = ($itemToCopy['delivery_number'] + 1);
            $itemToCopy['shipping_invoice'] = '';
            $itemToCopy['date_deliverie'] = UtilsController::convertDate($newDelivery['date_delivery']);
            $itemToCopy['date_edition'] = $dateNow;
            $itemToCopy['amount'] = $amountReceived;
            $itemToCopy['amount_balance'] = null;
            $itemToCopy['value_delivery'] = $valueNewDelivery;
            $itemToCopy['value_delivery_balance'] = null;
            $itemToCopy['note_delivery'] = '';

            $refItemDelivery = Deliverie::saveItemsDelivery($itemToCopy); // Inserção do item de entrega

            // Alteração da quantidade da entrega(balance)
            $deliveryInfo = Deliverie::getDeliveryInfo($newDelivery['nc_id_delivery']);

            $deliveryUpdate['balance'] = ($deliveryInfo['balance'] + $amountReceived);
            Deliverie::updateDeliverie($deliveryUpdate, $newDelivery['nc_id_delivery']); // Atualização da entrega

            // Alterações do pedido e item do pedido
            $requestItemUpdate['quantity'] = ($requestItem['quantity'] + $amountReceived);
            $requestItemUpdate['total'] = ($requestItem['total'] + $valueNewDelivery);

            Request::updateItems($requestItem['id'], $requestItemUpdate); // Atualização do item do pedido

            $requestInfo = Request::getRequest($newDelivery['nc_id_request']); 

            $requestUpdate['status'] = 3;
            $requestUpdate['total'] = ($requestInfo['total'] + $valueNewDelivery);

            Request::requestUpdate($requestInfo['id'], $requestUpdate); // Atualização do Pedido

            // Criação de contas a receber de nova carga
            $delivery['is_new_change'] = true;
            $delivery['id_request'] = $newDelivery['nc_id_request'];
            $delivery['total_new_change'] = $valueNewDelivery;

            // Enviando informações para criação de contas a receber, dependendo do grupo
            if($newDelivery['nc_product_group'] == 1) {

                self::accountReceiverRepresentation($refItemDelivery, $delivery, $itemToCopy['date_deliverie'], 1);

            } else if($newDelivery['nc_product_group'] == 3) {

                self::accountReceiverSpecial($refItemDelivery, $delivery, $itemToCopy['date_deliverie'], $valueNewDelivery, 1, 1);
            }

            // Verificar se existe conta a pagar para criar
            $comissionSalesman = Request::getOtherInformations('salesman_comission', $requestInfo['id']);

            if($comissionSalesman) {
                $obj_delivery['is_new_change'] = true;
                $obj_delivery['product_group'] = $newDelivery['nc_product_group'];
                $obj_delivery['qtd_deliveries'] = 1;
                $obj_delivery['value_new_change'] = $valueNewDelivery;

                self::initComissionSalesman($refItemDelivery, $deliveryInfo['id'], $obj_delivery, $itemToCopy['date_deliverie'], $comissionSalesman, $requestInfo);    
            }

            echo json_encode(true);
        }
    }

    // Adição de Comissão em contas a pagar
    private function initComissionSalesman($ref_delivery_item, $id_delivery, $obj_delivery, $dateDeliverie, $comission_salesman, $requestInfo) {
        // Verificar se o pedido é a vista ou parcelado
        $paymentReceiver = Request::getOtherInformations('request_payment_receiver', $requestInfo['id']);
        // $expirate_date = date('Y-m-d', strtotime('+ '.$comission_salesman['payment_comission_days'].' days', strtotime($dateDeliverie)));        
        $expirate_date = $dateDeliverie;

        if($obj_delivery['product_group'] == 2) {
            $situation = 2;
            $total = ($comission_salesman['total'] / $paymentReceiver['installments']);
            $billstopay_type = 31;
        } else {
            $situation = 1;
            $total = ($comission_salesman['total'] / $obj_delivery['qtd_deliveries']);
            $billstopay_type = 2;
        }

        // Verificação de nova carga
        if(isset($obj_delivery['is_new_change'])) {
            $total = ($comission_salesman['percentage'] * $obj_delivery['value_new_change']) / 100;
        }
        // Fim Verificação de nova carga

        // Objeto com informações de contas a pagar, para comissão do vendedor
        $salesmanAccount['copied'] = 0;
        $salesmanAccount['id_user'] = $this->loggedUser->id;
        $salesmanAccount['id_comission_salesman'] = $comission_salesman['id'];
        $salesmanAccount['provider_description'] = Salesman::getSalesmanName($comission_salesman['salesman']);
        $salesmanAccount['id_delivery'] = $id_delivery;
        $salesmanAccount['id_item_delivery'] = $ref_delivery_item;
        $salesmanAccount['id_request'] = $requestInfo['id'];
        $salesmanAccount['id_situation'] = $situation;
        $salesmanAccount['billstopay_type'] = $billstopay_type;
        $salesmanAccount['billstopay_description'] = "Pgto de Comissão";
        $salesmanAccount['document_date'] = $requestInfo['date_created'];        
        $salesmanAccount['main_value'] = $total;
        $salesmanAccount['value_to_pay'] = $total;
        $salesmanAccount['residual_value'] = $total;
        $salesmanAccount['note'] = 'Referente ao pedido nr '.$requestInfo['id'];

        for($i=0; $i<$paymentReceiver['installments']; $i++) {
            $counter = ($i * 30);
            $dateExpirate = date('Y-m-d', strtotime('+ '.$counter.' days', strtotime($expirate_date)));

            $salesmanAccount['expirate_date'] = $dateExpirate;

            Bills_to_pay::saveAcount($salesmanAccount);
        }          
    }

    // Criação de contas a pagar para produtos do grupo especial (Pagar fornecedor)
    private function createAccountPaymentProvider($ref_delivery_item, $id_delivery, $deliveryItem, $dateDeliverie, $id_request, $id_user) {
        $product = Product::getProduct($deliveryItem['id_product']);
        $purchaseAdvance = Purchase::getAdavanceLastPurshase($deliveryItem['id_product']);
        $advance = 0;

        $m_value = ($product['cost_price'] * $deliveryItem['amount']);

        if($purchaseAdvance) {
            $advance = ($purchaseAdvance['advance'] * $m_value) / 100;
        }

        $value_pay = ($m_value - $advance);
        
        $billsToPay['copied'] = 0;
        $billsToPay['id_user'] = $id_user;
        $billsToPay['id_provider'] = $deliveryItem['id_provider'];
        $billsToPay['provider_description'] = Provider::getProviderName($deliveryItem['id_provider']);
        $billsToPay['id_delivery'] = $id_delivery;
        $billsToPay['id_item_delivery'] = $ref_delivery_item;
        $billsToPay['id_request'] = $id_request;
        $billsToPay['id_situation'] = 1;
        $billsToPay['billstopay_type'] = 3;
        $billsToPay['billstopay_description'] = "Pgto de Fornecedor";
        $billsToPay['document_date'] = $dateDeliverie;
        $billsToPay['expirate_date'] = $dateDeliverie;
        $billsToPay['main_value'] = $m_value;
        $billsToPay['advance_value'] = $advance;
        $billsToPay['value_to_pay'] = $value_pay;
        $billsToPay['residual_value'] = $value_pay;
        $billsToPay['note'] = 'Referente ao pedido nº '.$id_request;
        
        Bills_to_pay::saveAcount($billsToPay); 
    }

    // Adicionar contas a pagar de Outras despesas
    private function createAccountOtherExpenses($id_item, $other_expenses, $delivery, $dateDeliverie, $id_user) {        
        $prod_quantity = Request::getAmountRequest($delivery['id_request']);
        $total_od = ($other_expenses['value_unity'] * $prod_quantity);
        $od_unity = ($total_od / $delivery['qtd_deliveries']);

        if($delivery['product_group'] == 2) {
            $situation = 2;
        } else {
            $situation = 1;
        }

        $otherExpenses['copied'] = 0;
        $otherExpenses['id_user'] = $id_user;
        $otherExpenses['provider_description'] = $other_expenses['note'];
        $otherExpenses['billstopay_type'] = 5;
        $otherExpenses['billstopay_description'] = "Pgto de OD";
        $otherExpenses['document_date'] = $dateDeliverie;
        $otherExpenses['expirate_date'] = $dateDeliverie;
        $otherExpenses['main_value'] = $od_unity;
        $otherExpenses['value_to_pay'] = $od_unity;
        $otherExpenses['residual_value'] = $od_unity;
        $otherExpenses['id_situation'] = $situation;
        $otherExpenses['id_request'] = $delivery['id_request'];
        $otherExpenses['note'] = 'Referente ao pedido nº '.$delivery['id_request'];

        Bills_to_pay::saveAcount($otherExpenses);
    }

    // Criação de contas a receber Pedido com estoque (A chamada dessa função será tranferida para RequestController na criação do pedido)
    private function createAccountReceiverWithStock($idRequest, $idDelivery, $idDeliveryItem) {
        $requestInfo = Request::getRequest($idRequest);
        $paymentReceiver = Request::getOtherInformations('request_payment_receiver', $idRequest);
        $firstExpirate = $paymentReceiver['date_receiver'];
        $valueAccount = ($requestInfo['total'] / $paymentReceiver['installments']);

        $dataAccount['copied'] = 0;
        $dataAccount['id_user'] = $this->loggedUser->id;
        $dataAccount['id_item_delivery'] = $idDeliveryItem;
        $dataAccount['id_provider'] = $requestInfo['id_client']; // No caso de contas a receber com estoque, quem paga é o cliente
        $dataAccount['provider_description'] = Client::getName($requestInfo['id_client']);
        $dataAccount['receiver_origin'] = 2;
        $dataAccount['origin_description'] = "Produto Grupo Com Estoque";
        $dataAccount['form_to_pay'] = $requestInfo['id_receiverform'];
        $dataAccount['form_to_pay_description'] = Bills_to_receive::getReceiverForm($requestInfo['id_receiverform']);
        $dataAccount['document_date'] = $requestInfo['date_created'];
        $dataAccount['document_number'] = $idRequest;
        $dataAccount['id_request'] = $idRequest;
        $dataAccount['note'] = 'Referente ao pedido nº '.$idRequest;
        $dataAccount['id_situation'] = 2;
        $dataAccount['main_value'] = $valueAccount;
        $dataAccount['value_to_pay'] = $valueAccount;
        $dataAccount['residual_value'] = $valueAccount;

        for($i=0; $i<$paymentReceiver['installments']; $i++) {
            $counter = ($i * 30);
            $dateExpirate = date('Y-m-d', strtotime('+ '.$counter.' days', strtotime($firstExpirate)));

            $dataAccount['expirate_date'] = $dateExpirate;

            Bills_to_receive::saveAcount($dataAccount);
        }
    }

    // Criação de contas a receber Pedido Especial
    private function accountReceiverSpecial($id_item, $delivery, $datesDeliveries, $value_delivery, $i, $qtd_deliveries) {
        $request_input = Request::getOtherInformations('request_input', $delivery['id_request']);
        $requestInfo = Request::getRequest($delivery['id_request']);
        $v_advance = 0;

        // Obsoleto, possívelmente não mais usado
        if($request_input) {
            if($request_input['how_dilute_input'] == 2) {
                $v_advance = ($request_input['value_input'] / $qtd_deliveries);
            } else if($request_input['how_dilute_input'] == 3) {
                if($i+1 == $qtd_deliveries) {
                    $v_advance = $request_input['value_input'];
                }
            }
        }

        $dataAccount['copied'] = 0;
        $dataAccount['id_user'] = $this->loggedUser->id;
        $dataAccount['id_item_delivery'] = $id_item;        
        $dataAccount['id_provider'] = $requestInfo['id_client']; // No caso de contas a receber com estoque, quem paga é o cliente
        $dataAccount['provider_description'] = Client::getName($requestInfo['id_client']);
        $dataAccount['receiver_origin'] = 3;
        $dataAccount['origin_description'] = "Produto Grupo Especial";
        $dataAccount['form_to_pay'] = $requestInfo['id_receiverform'];
        $dataAccount['form_to_pay_description'] = Bills_to_receive::getReceiverForm($requestInfo['id_receiverform']);
        $dataAccount['document_date'] = $datesDeliveries;
        $dataAccount['expirate_date'] = $datesDeliveries;
        $dataAccount['document_number'] = $delivery['id_request'];
        $dataAccount['main_value'] = $value_delivery;
        $dataAccount['advance_value'] = $v_advance;
        $dataAccount['value_to_pay'] = ($value_delivery - $v_advance);
        $dataAccount['residual_value'] = $dataAccount['value_to_pay'];        
        $dataAccount['id_request'] = $delivery['id_request'];
        $dataAccount['note'] = 'Referente ao pedido nº '.$delivery['id_request'];
        $dataAccount['id_situation'] = 1;
        
        Bills_to_receive::saveAcount($dataAccount);
    }

    // Criação de contas a receber Pedido Sem estoque
    private function accountReceiverRepresentation($id_item, $delivery, $datesDeliveries, $qtd_deliveries) {
        $requestInfo = Request::getRequest($delivery['id_request']);

        if($requestInfo['percente_supporte'] != null && $requestInfo['percente_supporte'] > 0) {
            $paymentReceiver = Request::getOtherInformations('request_payment_receiver', $delivery['id_request']);

            $dataAccount['id_provider'] = null;
            $dataAccount['provider_description'] = Provider::getProviderName($requestInfo['id_provider']);

            if($paymentReceiver['how_pay_comission_supporte'] == 2) {
                $dataAccount['id_provider'] = $requestInfo['id_client'];
                $dataAccount['provider_description'] = Client::getName($requestInfo['id_client']);
            }

            if(isset($delivery['is_new_change'])) {
                $mainValue = ($requestInfo['percente_supporte'] * $delivery['total_new_change']) / 100;
                $mainValue = ($mainValue / $qtd_deliveries);
            } else {
                $mainValue = ($requestInfo['percente_supporte'] * $requestInfo['total']) / 100;
                $mainValue = ($mainValue / $qtd_deliveries);
            }        
            // Validação para saber que é criação de nova carga

            $dataAccount['copied'] = 0;
            $dataAccount['id_user'] = $this->loggedUser->id;            
            $dataAccount['id_item_delivery'] = $id_item;
            $dataAccount['receiver_origin'] = 1;
            $dataAccount['origin_description'] = "Produto de Representação";
            $dataAccount['form_to_pay'] = $requestInfo['id_receiverform'];
            $dataAccount['form_to_pay_description'] = Bills_to_receive::getReceiverForm($requestInfo['id_receiverform']);
            $dataAccount['document_date'] = $datesDeliveries;
            $dataAccount['expirate_date'] = $datesDeliveries;
            $dataAccount['document_number'] = $delivery['id_request'];
            $dataAccount['main_value'] = $mainValue;
            $dataAccount['value_to_pay'] = $mainValue;
            $dataAccount['residual_value'] = $mainValue;
            $dataAccount['id_request'] = $delivery['id_request'];
            $dataAccount['note'] = 'Referente ao pedido nº '.$delivery['id_request'];
            $dataAccount['id_situation'] = 1;            
            
            Bills_to_receive::saveAcount($dataAccount);
        }
    }

    // Zerar saldo da balança
    public function zeroBalance() {
        $delivery = intval(filter_input(INPUT_POST, 'delivery'));

        if($delivery) {
            $deliveryData['balance'] = 0;

            Deliverie::updateDeliverie($deliveryData, $delivery);
            echo json_encode(true);
        }
    }

    // Modificar data conforme informação de pagamento de fornecedor e nova formula fornecida.
    private static function getNewDateFromBtr($dayPayment, $date) {
        $day = ($dayPayment < 10)? '0'.$dayPayment : $dayPayment;

        $dateArray = explode('-', $date);
        $month = $dateArray[1] + 1;
        $month = ($month < 10)? '0'.$month : $month;

        if($month > 12) {
            $month = '01';
            $dateArray[0] = $dateArray[0] + 1;
        }

        $dateArray[1] = $month;
        $dateArray[2] = $day;

        $dateArray = implode('-', $dateArray);

        return $dateArray;
    }
}