<?php
namespace Teknisa\PebLibs\Controllers;

use Teknisa\PebLibs\Services\ValidacoesEstoqueService;
use Teknisa\PebLibs\Controllers\TeknisaCrud;
use Zeedhi\Framework\DTO\Response\Error;
use Zeedhi\Framework\DataSource\DataSet;
use Zeedhi\Framework\DTO\Request\Filter;
use Zeedhi\Framework\DTO\Request\Row;
use Zeedhi\Framework\DTO\Request;
use Zeedhi\Framework\DTO\Response;
use Zeedhi\Framework\DTO;

class Est58000Retirada extends TeknisaCrud {
    
    public $itensWithErrors = [];
    public $itensRetirada = [];

    protected $dataSourceName = "lanctoestoq_retirada";
    protected $parameterBagColumns = ['CDFILIAL','CDALMOXARIFE','CDLOCALESTOQ',"DTFINAL",'DTINICIAL','DATA', 'INTERVALO'];

    protected $crudService;
    protected $parameterBag;
    protected $Est58000Service;
    protected $validacoesEstoqueService;
    protected $entityManager;

    protected $connection;

    public function __construct(
        $crudService,
        $parameterBag, 
        $Est58000Service, 
        ValidacoesEstoqueService $validacoesEstoqueService, 
        $entityManager) {
            
        parent::__construct($crudService,$parameterBag);

        $this->Est58000Service = $Est58000Service;
        $this->validacoesEstoqueService = $validacoesEstoqueService;

        $this->connection = $entityManager->getConnection();
    }

    public function saveRetirada(DTO\Request $request, DTO\Response $response) {
        $lancamento = $request->getRow();
        $evolestoque = 'S';
        $this->connection->beginTransaction();
        try {
            //Essa parte tem como função armazenar o código e nome da retirada inseridos,
            //para serem passados no dataset que retornara a widget. pois o select de retirada
            //não traz esse dois campos.
            $nmtiporeti = $lancamento['NMTIPORETI'];
            $cdtiporeti = $lancamento['CDTIPORETI'];

            //Essa parte verifica se há inventario pendente para a filial seleiconada
            $this->Est58000Service->verificaInventarioRotativo($lancamento['CDFILIAL'],
                                                              $lancamento['DTLANCESTQ']);
                                                              

            //Salva a movimentação na tabela LANCTOESTOQ
            
            $this->Est58000Service->saveLanctoestoq($lancamento['DTLANCESTQ'],
                                                    $lancamento['DSLANCESTQ'],
                                                    $lancamento['CDFILIAL']);

            //Retira os itens que vieram da requisição
            $itens = $lancamento['ITENS'];
            //Verifica se a retirada vai evoluir estoque automaticamente
            //Se a retirada for via leitor de código de barras não evoluirá
            if(!empty($lancamento['IDEVOLESTOQ'])){
                $evolestoque = $lancamento['IDEVOLESTOQ'];
            }
            
            //Salva a retirada na tabela RETIRADAESTO
            $this->Est58000Service->saveRetiradaesto($lancamento['CDFILIAL'],
                                                     $lancamento['DTLANCESTQ'],
                                                     $lancamento['DSLANCESTQ'],
                                                     $lancamento['CDSETOR'],
                                                     $lancamento['CDCENTCUST'],
                                                     null,
                                                     $lancamento['NRREQUESTO']);

            //Salva os itens movimentados na tabela ITLANCTOEST
            $this->Est58000Service->insertItensForRetirada($itens,
                                                          $lancamento['DTLANCESTQ'],
                                                          $lancamento['CDTIPORETI'],
                                                          $lancamento['CDCENTCUST'],
                                                          $lancamento['NRREQUESTO'], 
                                                          $evolestoque);

            //Depois dos processos de salvamento busca-se o registro que foi salvo para
            //retorná-lo ao frontend para que ele possa preencher a currentRow da widget,
            //o que elemina a necessidade de dar reload na widget e perder o "foco" na
            //retirada recém incluida
            $lancamento = $this->Est58000Service->getLancamento($lancamento['CDFILIAL'],
                                                                $lancamento['DTLANCESTQ']);
            //Verifica se o lançamento foi referente a uma requisição de estoque
            if(empty($lancamento['NRREQUESTO'])) {
                $lancamento['NRREQUESTO'] = null;
            } else {
                //Se sim, valida os status da requisição que foi passada e de seus itens
                $this->Est58000Service->validateRequisicao($lancamento, $itens);

                //Verifica a situação da requisição complementar conforme parametrização
                $this->Est58000Service->validateReqComp($lancamento, $itens);
            }
            $item = $itens[0];
            if($evolestoque === 'S' && $item){
                $this->validacoesEstoqueService->atualizaEstoque($lancamento["CDFILIAL"], $lancamento["NRLANCESTQ"], $item);
            }
            
            //Adiciona o nome e o código da retidada no objeto que sera passado ao dataset
            $aux = array("NMTIPORETI"=>$nmtiporeti, "CDTIPORETI"=>$cdtiporeti);
            $lancamento = array_merge($lancamento, $aux);

            $dataSet = new DataSet('lancamento', array($lancamento));
            $response->addDataSet($dataSet);

            $this->connection->commit();
        } catch(\Exception $e) {
            $this->connection->rollBack();
            $irregularProducts = $this->validacoesEstoqueService->getIrregularProducts();
            if(!empty($irregularProducts)) {
                $products = array();
                foreach($irregularProducts as $irregularProduct) {
                    $row = ["cdproduto"=> $irregularProduct->getCdproduto(),
                            "cdalmoxarife"=>$irregularProduct->getCdalmoxarife(),
                            "cdlocalestoq"=>$irregularProduct->getCdlocalestoq(),
                            "nrloteestq"=>$irregularProduct->getNrloteestq(),
                            "nrsublote"=>$irregularProduct->getNrsublote()];
                            
                    $products[] = $row;
                }
                $dataSet = new DataSet("irregularProducts", $products);
                $response->addDataset($dataSet);
            }
            #sends data to frontend through response's dataset
            $response->setError(new Error($e->getMessage(), 500));
        }
    }

