<?php

/**
 * 20/10/2015
 * @author Victor Novy
 */

namespace Teknisa\PebLibs\Controllers;

use \Zeedhi\Framework\DTO\Request\Row;
use \Zeedhi\Framework\DTO\Request\DataSet as DataSets;
use \Zeedhi\Framework\DTO\Response;
use \Zeedhi\Framework\DTO\Response\Error;
use \Zeedhi\Framework\DataSource\DataSet;
use \Teknisa\PebLibs\Services\ValidacoesEstoqueService;
use \Geral\Entities\Paramfilial;

class ValidacoesEstoqueController {

    protected $validacoesEstoqueService;
    protected $environment;

    public function __construct (ValidacoesEstoqueService $validacoesEstoqueService, $environment) {
        $this->validacoesEstoqueService = $validacoesEstoqueService;
        $this->environment = $environment;
    }

    /**
     * Busca os dodos relacionados a 'data de processamento' e realiza a validacao da 'data do lancemento'.
     *
     * @param Row $request
     * @param Response $response
     */
    public function validaDataLancamento(Row $request, Response $response) {
        try {
            $dadosValidacao = $request->getRow();

            $filial = $dadosValidacao['CDFILIAL'];
            $dtLancamento = $dadosValidacao['DTLANCTOEST'];
            $operacao = $dadosValidacao['OPERACAO'];
            $sistema = $dadosValidacao['IDSISTEMA'];
            $dtEmissao = $dadosValidacao['DTEMISSAO'];

            $this->validacoesEstoqueService->validaDataLancamento(
                $filial, $dtLancamento, $operacao, $sistema, $dtEmissao
            );
        } catch (\Exception $e) {
            $response->setError(new Error($e->getmessage(), $e->getCode()));
        }
    }

