<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\ResponseController;
use App\Http\Controllers\ResourcesController;
use App\Http\Controllers\EncryptionController;
use App\Http\Controllers\DocumentManagementController;
use App\Http\Controllers\FunctionsController;

class InvoiceControlController extends Controller {

    private $responseController;
    private $encController;
    private $resourcesController;
    private $functionsController;
    private $documentManagementController;

    public function __construct() {
        $this->responseController = new ResponseController();
        $this->encController = new EncryptionController();
        $this->resourcesController = new ResourcesController();
        $this->functionsController = new FunctionsController();
        $this->documentManagementController = new DocumentManagementController();
    }

    public function getCompareInvoice($line) {
        try {
            $getInvoice = DB::table('S002V01TFALS')
                ->where('FALS_NULI', '=', $line)
                ->get([
                    'FALS_IDFA',
                    'FALS_IDLI',
                    'FALS_CODO',
                    'FALS_UUID',
                    'FALS_VERS',
                    'FALS_FEEM',
                    'FALS_RFCE',
                    'FALS_RFCR',
                    'FALS_FOLI',
                    'FALS_SERI',
                    'FALS_FOPA',
                    'FALS_MEPA',
                    'FALS_TICA',
                    'FALS_MONE',
                    'FALS_COPA',
                    'FALS_ESTA',
                    'FALS_USRE',
                    'FALS_FERE',
                    'FALS_USMO',
                    'FALS_FEMO',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_INVOICE_GET000: Ocurrió un error al obtener las facturas.", [], 500);
        }
        $arrInvoice = json_decode(json_encode($getInvoice), true);
        return $this->responseController->makeResponse(false, "ÉXITO: Consulta Exitosa", $arrInvoice);
    }

    public function compareInvoice(Request $request) {
        $validator = Validator::make($request->all(), [
            'IDARCHIVOPDF' => 'required|string',
            'IDARCHIVOXML' => 'required|string',
            'USER' => 'required|string',
            'LINE_NUMBER' => 'required|string',
            'REQUEST_LINE' => 'required|integer',
        ]);
        if ($validator->fails()) {
            return $this->responseController->makeResponse(
                true,
                "ERR_INVOICE_COMPARE000: Se encontraron uno o más errores.",
                $this->responseController->makeErrors($validator->errors()->messages()),
                401
            );
        }

        $responseData = $request->all();
        DB::beginTransaction();


        try {
            $idArchivoPDF = $this->encController->decrypt($responseData['IDARCHIVOPDF']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE001: Ocurrió un error al recuperar el archivo PDF.", [], 500);
        }
        try {
            $idArchivoXML = $this->encController->decrypt($responseData['IDARCHIVOXML']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE002: Ocurrió un error al recuperar el archivo XML.", [], 500);
        }
        try {
            $user = $this->encController->decrypt($responseData['USER']);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE003: Ocurrió un error al recuperar el usuario.", [], 500);
        }

        try {
            $fileTempDataXML = DB::table('S002V01TARTE')
                ->where('ARTE_NULI', '=', $responseData['LINE_NUMBER'])
                ->where('ARTE_IDAR', '=', $idArchivoXML)
                ->where('ARTE_ESTA', '=', 'Activo')
                ->first([
                    'ARTE_IDAR',
                    'ARTE_NULI',
                    'ARTE_NOAR',
                    'ARTE_EXTE',
                    'ARTE_TAMA',
                    'ARTE_UBTE',
                    'ARTE_ESTA',
                    'ARTE_USRE',
                    'ARTE_FERE',
                    'ARTE_USMO',
                    'ARTE_FEMO',
                    'ARTE_FEAR',
                ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true,"ERR_INVOICE_COMPARE004: Ocurrió un error al obtener la información de la base de datos del documento.",$th->getMessage(),500);
        }

        if (is_null($fileTempDataXML)) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE005: No se pudo obtener la información del documento.", [], 401);
        }
        if($fileTempDataXML->ARTE_ESTA == 'Eliminado'){
            return $this->responseController->makeResponse(true, 'ERR_INVOICE_COMPARE006: El archivo consultado está eliminado', [], 404);
        }

        if ( !file_exists($fileTempDataXML->ARTE_UBTE) ) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE007: No se pudo obtener el documento.", [], 401);
        }

        try {
            $arrLineRequestData = DB::table('S002V01TLINE')
                ->where('LINE_NULI', '=', $responseData['LINE_NUMBER'])
                ->where('LINE_IDLI', '=', $responseData['REQUEST_LINE'])
                ->where('LINE_ESTA', '=', 'En espera')
                ->where('ARSE_ESTA', '=', 'Activo')
                ->where('ARSE_NULI', '=', $responseData['LINE_NUMBER'])
                ->join('S002V01TARSE', 'ARSE_IDLI','=', 'LINE_IDLI')
                ->join('S002V01TINAR', 'INAR_IDIN','=', 'ARSE_IDIN')
                ->join('S002V01TCAMO', 'CAMO_COMO','=', 'INAR_COMO')
                ->join('S002V01TDEAR', 'DEAR_IDDE','=', 'INAR_IDDE')
                ->join('S002V01TARTI', 'ARTI_IDAR','=', 'DEAR_IDAR')
                ->join('S002V01TUNID', 'UNID_IDUN','=', 'DEAR_IDUN')
                ->join('S002V01TPROV', 'PROV_NUPR','=', 'ARSE_NUPR')
                ->get([
                    'LINE_IDLI',
                    'LINE_NUOR',
                    'LINE_OTPR',
                    'LINE_OTCO',
                    'ARSE_IDAS',
                    'ARSE_CANT',
                    'ARSE_PRTO',
                    'INAR_IDIN',
                    'INAR_CODI',
                    'INAR_MODE',
                    'INAR_COMO',
                    'INAR_PREC',
                    'INAR_MOMI',
                    'INAR_CARA',
                    'CAMO_COMO',
                    'CAMO_DESC',
                    'CAMO_DECI',
                    'CAMO_POVA',
                    'CAMO_FEIN',
                    'CAMO_FEFI',
                    'DEAR_IDDE',
                    'DEAR_IMAG',
                    'DEAR_DESC',
                    'DEAR_CARA',
                    'DEAR_COWE',
                    'ARTI_IDAR',
                    'ARTI_IDFA',
                    'ARTI_IDSU',
                    'ARTI_CODI',
                    'ARTI_NOMB',
                    'UNID_IDUN',
                    'UNID_NOMB',
                    'UNID_ACRO',
                    'PROV_NUPR',
                    'PROV_NOCO',
                    'PROV_NOMB',
                    'PROV_APPA',
                    'PROV_APMA',
                    'PROV_CORR',
                    'PROV_LAD1',
                    'PROV_TEL1',
                    'PROV_LAD2',
                    'PROV_TEL2',
                    'PROV_XRFC',
                    'PROV_XTAX',
                    'PROV_CRFI',
                    'PROV_TIPO',
                    'PROV_TICO',
                    'PROV_SIWE',
                    'PROV_MEPA',
                    'PROV_CALL',
                    'PROV_NUEX',
                    'PROV_NUIN',
                    'PROV_COPO',
                    'PROV_COLO',
                    'PROV_MUNI',
                    'PROV_LOCA',
                    'PROV_ENTI',
                    'PROV_PAIS',
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true,"ERR_INVOICE_COMPARE008: Ocurrió un error al obtener la información de la base de datos del documento.",$th->getMessage(),500);
        }
        $arrLineRequestData = json_decode(json_encode($arrLineRequestData),true);
        if (empty($arrLineRequestData)) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE009: No se pudo obtener la información de la línea de solicitud de compra.", [], 401);
        }

        try {
            $xml = simplexml_load_file($fileTempDataXML->ARTE_UBTE, 'SimpleXMLElement', LIBXML_NOCDATA);
            $ns = $xml->getNamespaces(true);
            $xml->registerXPathNamespace('c', $ns['cfdi']);
            $xml->registerXPathNamespace('t', $ns['tfd']);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE010: Ocurrió un error al obtener la información del documento.", $th->getMessage(), 500);
        }

        $arrResponseComprobante = $this->validateComprobante($xml, $arrLineRequestData, $responseData['LINE_NUMBER']);
        if ($arrResponseComprobante['error']) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE011: Ocurrió un error al válidar el documento: ".$arrResponseComprobante['msg'], $arrResponseComprobante['errors'], 401);
        }
        $arrComprobante = $arrResponseComprobante['response'];

        $arrResponseEmisor = $this->validateEmisor($xml, $arrLineRequestData, $responseData['LINE_NUMBER']);
        if ($arrResponseEmisor['error']) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE012: Ocurrió un error al válidar el documento: ".$arrResponseEmisor['msg'], $arrResponseEmisor['errors'], 401);
        }
        $arrEmisor = $arrResponseEmisor['response'];

        $arrResponseReceptor = $this->validateReceptor($xml, $arrLineRequestData[0], $responseData['LINE_NUMBER']);
        if ($arrResponseReceptor['error']) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE013: Ocurrió un error al válidar el documento: ".$arrResponseReceptor['msg'], $arrResponseReceptor['errors'], 401);
        }
        $arrReceptor = $arrResponseReceptor['response'];

        $arrResponseConceptos = $this->validateConceptos($xml, $arrLineRequestData, $responseData['LINE_NUMBER']);
        if ($arrResponseConceptos['error']) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE014: Ocurrió un error al válidar el documento: ".$arrResponseConceptos['msg'], $arrResponseConceptos['errors'], 401);
        }
        $arrConceptos = $arrResponseConceptos['response'];
        