    public function save(DTO\Request $request, DTO\Response $response) {
        $lancamento = $request->getDataSet()->getRows();
        $this->connection->beginTransaction();
        try {
            if($lancamento[0]['__is_new'] === false) {
                $this->Est58000Service->processEditLancamento($lancamento[0]);
            } else {
                throw new \Exception("Erro in function save. Was expecting '_is_new' = false", 1);
            }
            $this->connection->commit();
        } catch(\Exception $e) {
            $this->connection->rollBack();
            $response->setError(new Error($e->getMessage(), 500));
        }
    }

    public function delete(DTO\Request $request, DTO\Response $response) {
        $retirada = $request->getRow();
        $lancamento = $request->getRow();
        $this->connection->beginTransaction();
        try {
            $this->Est58000Service->verificaInventarioRotativo($lancamento['CDFILIAL'],
                                                              $lancamento['DTLANCESTQ']);

            $gambiarra = $this->validacoesEstoqueService->buscaLanctoestoq($lancamento["CDFILIAL"], $lancamento["NRLANCESTQ"], $lancamento["NRORG"]);
            if($retirada["EXISTECONSUMO"] = "S"){
                $this->Est58000Service->limpaCampoConsumo((array)$retirada); 
                
            }
            
            $this->Est58000Service->processDeleteRetirada($retirada);

            $this->validacoesEstoqueService->atualizaEstoque($lancamento["CDFILIAL"], $lancamento["NRLANCESTQ"]);

            $this->connection->commit();
        } catch(\Exception $e) {
            $this->connection->rollBack();
            $response->setError(new Error($e->getMessage(), 500));
        }
    }

    public function findPosestdia(DTO\Request\Filter $request, DTO\Response $response) {
        $conditions = $request->getFilterCriteria()->getConditions();
        $filter = [];
        foreach ($conditions as $condition) {
            $filter[$condition["columnName"]] = $condition["value"];
        }

        try {
            $data = $this->Est58000Service->getPosestDia($filter);

            $dataSet = new DataSet('posestdia', array($data));
            $response->addDataSet($dataSet);
        } catch (\Exception $e) {
            $response->setError(new Error($e->getMessage(), 500));
        }
    }
    
    public function importarProdutosTxt(Row $request, Response $response){
        $row = $request->getRow();
        try{
            $isTxt = strpos($row['ARQUIVOTXT'][0]['type'],'text/plain') !== false;
            if($isTxt){
           
                $arquivoB64 = $row["ARQUIVOTXT"][0]["b64File"];
                if(strpos($arquivoB64, ",") !== false){
                    $arquivoB64 = explode(",", $arquivoB64)[1];
                }
                
                if($arquivoB64 == null || $arquivoB64 == "" || $arquivoB64 == "data:"){
                    throw new \Exception("Operação bloqueada! Arquivo de Origem deve ser informado.",400);
                }
                    
                $arquivo = utf8_encode(base64_decode($arquivoB64));
                $produtos = explode("\n", $arquivo);
                
                $produtos = array_filter($produtos, function($v){
                    return $v != "" && $v != null; 
                });
            }else{
                $table = $this->Est58000Service->readXls($row);
                $produtos = $this->Est58000Service->formatXls($table);
            }
            
            $params = $row["PARAMS"];
            $boolRetirada = $row['CONTAINER'] == 'est58000_retirada_estoque'? true: false;
            $ErrorRowNumber = 1;
            
            foreach($produtos as &$produto){
                
                if($isTxt){
                   $produto = $this->Est58000Service->buildObjectTheCode($produto, $params,$this->itensWithErrors,$ErrorRowNumber);
                }else{
                    $produto = $this->Est58000Service->buildObjectTheCodeXls($produto, $params,$this->itensWithErrors,$ErrorRowNumber);
                }
                
                if($produto != null){
                    
                    $produto = $this->Est58000Service->completaProduto($produto, $row['CDFILIAL'], $row["CDFILIMOVI"], $row["DTLANCESTQ"],$this->itensWithErrors,$ErrorRowNumber);
                    if($produto != null){
                           $this->itensRetirada[] = $produto;
                    }
                }
                $ErrorRowNumber++;
                
            }
          
            
            $this->dataSourceName = 'lanctoestoq_retirada';
            $response->addDataSet(new DataSet("itensRetirada", $this->itensRetirada));
            $response->addDataSet(new DataSet("itensWithErrors",$this->itensWithErrors));
        } catch(\Exception $e) {
            $response->setError(new Error($e->getMessage(), 500));
        }
    }
    
}