    /**
     * Procedimento que recebe uma row e pede pela
     * requisição da atualização de estoque para o
     * lançamento de estoque e unidade informados,
     * respeitando quaisquer flags recebidas.
     *
     * Envia no objeto response um DataSet com os códigos
     * dos produtos que apresentam irregularidades de
     * estoque, nos casos em que essa possibilidade se
     * aplica.
     *
     * Envia no objeto response um erro, quando aplicável
     *
     * @param Row      $request
     * @param Response $response
     */
    public function atualizaEstoque(Row $request, Response $response) {
        try {
            $payload = $request->getRow();

            #gets relevant data from payload
            $cdfilial              = $payload['CDFILIAL'];
            $nrlancestq            = $payload['NRLANCESTQ'];
            $verifyIrregularities  = $payload['IDVERIRREG'];
            $abortAtIrregularities = $payload['IDABRIRREG'];
            $seqItemCodes          = $payload['SEQITEMS'];
            $consolidate           = isset($payload['CONSOLIDATE'])? $payload['CONSOLIDATE'] : false;

            #calls procedure validation, preparation and execution, receiving any irregular products, if applicable
            $irregularProducts = $this->validacoesEstoqueService->atualizaEstoque(
                $cdfilial, $nrlancestq, $consolidate, $verifyIrregularities, $abortAtIrregularities, $seqItemCodes
            );
            $irregularProducts = $this->validacoesEstoqueService->getIrregularProducts();
            #sends data to frontend through response's dataset
            $response->addDataset(new DataSet("irregularProducts", $irregularProducts));
        } catch(\Doctrine\DBAL\DBALException $e) {
            #catches doctrine exceptions and prepares message for response's error
            $message = substr($e->getMessage(), strpos($e->getMessage(), 'ORA') + 10);
            $message = substr($message, 0, strpos($message, 'ORA') - 1);
                
            $response->setError(new Error($message, $e->getCode()));
        } catch (\Exception $e) {
            $irregularProducts = $this->validacoesEstoqueService->getIrregularProducts();
            if(!empty($irregularProducts)) {
                $products = array();
                //$row = {"cdproduto"=> $irregularProduct->getCdproduto(), cdalmoxarife: 01, cdlocalestoq: 33, nrloteestq:111111, nrsublote: 55}
                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);
            }
            #catches generic error and sends message to frontend through response's error
            $response->setError(new Error($e->getmessage(), $e->getCode()));
        }
    }
    
    public function atualizaEstoqueAfterUpdateDataSet(DataSets $request, Response $response) {
        try {
            $payload = $request->getDataSet();
            $rows = $payload->getRows();
            #gets relevant data from payload
            $cdfilial              = $rows[0]['CDFILIAL'];
            $nrlancestq            = $rows[0]['NRLANCESTQ'];
            $verifyIrregularities  = $rows[0]['IDVERIRREG'];
            $abortAtIrregularities = $rows[0]['IDABRIRREG'];
            $consolidate           = isset($rows[0]['CONSOLIDATE'])? $rows[0]['CONSOLIDATE'] : false;
            #calls procedure validation, preparation and execution, receiving any irregular products, if applicable
            $irregularProducts = $this->validacoesEstoqueService->atualizaEstoqueUpdate(
                $cdfilial, $nrlancestq, $rows, $consolidate, $verifyIrregularities, $abortAtIrregularities
            );
            $irregularProducts = $this->validacoesEstoqueService->getIrregularProducts();
            $products = array();
            if(!empty($irregularProducts)) {
                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);
        } catch(\Doctrine\DBAL\DBALException $e) {
            #catches doctrine exceptions and prepares message for response's error
            $message = substr($e->getMessage(), strpos($e->getMessage(), 'ORA') + 10);
            $message = substr($message, 0, strpos($message, 'ORA') - 1);
                
            $response->setError(new Error($message, $e->getCode()));
        } catch (\Exception $e) {
            $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);
            }
            #catches generic error and sends message to frontend through response's error
            $response->setError(new Error($e->getmessage(), $e->getCode()));
        }
    }
    
    public function atualizaEstoqueRetirada(Row $request, Response $response) {
        try {
            $payload = $request->getRow();
            #gets relevant data from payload
            $cdfilial              = $payload['CDFILIAL'];
            $nrlancestq            = $payload['NRLANCESTQ'];
            $verifyIrregularities  = $payload['IDVERIRREG'];
            $abortAtIrregularities = $payload['IDABRIRREG'];
            $seqItemCodes          = $payload['SEQITEMS'];
            $consolidate           = isset($payload['CONSOLIDATE'])? $payload['CONSOLIDATE'] : false;
            $row                   = $payload['ROW'];
            
            $arrProdutosRetirada = $this->validacoesEstoqueService->getProdutosRetirar($cdfilial, $nrlancestq);
            
            if(!empty($arrProdutosRetirada))
                $this->validacoesEstoqueService->processRetirada($row, $arrProdutosRetirada);
            $this->atualizaEstoque($request, $response);

        } catch(\Doctrine\DBAL\DBALException $e) {
            #catches doctrine exceptions and prepares message for response's error
            $message = substr($e->getMessage(), strpos($e->getMessage(), 'ORA') + 10);
            $message = substr($message, 0, strpos($message, 'ORA') - 1);
                
            $response->setError(new Error($message, $e->getCode()));
        } catch (\Exception $e) {
            $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);
            }
            #catches generic error and sends message to frontend through response's error
            $response->setError(new Error($e->getmessage(), $e->getCode()));
        }
    }

    public function zeraInventario(Row $request, Response $response) {
        try {
            $dadosAtualizacao = $request->getRow();

            $filial         = $dadosAtualizacao['CDFILIAL'];
            $lancamento     = $dadosAtualizacao['NRLANCAMENTO'];
            $idordem        = $dadosAtualizacao['IDORDEMCLC'];
            $consolidate    = isset($dadosAtualizacao['CONSOLIDATE'])? $dadosAtualizacao['CONSOLIDATE'] : false;

            $this->validacoesEstoqueService->zeraInventario($filial, $lancamento, $idordem, $consolidate);
            $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);
            }
        } catch(\Doctrine\DBAL\DBALException $e) {
            $message = substr($e->getMessage(), strpos($e->getMessage(), 'ORA') + 10);
            $message = substr($message, 0, strpos($message, 'ORA') - 1);
            $response->setError(new Error($message, $e->getCode()));
        } catch (\Exception $e) {
            $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);
            }
            $response->setError(new Error($e->getmessage(), $e->getCode()));
        }
    }
    
    public function zeraInventarioRetirada(Row $request, Response $response) {
        try {
            $dadosAtualizacao = $request->getRow();

            $filial         = $dadosAtualizacao['CDFILIAL'];
            $lancamento     = $dadosAtualizacao['NRLANCAMENTO'];
            $idordem        = $dadosAtualizacao['IDORDEMCLC'];
            $consolidate    = isset($dadosAtualizacao['CONSOLIDATE'])? $dadosAtualizacao['CONSOLIDATE'] : false;
            $row            = $dadosAtualizacao['ROW'];
            
            $arrProdutosRetirada = $this->validacoesEstoqueService->getProdutosRetirar($filial, $lancamento);
            
            if(!empty($arrProdutosRetirada))
                $this->validacoesEstoqueService->processRetirada($row, $arrProdutosRetirada);

            $this->validacoesEstoqueService->zeraInventario($filial, $lancamento, $idordem, $consolidate);
            $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);
            }
        } catch(\Doctrine\DBAL\DBALException $e) {
            $message = substr($e->getMessage(), strpos($e->getMessage(), 'ORA') + 10);
            $message = substr($message, 0, strpos($message, 'ORA') - 1);
            $response->setError(new Error($message, $e->getCode()));
        } catch (\Exception $e) {
            $irregularProducts = $this->validacoesEstoqueService->getIrregularProducts();
            //campos Retirada, CDPRODUTO , Retirada: QTTOTLANCTO, Devolvida : , Almoxerifado, Lote e data de validade
            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);
            }
            $response->setError(new Error($e->getmessage(), $e->getCode()));
        }
    }
    
    public function getCustfilial($filial){
        $nrorg = $this->environment->getNrOrgTrab();
        $entFilial = Paramfilial::findOneByCdfilialAndNrorg($filial, $nrorg);
        $tipoCusto = $entFilial->getCdtipcustest();
        return $tipoCusto;
    }

    public function consultaCustoQuantidadeProduto(Row $request, Response $response) {
        try {
            $dadosConsultaCusto = $request->getRow();

            $filial = $dadosConsultaCusto['CDFILIAL'];
            $tipoCusto = $dadosConsultaCusto['CDTIPOCUST'];
            $produto = $dadosConsultaCusto['CDPRODUTO'];
            $almoxarifado = $dadosConsultaCusto['CDALMOXARIFE'];
            $localEstoque = $dadosConsultaCusto['CDLOCALESTOQ'];
            $lote = $dadosConsultaCusto['NRLOTE'];
            $subLote = $dadosConsultaCusto['NRSUBLOTE'];
            $dtLancamento = $dadosConsultaCusto['DTLANCAMENTO'];
            
            if(!$tipoCusto){
                $tipoCusto = $this->getCustfilial($filial);
            }
            $custoQuantidade = $this->validacoesEstoqueService->consultaCustoQuantidadeProduto(
                $filial, $produto, $dtLancamento, $tipoCusto, $almoxarifado, $localEstoque, $lote, $subLote
            );
            $response->addDataset(new DataSet('consultaCustoQuantidadeProduto', $custoQuantidade));
        } catch (\Exception $e) {
            $response->setError(new Error($e->getmessage(), $e->getCode()));
        }
    }
}