        $arrResponseTimbreFiscal = $this->validateTimbreFiscal($xml);
        if ($arrResponseTimbreFiscal['error']) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE015: Ocurrió un error al válidar el documento: ".$arrResponseTimbreFiscal['msg'], $arrResponseTimbreFiscal['errors'], 401);
        }
        $arrTimbreFiscal = $arrResponseTimbreFiscal['response'];


        $fileResponse = $this->documentManagementController->moveFinalFile(
            intval($responseData['LINE_NUMBER']),
            'GEAD',
            'FA',
            $fileTempDataXML,
            $user,
        );
        if(!$fileResponse[0]){
            return $this->responseController->makeResponse(true, 'ERR_INVOICE_COMPARE016: '.$fileResponse[1], [], 400);
        }
        $encCodeXML = $this->encController->encrypt($fileResponse[1]);
        
        $now = $this->functionsController->now();
        $currentDate = $now->toDateTimeString();

        try {
            $idFacturaXml = DB::table('S002V01TFALS')->insertGetId([
                'FALS_NULI' => $responseData['LINE_NUMBER'],
                'FALS_IDLI' => $responseData['REQUEST_LINE'],
                'FALS_CODO' => $encCodeXML,
                'FALS_UUID' => $arrTimbreFiscal['UUID'],
                'FALS_VERS' => $arrComprobante['Version'],
                'FALS_FEEM' => $arrComprobante['Fecha'],
                'FALS_RFCE' => $arrEmisor['Rfc'],
                'FALS_RFCR' => $arrReceptor['Rfc'],
                'FALS_FOLI' => $arrComprobante['Folio'],
                'FALS_SERI' => $arrComprobante['Serie'],
                'FALS_FOPA' => $arrComprobante['FormaPago'],
                'FALS_MEPA' => $arrComprobante['MetodoPago'],
                'FALS_TICA' => $arrComprobante['TipoCambio'],
                'FALS_MONE' => $arrComprobante['Moneda'],
                'FALS_COPA' => $arrComprobante['CondicionesDePago'],
                'FALS_USRE' => $responseData['LINE_NUMBER'],
                'FALS_FERE' => $currentDate,
                'FALS_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
            ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE017: Ocurrió un error al registrar la factura.", $th->getMessage(), 401);
        }
        if (!$idFacturaXml) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE018: No se pudo registrar la factura.", 401);
        }
        
        $fileTempDataPDF = DB::table('S002V01TARTE')->where([
            ['ARTE_NULI', '=', $responseData['LINE_NUMBER']],
            ['ARTE_IDAR', '=', $idArchivoPDF],
        ])->first();

        if(is_null($fileTempDataPDF)){
            return $this->responseController->makeResponse(true, 'ERR_INVOICE_COMPARE019: El archivo consultado no está registrado', [], 404);
        }else if($fileTempDataPDF->ARTE_ESTA == 'Eliminado'){
            return $this->responseController->makeResponse(true, 'ERR_INVOICE_COMPARE020: El archivo consultado está eliminado', [], 404);
        }
        $fileResponse = $this->documentManagementController->moveFinalFile(
            intval($responseData['LINE_NUMBER']),
            'GEAD',
            'FA',
            $fileTempDataPDF,
            $user,
        );
        if(!$fileResponse[0]){
            return $this->responseController->makeResponse(true, 'ERR_INVOICE_COMPARE021: '.$fileResponse[1], [], 400);
        }
        $encCodePDF = $this->encController->encrypt($fileResponse[1]);

        try {
            $validateInsert = DB::table('S002V01TDLSC')
                ->insert([
                    'DLSC_NULI' => $responseData['LINE_NUMBER'],
                    'DLSC_IDLI' => $responseData['REQUEST_LINE'],
                    'DLSC_IDFA' => $idFacturaXml,
                    'DLSC_CODO' => $encCodePDF,
                    'DLSC_TIPO' => 'Cotización',
                    'DLSC_USRE' => $user,
                    'DLSC_FERE' => $currentDate,
                    'DLSC_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
                ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE022: Ocurrió un error al registrar la factura.", $th->getMessage(), 401);
        }
        if (!$validateInsert) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE023: No se pudo registrar la factura.", 401);
        }


        try {
            $validateUpdate = DB::table('S002V01TLINE')
                ->where('LINE_IDLI', '=', $responseData['REQUEST_LINE'])
                ->where('LINE_ESTA', '=', 'En espera')
                ->where('LINE_NULI', '=', $responseData['LINE_NUMBER'])
                ->update([
                    'LINE_ESTA' => 'Analizado',
                    'LINE_USMO' => $user,
                    'LINE_FEMO' => $currentDate,
                    'LINE_FEAR' => DB::raw('CURRENT_TIMESTAMP'),
                ]);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE024: Ocurrió un error al modificar la solicitud la factura.", $th->getMessage(), 401);
        }
        if (!$validateUpdate) {
            DB::rollBack();
            return $this->responseController->makeResponse(true, "ERR_INVOICE_COMPARE025: No se pudo modificar línea de solicitud de compra.", 401);
        }

        DB::commit();
        return $this->responseController->makeResponse(false, "ÉXITO: Registro Exitoso");
    }

    private function validateComprobante($xml, $arrLineRequestData, $line) {
        $arrResponseFunction = array('error' => false, 'msg' => '', 'response' => [], 'errors' => []);
        $arrComprobante = json_decode(json_encode($xml), true);
        $arrComprobante = $arrComprobante['@attributes'];

        if ($arrComprobante['Version'] != '4.0') {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'La versión de la factura no es 4.0.';
        }
        
        foreach ($arrLineRequestData as $keyLineRequestData => $lineRequestData) {
            if ($arrComprobante['Moneda'] != $lineRequestData['INAR_COMO']) {
                $arrResponseFunction['error'] = true;
                $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
                $arrResponseFunction['errors'][] = 'El tipo de moneda es diferente.';
            }
        }
        

        $arrResponseFunction['response'] = $arrComprobante;
        fin_validateComprobante:
        return $arrResponseFunction;
    }

    private function validateEmisor($xml, $arrLineRequestData, $line) {
        $arrResponseFunction = array('error' => false, 'msg' => '', 'response' => [], 'errors' => []);
        try {
            $arrEmisor = $xml->xpath('//cfdi:Comprobante//cfdi:Emisor');
            $arrEmisor = json_decode(json_encode($arrEmisor), true);
            $arrEmisor = $arrEmisor[0]['@attributes'];
        } catch (\Throwable $th) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error a obtener el contenido de la factura.';
            $arrResponseFunction['response'] = $th->getMessage();
            goto fin_validateEmisor;
        }

        try {
            $arrTaxInformation = (array) DB::table('S002V01TINFI')
                ->where('INFI_NULI', '=', $line)
                ->where('INFI_ESTA', '=', 'Activo')
                ->first([
                    'INFI_XRFC',
                    'INFI_NOFI',
                    'INFI_CORF',
                ]);
        } catch (\Throwable $th) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error a obtener los datos de la información fiscal';
            $arrResponseFunction['response'] = $th->getMessage();
            goto fin_validateEmisor;
        }

        if (empty($arrTaxInformation)) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al obtener los datos fiscales.';
            $arrResponseFunction['response'] = $th->getMessage();
            goto fin_validateEmisor;
        }

        if ($arrTaxInformation['INFI_XRFC'] != $arrEmisor['Rfc']) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el R.F.C del emisor.';
        }
        if ($arrTaxInformation['INFI_NOFI'] != $arrEmisor['Nombre']) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el Nombre del emisor.';
        }
        if ($arrTaxInformation['INFI_CORF'] != $arrEmisor['RegimenFiscal']) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el Regimen Fiscal del emisor.';
        }

        $arrResponseFunction['response'] = $arrEmisor;
        fin_validateEmisor:
        return $arrResponseFunction;
    }

    private function validateReceptor($xml, $arrLineRequestData, $line) {
        $arrResponseFunction = array('error' => false, 'msg' => '', 'response' => [], 'errors' => []);
        try {
            $arrReceptor = $xml->xpath('//cfdi:Comprobante//cfdi:Receptor');
            $arrReceptor = json_decode(json_encode($arrReceptor), true);
            $arrReceptor = $arrReceptor[0]['@attributes'];
        } catch (\Throwable $th) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error a obtener el contenido de la factura.';
            $arrResponseFunction['response'] = $th->getMessage();
            goto fin_validateReceptor;
        }


        if (strtoupper($arrReceptor['Rfc']) != strtoupper($arrLineRequestData['PROV_XRFC'])) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el R.F.C de la factura del receptor.';
        }
        if (strtolower($arrReceptor['Nombre']) != strtolower($arrLineRequestData['PROV_NOCO'])) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar Nombre de la factura del receptor.';
        }
        if ($arrReceptor['DomicilioFiscalReceptor'] != $arrLineRequestData['PROV_COPO']) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el Domicilio Fiscal de la factura del receptor.';
        }
        if ($arrReceptor['RegimenFiscalReceptor'] != $arrLineRequestData['PROV_CRFI']) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
            $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el Régimen Fiscal de la factura del receptor.';
        }

        $arrResponseFunction['response'] = $arrReceptor;
        fin_validateReceptor:
        return $arrResponseFunction;
    }

    private function validateConceptos($xml, $arrLineRequestData, $line) {
        $arrResponseFunction = array('error' => false, 'msg' => '', 'response' => [], 'errors' => []);
        try {
            $arrConceptos = $xml->xpath('//cfdi:Comprobante//cfdi:Conceptos//cfdi:Concepto');
            $arrConceptos = json_decode(json_encode($arrConceptos), true);
        } catch (\Throwable $th) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error a obtener el contenido de la factura.';
            $arrResponseFunction['response'] = $th->getMessage();
            goto fin_valdiateConcepto;
        }

        foreach ($arrConceptos as $keyConceptos => $conceptos) {
            if (array_key_exists('@attributes', $conceptos)) {
                $conceptos = $conceptos['@attributes']; 
                $arrConceptos[$keyConceptos] = $conceptos;
            }


            foreach ($arrLineRequestData as $keyLineRequestData => $lineRequestData) {
                $countErrors = 0;
                if($conceptos['Cantidad'] != $lineRequestData['ARSE_CANT']){
                    $arrResponseFunction['error'] = true;
                    $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
                    $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar la Cantidad del concepto.';
                    $countErrors++;
                }
                if($conceptos['Unidad'] != $lineRequestData['UNID_NOMB']){
                    $arrResponseFunction['error'] = true;
                    $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
                    $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar la Unidad del concepto.';
                    $countErrors++;
                }
                if($conceptos['Descripcion'] != $lineRequestData['INAR_CODI']){
                    $arrResponseFunction['error'] = true;
                    $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
                    $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar la Descripción del concepto.';
                    $countErrors++;
                }
                if($conceptos['ValorUnitario'] != $lineRequestData['INAR_PREC']){
                    $arrResponseFunction['error'] = true;
                    $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
                    $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el Valor Unitario del concepto.';
                    $countErrors++;
                }
                if($conceptos['Importe'] != $lineRequestData['ARSE_PRTO']){
                    $arrResponseFunction['error'] = true;
                    $arrResponseFunction['msg'] = 'Ocurrió un error al válidar los atributuos de la factura.';
                    $arrResponseFunction['errors'][] = 'Ocurrió un error al válidar el Importe del concepto.';
                    $countErrors++;
                }
                if ($countErrors == 0) {
                    $arrResponseFunction['error'] = false;
                    $arrResponseFunction['msg'] = '';
                    $arrResponseFunction['errors'] = [];
                    break;
                }
            }

            if ($arrResponseFunction['error']) {
                goto fin_valdiateConcepto;
            }
        }
        $arrResponseFunction['response'] = $arrConceptos;
        fin_valdiateConcepto:
        return $arrResponseFunction;
    }

    private function validateTimbreFiscal($xml) {
        $arrResponseFunction = array('error' => false, 'msg' => '', 'response' => [], 'errors' => []);
        try {
            $arrTimbreFiscal = $xml->xpath('//t:TimbreFiscalDigital');
            $arrTimbreFiscal = json_decode(json_encode($arrTimbreFiscal), true);
            $arrTimbreFiscal = $arrTimbreFiscal[0]['@attributes'];
        } catch (\Throwable $th) {
            $arrResponseFunction['error'] = true;
            $arrResponseFunction['msg'] = 'Ocurrió un error a obtener el contenido de la factura.';
            $arrResponseFunction['response'] = $th->getMessage();
            goto fin_validateTimbreFiscal;
        }

        $arrResponseFunction['response'] = $arrTimbreFiscal;

        fin_validateTimbreFiscal:
        return $arrResponseFunction;
    }
}
