<?php

namespace App\Http\Controllers\Base;

use ZipArchive;
use App\Helpers\Helper;
use App\Helpers\PacHelper;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use App\Models\Base\Company;
use Illuminate\Http\Request;
use App\Models\Base\CfdiDownload;
use App\Models\Catalogs\CfdiType;
use App\Models\Catalogs\Currency;
use Chumper\Zipper\Facades\Zipper;
use App\Models\Catalogs\PaymentWay;
use App\Exports\CfdiDownloadsExport;
use App\Http\Controllers\Controller;
use App\Models\Catalogs\ExpenseType;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Crypt;
use App\Helpers\UtilCertificadoHelper;
use App\Helpers\BusquedaEmitidosHelper;
use App\Models\Base\BankMoveReconciled;
use App\Helpers\BusquedaRecibidosHelper;
use App\Helpers\DescargaAsincronaHelper;
use App\Models\Base\CfdiDownloadPayment;
use App\Models\Base\CfdiDownloadRequest;
use App\Models\Catalogs\OperationalType;
use PhpCfdi\SatWsDescargaMasiva\Service;
use App\Helpers\DescargaMasivaCfdiHelper;
use App\Models\Base\CfdiDownloadRequestFile;
use App\Exports\CfdiDownloadsCustomerPaymentExport;
use App\Exports\CfdiDownloadsEmployeePayrollExport;
use PhpCfdi\SatWsDescargaMasiva\Shared\RequestType;
use PhpCfdi\SatWsDescargaMasiva\Shared\DownloadType;
use PhpCfdi\SatWsDescargaMasiva\Shared\DateTimePeriod;
use PhpCfdi\SatWsDescargaMasiva\WebClient\GuzzleWebClient;
use PhpCfdi\SatWsDescargaMasiva\Services\Query\QueryParameters;
use PhpCfdi\SatWsDescargaMasiva\PackageReader\MetadataPackageReader;
use PhpCfdi\SatWsDescargaMasiva\RequestBuilder\FielRequestBuilder\Fiel;
use PhpCfdi\SatWsDescargaMasiva\RequestBuilder\FielRequestBuilder\FielRequestBuilder;

class CfdiDownloadController extends Controller
{

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        if(empty(setting('cfdi_download')) && !\Auth::user()->new_user){
            return redirect()->route('home');
        }

        //Variables
        $limit = ($request->has('limit') ? $request->get('limit') : 100);
        $cfdi_types = CfdiType::populateSelect()->pluck('name','id');
        $sat_status = __('general.text_sat_status');
        //fix para exportar todos
        if(!empty($request->download_xmlpdf) || !empty($request->validate_status_sat)){
            $request->request->add([
                'page' => 1
            ]);
            $limit = 1000000;
        }
        if (empty($request->filter_date_from)) {
            $request->request->add([
                'filter_date_from' => Helper::date(\Date::parse('first day of this month')->subMonth())
            ]);
        }
        if (empty($request->filter_date_to)) {
            $request->request->add([
                'filter_date_to' => Helper::date(\Date::parse('last day of this month'))
            ]);
        }

        //Consulta
        $results = CfdiDownload::filter($request->all())
            ->with('currency')
            ->with('paymentWay')
            ->with('paymentMethod')
            ->with('cfdiUse')
            ->with('cfdiType')
            ->with('blackListSatEmisor')
            ->with('blackListSatReceptor')
            ->sortable(['date' => 'desc'])->paginate($limit);

        /*foreach ($results as $result) {
            if (!empty($result->file_xml)) {
                $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES, $result->company_id) . '/';
                $file_xml = $path_files . $result->file_xml;
                $data_xml = Helper::parseXmlToArrayCfdi33($file_xml);
                if(!empty($data_xml['data']['cfdi_type_id'])){
                    $result->cfdi_type_id = $data_xml['data']['cfdi_type_id'];
                    $result->save();
                }
            }
        }*/

        //Valida estatus del CFDI
        if(!empty($request->validate_status_sat)){
            if($results->isNotEmpty()) {
                $cfdi_updated = 0;
                foreach ($results as $result) {
                    if (!empty($result->file_xml)) {
                        $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES, $result->company_id) . '/';
                        $file_xml = $path_files . $result->file_xml;
                        if (\Storage::exists($file_xml)) {
                            $tmp['file_xml_pac'] = $file_xml;
                            $data_status_sat = PacHelper::satStatus($tmp);
                            if($result->status != $data_status_sat['pac_status'] || $result->is_cancelable != $data_status_sat['pac_is_cancelable']){
                                $result->status = $data_status_sat['pac_status'];
                                $result->is_cancelable = $data_status_sat['pac_is_cancelable'];
                                $result->save();
                                $cfdi_updated++;
                            }
                        }
                    }
                }
                flash(sprintf(__('base/cfdi_download.text_success_cfdi_updated'),$cfdi_updated))->success();
            }
        }

        //Descar zip de XML´s y PDF´s
        if(!empty($request->download_xmlpdf)){
            if($results->isNotEmpty()) {
                $company = Helper::defaultCompany();
                $file_zip_name = __('base/cfdi_download.document_title_download_xmlpdf') .'_' . $company->taxid .'_'. str_replace(['-','/'],['',''],$request->filter_date_from).'_'. str_replace(['-','/'],['',''],$request->filter_date_to) .'_'.random_int(10,99).'.zip';
                if(\Storage::exists('temp/' . $file_zip_name)) {
                    @\Storage::delete('temp/' . $file_zip_name);
                }
                $zip =\Zipper::make(\Storage::path('temp/' . $file_zip_name));

                foreach ($results as $result) {
                    if (!empty($result->file_xml)) {

                        //Ruta y validacion
                        $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES, $result->company_id) . '/';
                        $file_xml = $path_files . $result->file_xml;
                        if (\Storage::exists($file_xml)) {
                            $zip->add(\Storage::path($file_xml), $result->uuid . '.xml');
                        }
                        if(!empty($result->file_pdf)) {
                            $file_pdf = $path_files . $result->file_pdf;
                            if (\Storage::exists($file_pdf)) {
                                $zip->add(\Storage::path($file_pdf), $result->uuid . '.pdf');
                            }
                        }
                        if(!empty($result->file_acuse)) {
                            $file_acuse = $path_files . $result->file_acuse;
                            if (\Storage::exists($file_acuse)) {
                                $zip->add(\Storage::path($file_acuse), $result->uuid . '-acuse.pdf');
                            }
                        }
                    }
                }
                $zip->close();
                if(\Storage::exists('temp/' . $file_zip_name)) {
                    while (ob_get_level()) ob_end_clean();
                    ob_start();

                    return response()->download(\Storage::path('temp/' . $file_zip_name));
                }else{
                    flash(__('base/cfdi_download.error_download_xmlpdf'))->warning();
                }
            }
        }

        //Vista
        return view('base.cfdi_downloads.index', compact('results','cfdi_types','sat_status'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Base\CfdiDownload  $cfdi_download
     * @return \Illuminate\Http\Response
     */
    public function show(CfdiDownload $cfdi_download)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Base\CfdiDownload  $cfdi_download
     * @return \Illuminate\Http\Response
     */
    public function edit(CfdiDownload $cfdi_download)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Base\CfdiDownload  $cfdi_download
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, CfdiDownload $cfdi_download)
    {
        //
        if ($request->ajax()) {

            $cfdi_download->expense_type_id = $request->expense_type_id;
            $cfdi_download->operational_type_id = $request->operational_type_id ?? null;
            $cfdi_download->comment_2 = $request->comment_2 ?? '';
            $cfdi_download->save();

            $data = [
                'id' => $cfdi_download->id,
                'expense_type' => $cfdi_download->expenseType->name ?? '',
                'msg_success' => __('general.text_form_success_edit')
            ];

            return response()->json($data, 200);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Base\CfdiDownload  $cfdi_download
     * @return \Illuminate\Http\Response
     */
    public function updateSelected(Request $request)
    {
        if(empty($request->selected)){
            return response()->json(['error' => __('base/cfdi_download.error_cfdi_download_selected')], 422);
        }

        //
        if ($request->ajax()) {

            $data= [];

            //Aactualiza campo por campo
            $results = CfdiDownload::whereIn('id', $request->selected)
                ->update([
                    'expense_type_id' => !empty($request->expense_type_id) ? $request->expense_type_id : null,
                    'operational_type_id' => !empty($request->operational_type_id) ? $request->operational_type_id : null,
                    'comment_2' => !empty($request->comment_2) ? $request->comment_2 : null,
                ]);
            $data['msg_success'] = __('general.text_form_success_edit');

            return response()->json($data, 200);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Base\CfdiDownload  $cfdi_download
     * @return \Illuminate\Http\Response
     */
    public function deleteSelected(Request $request)
    {
        if(empty($request->selected)){
            return response()->json(['error' => __('base/cfdi_download.error_cfdi_download_selected')], 422);
        }

        //
        if ($request->ajax()) {

            $data = [];

            //Aactualiza campo por campo
            $results = CfdiDownload::whereIn('id', $request->selected)->delete();
            $data['msg_success'] = sprintf(__('base/cfdi_download.text_success_cfdi_delete'),count($request->selected));

            return response()->json($data, 200);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Base\CfdiDownload  $cfdi_download
     * @return \Illuminate\Http\Response
     */
    public function destroy(CfdiDownload $cfdi_download)
    {
        //
        if(BankMoveReconciled::where('reconciled_id', $cfdi_download->id)->count() > 0){
            //Mensaje
            flash(__('base/cfdi_download.error_cfdi_download_with_bank_reconciled'))->error();

            //Redireccion
            return redirect()->route('cfdi-downloads.index');
        }

        CfdiDownloadPayment::where('cfdi_download_id', $cfdi_download->id)->delete();

        //Logica
        $cfdi_download->delete();

        //Mensaje
        flash(__('general.text_form_success_delete'))->success();

        //Redireccion
        return redirect()->route('cfdi-downloads.index');
    }

    public function resetSatLogin(Request $request){
        $request->session()->forget('session_sat');
        $request->session()->forget('session_sat_fiel');
        //
        return redirect()->route('cfdi-downloads/create-sat-login');
    }

    public function createSatLogin(Request $request)
    {
        try
        {
            if(empty(setting('cfdi_download')) && !\Auth::user()->new_user){
                return redirect()->route('home');
            }

            //Valida si tiene permiso a descarga CFDI's
            if(!Helper::effectiveDateCfdiDownload()){
                flash(sprintf(__('base/cfdi_download.error_effective_date_cfdi_download'), Helper::convertSqlToDate(setting('effective_date_cfdi_download'))) )->error();
                return redirect()->route('cfdi-downloads.index');
            }

            $login_type = !empty($request->login_type) ? $request->login_type : 'login_password';

            if(!empty(session('session_sat')) && $login_type == 'login_password'){
                return redirect()->route('cfdi-downloads/create-cfdi-download');
            }

            if(!empty(session('session_sat_fiel')) && $login_type == 'efirma'){
                return redirect()->route('cfdi-downloads/create-cfdi-download-fiel');
            }

            $company = Helper::defaultCompany();
            $captcha = '';
            $token_session = '';
            if($login_type == 'login_password'){
                $descargaMasivaCfdi = new DescargaMasivaCfdiHelper();
                $captcha = $descargaMasivaCfdi->obtenerCaptcha();
                $token_session = $descargaMasivaCfdi->obtenerSesion();
            }

            return view('base.cfdi_downloads.create_sat_login', compact('login_type','captcha','token_session','company'));
        } catch (\Exception $e) {
            flash($e->getMessage())->error();
            return redirect()->route('cfdi-downloads.index');
        }
    }

    public function satLogin(Request $request){
        //Validacion

        //
        //Empresa default
        $company = Helper::defaultCompany();
        $rfc = $company->taxid;

        //
        try {

            if($request->login_type == 'login_password') {
                $request->session()->forget('session_sat_fiel');
                $descargaMasivaCfdi = new DescargaMasivaCfdiHelper();
                if(!empty($request->token_session)) {
                    $descargaMasivaCfdi->restaurarSesion($request->token_session);
                }
                if(!empty($rfc) && !empty($request->password)) {
                    // iniciar sesion en el SAT
                    $ok = $descargaMasivaCfdi->iniciarSesionCiecCaptcha($rfc,$request->password,$request->captcha);
                    if($ok) {
                        flash(__('base/cfdi_download.text_success_login_sat'))->success();
                        session(['session_sat' => $descargaMasivaCfdi->obtenerSesion()]);
                        return redirect()->route('cfdi-downloads/create-cfdi-download');
                    }else{
                        flash(__('base/cfdi_download.error_login_sat'))->error();
                        return redirect()->route('cfdi-downloads/create-sat-login');
                    }
                }else{
                    flash(__('base/cfdi_download.error_login_empty'))->error();
                    return redirect()->route('cfdi-downloads/create-sat-login');
                }
            }
            if($request->login_type == 'efirma') {
                $request->session()->forget('session_sat');
                if(!empty($rfc) && !empty($request->file_file_cer) && !empty($request->file_file_key) && !empty($request->fiel_password)) {
                    //Nueva forma de descargar con webservice 13-10-2020

                    //Guardamos los datos en la empresa
                    $name_file_cer = Str::random(40) . '.' . request()->file('file_file_cer')->getClientOriginalExtension();
                    $path_file_cer = request()->file('file_file_cer')->storeAs(Helper::setDirectory(Company::PATH_FILES,$company->id), $name_file_cer);
                    $company->fiel_file_cer = $name_file_cer;
                    $name_file_key = Str::random(40) . '.' . request()->file('file_file_key')->getClientOriginalExtension();
                    $path_file_key = request()->file('file_file_key')->storeAs(Helper::setDirectory(Company::PATH_FILES,$company->id), $name_file_key);
                    $company->fiel_file_key = $name_file_key;
                    $company->fiel_password_key = Crypt::encryptString($request->fiel_password);
                    $company->save();

                    //Validamos servicio
                    $service = $this->wsFielDownload($company);

                    session(['session_sat_fiel' => $service->obtainCurrentToken()]);
                    //
                    flash(__('base/cfdi_download.text_success_login_sat'))->success();
                    return redirect()->route('cfdi-downloads/create-cfdi-download-fiel');

                    // preparar certificado para inicio de sesion
                    /*$certificado = new UtilCertificadoHelper();
                    $ok = $certificado->loadFiles(
                        $request->file_file_cer,
                        $request->file_file_key,
                        $request->fiel_password
                    );
                    if($ok) {
                        // iniciar sesion en el SAT
                        $ok = $descargaMasivaCfdi->iniciarSesionFiel($certificado);
                        if($ok) {
                            flash(__('base/cfdi_download.text_success_login_sat'))->success();
                            session(['session_sat' => $descargaMasivaCfdi->obtenerSesion()]);
                            return redirect()->route('cfdi-downloads/create-cfdi-download');
                        }else{
                            flash(__('base/cfdi_download.error_login_sat'))->error();
                            return redirect()->route('cfdi-downloads/create-sat-login',['login_type' => 'efirma']);
                        }
                    }else{
                        flash(__('base/cfdi_download.error_login_fiel'))->error();
                        return redirect()->route('cfdi-downloads/create-sat-login',['login_type' => 'efirma']);
                    }*/
                }else{
                    flash(__('base/cfdi_download.error_login_empty'))->error();
                    return redirect()->route('cfdi-downloads/create-sat-login',['login_type' => 'efirma']);
                }
            }

            //Redirecciona
            return redirect()->route('cfdi-downloads.index');
        } catch (\Exception $e) {
            flash($e->getMessage())->error();
            return redirect()->route('cfdi-downloads/create-sat-login');
        }
    }

    public function createCfdiDownload(Request $request){
        if(empty(session('session_sat'))){
            return redirect()->route('cfdi-downloads/create-sat-login');
        }
        //
        $company = Helper::defaultCompany(); //Empresa
        $sat_status = __('general.text_sat_status');
        $descargaMasivaCfdi = new DescargaMasivaCfdiHelper();
        $descargaMasivaCfdi->restaurarSesion(session('session_sat'));

        //Logica
        $year_1 = \Date::now()->subYears(6)->format('Y');
        $year_2 = \Date::now()->format('Y');
        for($i=$year_1;$i <= $year_2;$i++){
            $years[$i] = $i;
        }
        $months = __('general.text_months');
        $days = array_combine(range(1,31),range(1,31));
        $hours = array_combine(range(0,23),range(0,23));
        $minutes = array_combine(range(0,59),range(0,59));


        return view('base.cfdi_downloads.create_cfdi_download', compact('years','months','days','hours','minutes', 'sat_status'));
    }

    public function cfdiDownloadRequest(Request $request){
        if(empty(session('session_sat'))){
            return response()->json(['error' => __('base/cfdi_download.error_login_sat')], 422);
        }

        try
        {
            //
            $company = Helper::defaultCompany(); //Empresa
            $descargaMasivaCfdi = new DescargaMasivaCfdiHelper();
            $descargaMasivaCfdi->restaurarSesion(session('session_sat'));

            //Consulta de datos
            $results = collect([]);

            //recibidos
            if(!empty($request->type) && $request->type == 1 && !empty($request->year) && !empty($request->month)){
                //
                $dataValidateQtyCfdiDownload = Helper::validateQtyCfdiDownload($request->year);
                if($dataValidateQtyCfdiDownload['error']){
                    flash($dataValidateQtyCfdiDownload['msg'])->error();
                    return redirect()->route('cfdi-downloads.index');
                }

                //
                $filtros = new BusquedaRecibidosHelper();
                $filtros->establecerFecha($request->year, $request->month, $request->day, $request->start_time_hour, $request->start_time_minute, $request->end_time_hour, $request->end_time_minute);
                $filtros->establecerTipoComplemento();
                if(!empty($request->status) && $request->status == 'Vigente'){
                    $filtros->establecerEstado(2);
                }
                if(!empty($request->status) && $request->status == 'Cancelado'){
                    $filtros->establecerEstado(6);
                }
                if(!empty($request->rfc_emisor)){
                    $filtros->establecerRfcEmisor($request->rfc_emisor);
                }
                if(!empty($request->uuid)){
                    $filtros->establecerFolioFiscal($request->uuid);
                }
                $xmlInfoArr = $descargaMasivaCfdi->buscar($filtros);
                if($xmlInfoArr === false){
                    flash(__('base/cfdi_download.error_cfdi_download_expired_session'))->error();
                    $request->session()->forget('session_sat');
                    return redirect()->route('cfdi-downloads/create-sat-login');
                }
                if($xmlInfoArr){
                    $uuids = [];
                    foreach ($xmlInfoArr as $xmlInfo) {
                        $xmlInfo = (array)$xmlInfo;
                        $uuids[] = $xmlInfo['folioFiscal'];
                        $results [] = (object)[
                            'url_xml' => $xmlInfo['urlDescargaXml'] ?? '',
                            'url_pdf' => $xmlInfo['urlDescargaRI'] ?? '',
                            'url_acuse' => $xmlInfo['urlDescargaAcuse'] ?? '',
                            'cfdi_type' => $xmlInfo['efecto'] ?? '',
                            'date' => $xmlInfo['fechaEmision'] ?? '',
                            'uuid' => $xmlInfo['folioFiscal'] ?? '',
                            'rfc_emisor' => $xmlInfo['emisorRfc'] ?? '',
                            'emisor' => $xmlInfo['emisorNombre'] ?? '',
                            'amount_total' => $xmlInfo['total'] ?? '',
                            'date_certification' => $xmlInfo['fechaCertificacion'] ?? '',
                            'rfc_pac' => $xmlInfo['pacCertifico'] ?? '',
                            'status' => $xmlInfo['estado'] ?? '',
                            'is_cancelable' => $xmlInfo['estadoCancelacion'] ?? '',
                            'date_cancel' => !empty($xmlInfo['fechaCancelacion']) ? str_replace('T',' ',$xmlInfo['fechaCancelacion']) : null,
                        ];
                    }
                    if(!empty($results)){
                        $cfdi_downloads = CfdiDownload::whereIn('uuid', $uuids)->where('company_id','=',$company->id)->pluck('uuid', 'uuid')->toArray();
                        $results = $results->map(function ($item) use($cfdi_downloads){
                            $item->downloaded = in_array($item->uuid, $cfdi_downloads);
                            return $item;
                        });
                    }
                }else{
                    return response()->json(['error' => __('base/cfdi_download.error_cfdi_download_empty')], 422);
                }
            }

            //emitidos
            if(!empty($request->type) && $request->type == 2 && !empty($request->filter_date_from) && !empty($request->filter_date_to)){
                $filtros = new BusquedaEmitidosHelper();
                $date_start = \Date::createFromFormat('d-m-Y', $request->filter_date_from);
                $date_end = \Date::createFromFormat('d-m-Y', $request->filter_date_to);

                //
                $dataValidateQtyCfdiDownload = Helper::validateQtyCfdiDownload($date_start->format('Y'));
                if($dataValidateQtyCfdiDownload['error']){
                    flash($dataValidateQtyCfdiDownload['msg'])->error();
                    return redirect()->route('cfdi-downloads.index');
                }

                $dataValidateQtyCfdiDownload = Helper::validateQtyCfdiDownload($date_end->format('Y'));
                if($dataValidateQtyCfdiDownload['error']){
                    flash($dataValidateQtyCfdiDownload['msg'])->error();
                    return redirect()->route('cfdi-downloads.index');
                }

                //
                $filtros->establecerFechaInicial($date_start->format('Y'), $date_start->format('m'), $date_start->format('d'), $request->start_time_hour2, $request->start_time_minute2);
                $filtros->establecerFechaFinal($date_end->format('Y'), $date_end->format('m'), $date_end->format('d'), $request->end_time_hour2, $request->end_time_minute2);
                $filtros->establecerTipoComplemento();
                if(!empty($request->status) && $request->status == 'Vigente'){
                    $filtros->establecerEstado(2);
                }
                if(!empty($request->status) && $request->status == 'Cancelado'){
                    $filtros->establecerEstado(6);
                }
                if(!empty($request->rfc_receptor)){
                    $filtros->establecerRfcReceptor($request->rfc_receptor);
                }
                if(!empty($request->uuid)){
                    $filtros->establecerFolioFiscal($request->uuid);
                }
                $xmlInfoArr = $descargaMasivaCfdi->buscar($filtros);
                if($xmlInfoArr === false){
                    flash(__('base/cfdi_download.error_cfdi_download_expired_session'))->error();
                    $request->session()->forget('session_sat');
                    return redirect()->route('cfdi-downloads/create-sat-login');
                }
                if($xmlInfoArr){
                    $uuids = [];
                    foreach ($xmlInfoArr as $xmlInfo) {
                        $xmlInfo = (array)$xmlInfo;
                        $uuids[] = $xmlInfo['folioFiscal'];
                        $results [] = (object)[
                            'url_xml' => $xmlInfo['urlDescargaXml'] ?? '',
                            'url_pdf' => $xmlInfo['urlDescargaRI'] ?? '',
                            'url_acuse' => $xmlInfo['urlDescargaAcuse'] ?? '',
                            'cfdi_type' => $xmlInfo['efecto'] ?? '',
                            'date' => $xmlInfo['fechaEmision'] ?? '',
                            'uuid' => $xmlInfo['folioFiscal'] ?? '',
                            'rfc_receptor' => $xmlInfo['receptorRfc'] ?? '',
                            'receptor' => $xmlInfo['receptorNombre'] ?? '',
                            'amount_total' => $xmlInfo['total'] ?? '',
                            'date_certification' => $xmlInfo['fechaCertificacion'] ?? '',
                            'rfc_pac' => $xmlInfo['pacCertifico'] ?? '',
                            'status' => $xmlInfo['estado'] ?? '',
                            'is_cancelable' => $xmlInfo['estadoCancelacion'] ?? '',
                            'date_cancel' => !empty($xmlInfo['fechaCancelacion']) ? str_replace('T',' ',$xmlInfo['fechaCancelacion']) : null,
                        ];
                    }
                    if(!empty($results)){
                        $cfdi_downloads = CfdiDownload::whereIn('uuid', $uuids)->where('company_id','=',$company->id)->pluck('uuid', 'uuid')->toArray();
                        $results = $results->map(function ($item) use($cfdi_downloads){
                            $item->downloaded = in_array($item->uuid, $cfdi_downloads);
                            return $item;
                        });
                    }
                }else{
                    return response()->json(['error' => __('base/cfdi_download.error_cfdi_download_empty')], 422);
                }
            }

            $type = $request->type ?? '';

            $html = view('layouts.partials.cfdi_downloads.cfdi_download_request', compact('type', 'results'))->render();
            return response()->json(['html' => $html]);
        }catch(\Exception $e){
            return response()->json(['error' => $e->getMessage()], 422);
        }
    }

    public function cfdiDownload(Request $request){
        try {
            $company = Helper::defaultCompany(); //Empresa
            $descargaMasivaCfdi = new DescargaMasivaCfdiHelper();
            $descargaMasivaCfdi->restaurarSesion(session('session_sat'));

            $descarga = new DescargaAsincronaHelper();
            $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES, $company->id);
            if ($request->type == '2') {
                $tmp_path = Str::random(5) . '/';
                if (!\Storage::exists($path_files . '/' . $tmp_path)) {
                    \Storage::makeDirectory($path_files . '/' . $tmp_path, 0777, true, true);
                    @shell_exec('chmod -R 777 ' . \Storage::path($path_files . '/' . $tmp_path));
                }
            } else {
                $tmp_path = Str::random(5) . '/';
                if (!\Storage::exists($path_files . '/' . $tmp_path)) {
                    \Storage::makeDirectory($path_files . '/' . $tmp_path, 0777, true, true);
                    @shell_exec('chmod -R 777 ' . \Storage::path($path_files . '/' . $tmp_path));
                }
            }
            $file_xml = $tmp_path;
            $to_download = [];

            //Descarga de XML
            if(!empty($request->xml)) {
                foreach ($request->xml as $folioFiscal => $url) {
                    $folioFiscal = strtoupper(trim($folioFiscal));
                    //$cfdi_download = CfdiDownload::where('company_id','=',$company->id)->where('uuid', '=', $folioFiscal)->first();
                    //Guarda arreglo de descargas
                    $to_download [$folioFiscal] = (object)[
                        'file_xml' => $file_xml . $folioFiscal . '.xml',
                        'file_pdf' => !empty($request->pdf) && array_key_exists($folioFiscal, $request->pdf) ? $file_xml . $folioFiscal . '.pdf' : '',
                        'file_acuse' => !empty($request->acuse) && array_key_exists($folioFiscal, $request->acuse) ? $file_xml . $folioFiscal . '-acuse' . '.pdf' : '',
                        'status' => !empty($request->status) && array_key_exists($folioFiscal, $request->status) ? $request->status[$folioFiscal] : '',
                        'is_cancelable' => !empty($request->is_cancelable) && array_key_exists($folioFiscal, $request->is_cancelable) ? $request->is_cancelable[$folioFiscal] : '',
                        'date_cancel' => !empty($request->date_cancel) && array_key_exists($folioFiscal, $request->date_cancel) ? $request->date_cancel[$folioFiscal] : null,
                    ];
                    //if(empty($cfdi_download)) {
                        // xml
                        $descarga->agregarXml($url, \Storage::path($path_files), $folioFiscal, $file_xml . $folioFiscal);
                    //}
                }
            }
            //Descarga de PDF
            if(!empty($request->pdf)) {
                foreach ($request->pdf as $folioFiscal => $url) {
                    $folioFiscal = strtoupper(trim($folioFiscal));
                    //Solo lo descarga si viene con el XML
                    if(!empty($to_download[$folioFiscal])) {
                        // representacion impresa
                        $descarga->agregarRepImpr($url, \Storage::path($path_files), $folioFiscal, $file_xml . $folioFiscal);
                    }else{
                        //Lo descarga si va a actualizar el PDF
                        $cfdi_download = CfdiDownload::where('company_id','=',$company->id)->where('uuid', '=', $folioFiscal)->first();
                        if(!empty($cfdi_download) || empty($to_download[$folioFiscal])) {
                            //Guarda arreglo de descargas
                            $to_download [$folioFiscal] = (object)[
                                'file_xml' => '',
                                'file_pdf' => $file_xml . $folioFiscal . '.pdf',
                                'file_acuse' => '',
                                'status' => !empty($request->status) && array_key_exists($folioFiscal, $request->status) ? $request->status[$folioFiscal] : '',
                                'is_cancelable' => !empty($request->is_cancelable) && array_key_exists($folioFiscal, $request->is_cancelable) ? $request->is_cancelable[$folioFiscal] : '',
                                'date_cancel' => !empty($request->date_cancel) && array_key_exists($folioFiscal, $request->date_cancel) ? $request->date_cancel[$folioFiscal] : null,
                            ];
                            // representacion impresa
                            $descarga->agregarRepImpr($url, \Storage::path($path_files), $folioFiscal, $file_xml . $folioFiscal);
                        }
                    }
                }
            }
            //Descarga de acuse
            if(!empty($request->acuse)) {
                foreach ($request->acuse as $folioFiscal => $url) {
                    $folioFiscal = strtoupper(trim($folioFiscal));
                    //Solo lo descarga si viene con el XML
                    if(!empty($to_download[$folioFiscal])) {
                        // acuse de resultado de cancelacion
                        $descarga->agregarAcuse($url, \Storage::path($path_files), $folioFiscal, $file_xml . $folioFiscal . '-acuse');
                    }else{
                        //Lo descarga si va a actualizar el PDF
                        $cfdi_download = CfdiDownload::where('company_id','=',$company->id)->where('uuid', '=', $folioFiscal)->first();
                        if(!empty($cfdi_download) || empty($to_download[$folioFiscal])) {
                            //Guarda arreglo de descargas
                            $to_download [$folioFiscal] = (object)[
                                'file_xml' => '',
                                'file_pdf' => '',
                                'file_acuse' => $file_xml . $folioFiscal . '-acuse' . '.pdf',
                                'status' => !empty($request->status) && array_key_exists($folioFiscal, $request->status) ? $request->status[$folioFiscal] : '',
                                'is_cancelable' => !empty($request->is_cancelable) && array_key_exists($folioFiscal, $request->is_cancelable) ? $request->is_cancelable[$folioFiscal] : '',
                                'date_cancel' => !empty($request->date_cancel) && array_key_exists($folioFiscal, $request->date_cancel) ? $request->date_cancel[$folioFiscal] : null,
                            ];
                            // representacion impresa
                            $descarga->agregarAcuse($url, \Storage::path($path_files), $folioFiscal, $file_xml . $folioFiscal . '-acuse');
                        }
                    }
                }
            }

            //
            $descarga->procesar();

            //Procesamos los archivos
            if(!empty($to_download)){
                foreach ($to_download as $folioFiscal => $download){
                    $folioFiscal = strtoupper(trim($folioFiscal));
                    $cfdi_download = CfdiDownload::where('company_id','=',$company->id)->where('uuid', '=', $folioFiscal)->first();
                    //Si ya se habia descargado solo actualiza informacion de los archivos
                    if(!empty($cfdi_download)) {

                        if(!empty($download->file_xml) && Helper::validateXmlToArrayCfdi332($path_files . '/' . $download->file_xml)){
                            $cfdi_download->file_xml = !empty($download->file_xml) ? $download->file_xml : $cfdi_download->file_xml;
                            $cfdi_download->file_pdf = !empty($download->file_pdf) ? $download->file_pdf : $cfdi_download->file_pdf;
                            $cfdi_download->file_acuse = !empty($download->file_acuse) ? $download->file_acuse : $cfdi_download->file_acuse;
                            $cfdi_download->status = !empty($download->file_acuse) ? $download->status : $cfdi_download->status;
                            $cfdi_download->is_cancelable = !empty($download->is_cancelable) ? $download->is_cancelable : $cfdi_download->is_cancelable;
                            $cfdi_download->date_cancel = !empty($download->date_cancel) ? $download->date_cancel : $cfdi_download->date_cancel;
                            $cfdi_download->save();

                            $data_xml = Helper::parseXmlToArrayCfdi33($path_files . '/' . $download->file_xml);
                            unset($data_xml['data']['balance']);
                            $cfdi_download->fill($data_xml['data']);
                            $cfdi_download->save();
                        }
                    }else{
                        //Valida si el CFDI es el correcto
                        //Leer XML para obtener los datos
                        if(!empty($download->file_xml) && Helper::validateXmlToArrayCfdi332($path_files . '/' . $download->file_xml)){
                            $cfdi_download = CfdiDownload::create([
                                'created_uid' => \Auth::user()->id,
                                'updated_uid' => \Auth::user()->id,
                                'type' => $request->type,
                                'uuid' => $folioFiscal,
                                'file_xml' => $download->file_xml,
                                'file_pdf' => $download->file_pdf,
                                'file_acuse' => $download->file_acuse,
                                'status' => $download->status,
                                'is_cancelable' => $download->is_cancelable,
                                'date_cancel' => $download->date_cancel,
                                'company_id' => $company->id,
                            ]);

                            $data_xml = Helper::parseXmlToArrayCfdi33($path_files . '/' . $download->file_xml);
                            $cfdi_download->fill($data_xml['data']);
                            $cfdi_download->save();
                        }
                    }
                }
            }

            //Cerramos la sesion
            //$request->session()->forget('session_sat');

            //Mensaje
            return response()->json(['message' => sprintf(__('base/cfdi_download.text_success_cfdi_download'),$descarga->totalDescargados(),$descarga->totalErrores(),$descarga->segundosTranscurridos())]);
        }catch(\Exception $e){
            return response()->json(['error' => __('base/cfdi_download.error_download_xml_session_sat') . '<br>' . $e->getMessage()], 422);
        }
    }

    public function createCfdiDownloadFiel(Request $request){
        if(empty(session('session_sat_fiel'))){
            return redirect()->route('cfdi-downloads/create-sat-login');
        }

        //
        $company = Helper::defaultCompany(); //Empresa

        if(!empty($request->filter_type) && !empty($request->filter_date_from) && !empty($request->filter_date_to)){
            //
            $date_start = \Date::createFromFormat('d-m-Y', $request->filter_date_from);
            $date_end = \Date::createFromFormat('d-m-Y', $request->filter_date_to);

            $dataValidateQtyCfdiDownload = Helper::validateQtyCfdiDownload($date_start->format('Y'));
            if($dataValidateQtyCfdiDownload['error']){
                flash($dataValidateQtyCfdiDownload['msg'])->error();
                return redirect()->route('cfdi-downloads.index');
            }

            $dataValidateQtyCfdiDownload = Helper::validateQtyCfdiDownload($date_end->format('Y'));
            if($dataValidateQtyCfdiDownload['error']){
                flash($dataValidateQtyCfdiDownload['msg'])->error();
                return redirect()->route('cfdi-downloads.index');
            }

            //
            $service = $this->wsFielDownload($company);

            //Realiza solicitud y la guarda
            $requestSw = QueryParameters::create(
                DateTimePeriod::createFromValues(Helper::convertDateToSql($request->filter_date_from). ' 00:00:00', Helper::convertDateToSql($request->filter_date_to) . ' 23:59:59'),
                ($request->filter_type == 1 ? DownloadType::received() : DownloadType::issued()),
                RequestType::cfdi(),''
            );
            $query = $service->query($requestSw);
            if (!$query->getStatus()->isAccepted()) {
                flash(__('base/cfdi_download_request.error_request_verify_1') . $query->getStatus()->getMessage())->error();
            }else{
                $requestId = $query->getRequestId();
                $cfdi_download_request= CfdiDownloadRequest::create([
                    'created_uid' => \Auth::user()->id,
                    'updated_uid' => \Auth::user()->id,
                    'date' => \Date::now(),
                    'folio' => $requestId,
                    'type' => $request->filter_type,
                    'date_start' => Helper::convertDateToSql($request->filter_date_from). ' 00:00:00',
                    'date_end' => Helper::convertDateToSql($request->filter_date_to) . ' 23:59:59',
                    'qty' => 0,
                    'folio_download' => null,
                    'file' => '',
                    'company_id' => $company->id,
                    'status' => 1
                ]);

                //Realiza solicitud de metadata
                $requestSw = QueryParameters::create(
                    DateTimePeriod::createFromValues(Helper::convertDateToSql($request->filter_date_from). ' 00:00:00', Helper::convertDateToSql($request->filter_date_to) . ' 23:59:59'),
                    ($request->filter_type == 1 ? DownloadType::received() : DownloadType::issued()),
                    RequestType::metadata(), ''
                );
                $query = $service->query($requestSw);
                if (!$query->getStatus()->isAccepted()) {
                    flash(__('base/cfdi_download_request.error_request_verify_2') . $query->getStatus()->getMessage())->error();
                }else{
                    $requestId = $query->getRequestId();
                    $cfdi_download_request->folio_metadata = $requestId;
                    $cfdi_download_request->save();
                }

                flash(__('base/cfdi_download_request.text_success_cfdi_download_request'))->success();
                return redirect()->route('cfdi-downloads/create-cfdi-download-fiel');
            }
        }

        //Obtiene registros solicitudes actuales
        $limit = ($request->has('limit') ? $request->get('limit') : 100);
        $results = CfdiDownloadRequest::filter([])->sortable(['date' => 'desc'])->paginate($limit);

        return view('base.cfdi_downloads.create_cfdi_download_fiel', compact('company','results'));
    }

    /**
     * Descarga de archivo XML
     *
     * @param Request $request
     * @param CfdiDownload $cfdi_download
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function downloadXml(Request $request, CfdiDownload $cfdi_download)
    {
        //Ruta y validacion del XML
        $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES,$cfdi_download->company_id) . '/';
        $file_xml = $path_files . $cfdi_download->file_xml;
        if (!empty($file_xml)) {
            if (\Storage::exists($file_xml)) {
                while (ob_get_level()) ob_end_clean();
                ob_start();

                return response()->download(\Storage::path($file_xml), $cfdi_download->uuid . '.xml', ['Cache-Control' => 'no-cache, must-revalidate']);
            }
        }

        //Mensaje
        flash(__('base/cfdi_download.error_download_xml'))->error();

        //Redireccion
        return redirect()->route('cfdi-downloads.index');
    }

    /**
     * Descarga de archivo PDF
     *
     * @param Request $request
     * @param CfdiDownload $cfdi_download
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function downloadPdf(Request $request, CfdiDownload $cfdi_download)
    {
        //Ruta y validacion del XML
        $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES,$cfdi_download->company_id) . '/';
        $file_pdf = $path_files . $cfdi_download->file_pdf;
        if (!empty($file_pdf)) {
            if (\Storage::exists($file_pdf)) {
                return response()->file(\Storage::path($file_pdf));
            }
        }

        //Mensaje
        flash(__('base/cfdi_download.error_download_pdf'))->error();

        //Redireccion
        return redirect()->route('cfdi-downloads.index');
    }

    /**
     * Descarga de archivo Acuse
     *
     * @param Request $request
     * @param CfdiDownload $cfdi_download
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function downloadAcuse(Request $request, CfdiDownload $cfdi_download)
    {
        //Ruta y validacion del XML
        $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES,$cfdi_download->company_id) . '/';
        $file_acuse = $path_files . $cfdi_download->file_acuse;
        if (!empty($file_acuse)) {
            if (\Storage::exists($file_acuse)) {
                return response()->file(\Storage::path($file_acuse));
            }
        }

        //Mensaje
        flash(__('base/cfdi_download.error_download_acuse'))->error();

        //Redireccion
        return redirect()->route('cfdi-downloads.index');
    }

    /**
     * Exportar datos a excel
     *
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
     */
    public function exportToExcel(Request $request)
    {
        while (ob_get_level()) ob_end_clean();
        ob_start();

        $cfdi_type = null;
        if($request->filter_cfdi_type_id) {
            $cfdi_type = CfdiType::findOrFail($request->filter_cfdi_type_id);
        }
        if(!empty($cfdi_type) && $cfdi_type->code == 'N'){ //Solo exporta la nomina
            return Excel::download(new CfdiDownloadsEmployeePayrollExport($request),
                __('base/cfdi_download.document_title_payroll_type') . '-' . config('app.name') . '.xlsx');
        } if(!empty($cfdi_type) && $cfdi_type->code == 'P'){ //Solo exporta los pagos

            if (empty($request->filter_date_from)) {
                $request->request->add([
                    'filter_date_from' => Helper::date(\Date::parse('first day of this month'))
                ]);
            }
            if (empty($request->filter_date_to)) {
                $request->request->add([
                    'filter_date_to' => Helper::date(\Date::parse('last day of this month'))
                ]);
            }
            $results = CfdiDownload::filter($request->all())->sortable(['date' => 'desc'])
                ->with('cfdiDownloadPayments')
                ->get();

            $data = [];
            if(!empty($results)){
                foreach($results as $row){
                    //Leer XML para obtener los conceptos
                    $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES,$row->company_id) . '/';
                    $file_xml = $path_files . $row->file_xml;
                    $cfdi_download_lines = '';
                    if (!empty($row->file_xml)) {
                        if (\Storage::exists($file_xml) && Helper::validateXmlToArrayCfdi33($file_xml)) {
                            $cfdi_download_lines = Helper::parseXmlToArrayCfdi33Conceptos($file_xml);
                        }
                    }

                    //Obtiene los pagos
                    $payments = '';
                    if ($row->cfdiDownloadPayments->isNotEmpty()) {
                        foreach ($row->cfdiDownloadPayments as $payment) {
                            $payments .= (!empty($payments) ? ' * ' : '') . Helper::convertSqlToDate($payment->date_payment) . '/' . ($payment->paymentWay->name ?? '') . '/' . money($payment->amount_payment,$row->currency->code ?? 'MXN',true);
                        }
                    }

                    //Obtener datos de impuestos
                    #$iva = 0;
                    $iva_16 = 0;
                    $iva_15 = 0;
                    $iva_11 = 0;
                    $iva_10 = 0;
                    $iva_8 = 0;
                    $ieps = 0;
                    $ret_iva = 0;
                    $ret_isr = 0;
                    if (!empty($file_xml)) {
                        if (\Storage::exists($file_xml) && Helper::validateXmlToArrayCfdi33($file_xml)) {
                            $tmp = Helper::parseXmlToArrayCfdi33Impuestos($file_xml);
                            #$iva = $tmp['iva'];
                            $iva_16 = $tmp['iva_16'];
                            $iva_15 = $tmp['iva_15'];
                            $iva_11 = $tmp['iva_11'];
                            $iva_10 = $tmp['iva_10'];
                            $iva_8 = $tmp['iva_8'];
                            $ieps = $tmp['ieps'];
                            $ret_iva = $tmp['ret_iva'];
                            $ret_isr = $tmp['ret_isr'];

                            if($row->cfdiType->name ?? '' == 'P'){
                                $tmp2 = [];
                                if($tmp['version'] == '4.0'){
                                    $tmp2 = Helper::parseXmlToArrayCfdi40PagosImpuestos($file_xml);
                                }elseif($tmp['version'] == '3.3'){
                                    $tmp2 = Helper::parseXmlToArrayCfdi33PagosImpuestos($file_xml, $path_files);
                                }

                                #$iva = $tmp['iva'];
                                $iva_16 += $tmp2['iva_16'] ?? 0;
                                $iva_15 += $tmp2['iva_15'] ?? 0;
                                $iva_11 += $tmp2['iva_11'] ?? 0;
                                $iva_10 += $tmp2['iva_10'] ?? 0;
                                $iva_8 += $tmp2['iva_8'] ?? 0;
                                $ieps += $tmp2['ieps'] ?? 0;
                                $ret_iva += $tmp2['ret_iva'] ?? 0;
                                $ret_isr += $tmp2['ret_isr'] ?? 0;

                                $row->amount_tax = $iva_16 + $iva_15 + $iva_11 + $iva_10 + $iva_8 + $ieps;
                                $row->amount_tax_ret = $ret_iva + $ret_isr;
                            }
                        }
                    }

                    $data [] = [
                        $row->type_name,
                        $row->cfdiType->name ?? '',
                        $row->serie,
                        $row->folio,
                        \App\Helpers\Helper::date(\Date::parse($row->date)),
                        \Date::parse($row->date)->format('H:i:s'),
                        $row->uuid,
                        $row->rfc_emisor,
                        $row->emisor,
                        $row->rfc_receptor,
                        $row->receptor,
                        $row->paymentWay->name ?? '',
                        $row->paymentMethod->code ?? '',
                        $row->cfdiUse->name ?? '',
                        $row->currency->code ?? '',
                        $row->currency_value ?? 1,
                        $row->amount_untaxed + $row->amount_discount,
                        $row->amount_discount,
                        #$iva,
                        $iva_16,
                        $iva_15,
                        $iva_11,
                        $iva_10,
                        $iva_8,
                        $ieps,
                        $row->amount_tax,
                        $ret_iva,
                        $ret_isr,
                        $row->amount_tax_ret,
                        $row->amount_total,
                        $row->balance,
                        $row->rfc_pac,
                        $row->status,
                        $row->is_cancelable,
                        $row->expenseType->name ?? '',
                        $row->operationalType->name ?? '',
                        $row->comment,
                        $row->comment_2,
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                        '',
                    ];

                    if (!empty($file_xml)) {
                        if (\Storage::exists($file_xml) && Helper::validateXmlToArrayCfdi33($file_xml)) {
                            $tmp = Helper::parseXmlToArrayCfdi33($file_xml, true);

                            if(!empty($tmp['data_reconcileds'])){
                                foreach($tmp['data_reconcileds'] as $reconciled){
                                    $data [] = [
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        #$iva,
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',
                                        '',

                                        $reconciled['uuid_related'],
                                        $reconciled['serie_related'],
                                        $reconciled['folio_related'],
                                        $reconciled['currency_code_related'],
                                        $reconciled['currency_value'],
                                        $reconciled['number_of_payment'],
                                        $reconciled['last_balance'],
                                        $reconciled['amount_reconciled'],
                                        $reconciled['current_balance'],
                                    ];
                                }
                            }
                        }
                    }
                }
            }

            return Excel::download(new CfdiDownloadsCustomerPaymentExport(collect($data)),
                __('base/cfdi_download.document_title_payment_type') . '-' . config('app.name') . '.xlsx');
        }else {
            return Excel::download(new CfdiDownloadsExport($request),
                __('base/cfdi_download.document_title') . '-' . config('app.name') . '.xlsx');
        }
    }

    /**
     * Modal para editar informacion
     *
     * @param Request $request
     * @param CfdiDownload $cfdi_download
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function modalEdit(Request $request, CfdiDownload $cfdi_download)
    {
        //Variables
        $id = $request->id;

        //Logica
        if ($request->ajax() && !empty($id)) {
            $expense_types = ExpenseType::populateSelect()->pluck('name','id');
            $operational_types = OperationalType::populateSelect()->pluck('name','id');

            $data_xml_conceptos = [];
            if (!empty($cfdi_download->file_xml)) {
                $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES, $cfdi_download->company_id) . '/';
                $file_xml = $path_files . $cfdi_download->file_xml;
                $data_xml_conceptos = Helper::parseXmlToArrayCfdi33Conceptos3($file_xml);
            }

            //
            $html = view('layouts.partials.cfdi_downloads.modal_edit', compact('cfdi_download','expense_types','operational_types','data_xml_conceptos'))->render();

            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    /**
     * Modal para editar informacion
     *
     * @param Request $request
     * @param CfdiDownload $cfdi_download
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function modalEditSelected(Request $request)
    {
        //Variables

        //Logica
        if ($request->ajax()) {
            $expense_types = ExpenseType::populateSelect()->pluck('name','id');
            $operational_types = OperationalType::populateSelect()->pluck('name','id');

            //
            $html = view('layouts.partials.cfdi_downloads.modal_edit_selected', compact('expense_types','operational_types'))->render();

            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    /**
     * Modal para alta de gastos
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function modalCreateExpense(Request $request)
    {
        //Variables

        //Logica
        if ($request->ajax()) {

            $expense_types = ExpenseType::where('type','=','1')->populateSelect()->pluck('name','id');
            $payment_ways = PaymentWay::populateSelect()->pluck('name','id');
            $currencies = Currency::populateSelect()->pluck('name','id');
            $operational_types = OperationalType::populateSelect()->pluck('name','id');

            //modal de buscar
            $html = view('layouts.partials.cfdi_downloads.modal_create_expense', compact('expense_types', 'payment_ways','currencies','operational_types'))->render();


            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    public function storeExpense(Request $request){
        //Validacion
        $this->validate($request, [
            'date' => 'required|date|date_format:"'.setting('datetime_format', 'd-m-Y H:i:s').'"',
            'name' => 'required',
            'emisor' => 'required',
            'date_payment' => 'nullable|date|date_format:"'.setting('date_format', 'd-m-Y').'"',
            'currency_id' => 'required|integer',
            'currency_value' => 'required|numeric|min:0.1',
            'amount_total' => 'required|numeric|min:0.00001',
        ], [
            'date.required' => __('base/cfdi_download.error_date'),
            'date.date' => __('base/cfdi_download.error_date_format'),
            'date.date_format' => __('base/cfdi_download.error_date_format'),
            'name.*' => __('base/cfdi_download.error_name'),
            'emisor.*' => __('base/cfdi_download.error_emisor'),
            'date_payment.date' => __('base/cfdi_download.error_date_payment_format'),
            'date_payment.date_format' => __('base/cfdi_download.error_date_payment_format'),
            'currency_id.*' => __('base/cfdi_download.error_currency_id'),
            'currency_value.*' => __('base/cfdi_download.error_currency_value'),
            'amount_total.*' => __('base/cfdi_download.error_amount_total_2'),
        ]);

        //
        $cfdi_type = CfdiType::whereCode('I')->first();
        $company = Helper::defaultCompany(); //Empresa

        //Logica
        $request->merge(['type' => 1]);
        $request->merge(['folio' => $request->name]);
        $request->merge(['cfdi_type_id' => $cfdi_type->id]);
        $request->merge(['created_uid' => \Auth::user()->id]);
        $request->merge(['updated_uid' => \Auth::user()->id]);
        $request->merge(['date' => Helper::convertDateTimeToSql($request->date)]);
        $request->merge(['date_payment' => !empty($request->date_payment) ? Helper::convertDateToSql($request->date_payment) : null]);
        $request->merge(['balance' => $request->amount_total]);
        $request->merge(['status' => 'Vigente']);
        $request->merge(['company_id' => $company->id]);

        //Guardar
        //Registro principal
        $cfdi_download = CfdiDownload::create($request->input());

        //Mensaje
        return response()->json([
            'success' => __('general.text_form_success_add')
        ]);
    }

    /**
     * Modal para alta de ingreso
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function modalCreateDeposit(Request $request)
    {
        //Variables

        //Logica
        if ($request->ajax()) {

            $expense_types = ExpenseType::where('type','=','2')->populateSelect()->pluck('name','id');
            $payment_ways = PaymentWay::populateSelect()->pluck('name','id');
            $currencies = Currency::populateSelect()->pluck('name','id');
            $operational_types = OperationalType::populateSelect()->pluck('name','id');

            //modal de buscar
            $html = view('layouts.partials.cfdi_downloads.modal_create_deposit', compact('expense_types', 'payment_ways','currencies','operational_types'))->render();


            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    public function storeDeposit(Request $request){
        //Validacion
        $this->validate($request, [
            'date' => 'required|date|date_format:"'.setting('datetime_format', 'd-m-Y H:i:s').'"',
            'name' => 'required',
            'receptor' => 'required',
            'currency_id' => 'required|integer',
            'currency_value' => 'required|numeric|min:0.1',
            'amount_total' => 'required|numeric|min:0.00001',
        ], [
            'date.required' => __('base/cfdi_download.error_date'),
            'date.date' => __('base/cfdi_download.error_date_format'),
            'date.date_format' => __('base/cfdi_download.error_date_format'),
            'name.*' => __('base/cfdi_download.error_name'),
            'receptor.*' => __('base/cfdi_download.error_receptor_2'),
            'currency_id.*' => __('base/cfdi_download.error_currency_id'),
            'currency_value.*' => __('base/cfdi_download.error_currency_value'),
            'amount_total.*' => __('base/cfdi_download.error_amount_total_2'),
        ]);

        //
        $cfdi_type = CfdiType::whereCode('I')->first();
        $company = Helper::defaultCompany(); //Empresa

        //Logica
        $request->merge(['type' => 2]);
        $request->merge(['folio' => $request->name]);
        $request->merge(['cfdi_type_id' => $cfdi_type->id]);
        $request->merge(['created_uid' => \Auth::user()->id]);
        $request->merge(['updated_uid' => \Auth::user()->id]);
        $request->merge(['date' => Helper::convertDateTimeToSql($request->date)]);
        $request->merge(['balance' => $request->amount_total]);
        $request->merge(['status' => 'Vigente']);
        $request->merge(['company_id' => $company->id]);

        //Guardar
        //Registro principal
        $cfdi_download = CfdiDownload::create($request->input());

        //Mensaje
        return response()->json([
            'success' => __('general.text_form_success_add')
        ]);
    }

    /**
     * Modal para ver y agregar pagos
     *
     * @param Request $request
     * @param CfdiDownload $cfdi_download
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function modalPayments(Request $request, CfdiDownload $cfdi_download)
    {
        //Variables
        $id = $request->id;

        //Logica
        if ($request->ajax() && !empty($id)) {

            $payment_ways = PaymentWay::populateSelect()->pluck('name','id');

            //
            $html = view('layouts.partials.cfdi_downloads.modal_payments', compact('cfdi_download','payment_ways'))->render();

            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    public function storePayment(Request $request){

        //Validacion
        $this->validate($request, [
            'date_payment' => 'required|date|date_format:"'.setting('date_format', 'd-m-Y').'"',
            'payment_way_id' => 'required',
            'currency_id' => 'required',
            'currency_value' => 'required|numeric|min:0.1',
            'amount_payment' => 'required|numeric|min:0.00001',
        ], [
            'date_payment.required' => __('base/cfdi_download.error_date_payment'),
            'date_payment.date' => __('base/cfdi_download.error_date_payment_format'),
            'date_payment.date_format' => __('base/cfdi_download.error_date_payment_format'),
            'payment_way_id.*' => __('base/cfdi_download.error_payment_way_id'),
            'currency_id.*' => __('base/cfdi_download.error_currency_id'),
            'currency_value.*' => __('base/cfdi_download.error_currency_value'),
            'amount_payment.*' => __('base/cfdi_download.error_amount_total_2'),
        ]);

        //
        $cfdi_download = CfdiDownload::findOrFail($request->cfdi_download_id);
        if($request->amount_payment > $cfdi_download->balance){
            return response()->json(['error' => __('base/cfdi_download.error_amount_payment_vs_balance')], 422);
        }

        //Logica
        $request->merge(['created_uid' => \Auth::user()->id]);
        $request->merge(['updated_uid' => \Auth::user()->id]);
        $request->merge(['date_payment' => Helper::convertDateToSql($request->date_payment)]);
        $request->merge(['sort_order' => 0]);
        $request->merge(['status' => 1]);

        //Guardar
        //Registro principal
        $cfdi_download_payment = CfdiDownloadPayment::create($request->input());

        //Resta
        $cfdi_download->balance -= $request->amount_payment;
        $cfdi_download->save();

        //Mensaje
        return response()->json([
            'success' => __('general.text_form_success_add'),
            'balance' => money($cfdi_download->balance, $cfdi_download->currency->code ?? 'MXN', true)->format(),
            'amount_payment' => money($cfdi_download->cfdiDownloadPayments->sum('amount_payment'),$cfdi_download->currency->code ?? 'MXN',true)->format()
        ]);
    }

    /**
     * Pagos asociados a un cfdi descargado
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function payments(Request $request)
    {
        //Variables
        $cfdi_download_id = $request->id;

        //Logica
        if ($request->ajax() && !empty($cfdi_download_id)) {

            //
            $cfdi_download = CfdiDownload::findOrFail($cfdi_download_id);

            //Consulta
            $results = $cfdi_download->cfdiDownloadPayments;

            $html = view('layouts.partials.cfdi_downloads.payments', compact('results'))->render();

            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    /**
     * Pagos asociados a un cfdi descargado
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function bankReconciliations(Request $request)
    {
        //Variables
        $cfdi_download_id = $request->id;

        //Logica
        if ($request->ajax() && !empty($cfdi_download_id)) {

            //
            $cfdi_download = CfdiDownload::findOrFail($cfdi_download_id);

            //Consulta
            $results = $cfdi_download->bankMoveReconcileds;

            $html = view('layouts.partials.cfdi_downloads.bank_reconciliations', compact('results'))->render();

            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    public function destroyPayment(Request $request){

        //Variables
        $cfdi_download_payment_id = $request->id;

        //Logica
        if ($request->ajax() && !empty($cfdi_download_payment_id)) {

            //
            $cfdi_download_payment = CfdiDownloadPayment::findOrFail($cfdi_download_payment_id);
            $cfdi_download = $cfdi_download_payment->cfdiDownload;

            //Logica

            //Guardar
            //Registro principal

            //Resta
            $cfdi_download->balance += $cfdi_download_payment->amount_payment;
            $cfdi_download->save();

            //
            $cfdi_download_payment->delete();

            //Mensaje
            return response()->json([
                'success' => __('general.text_form_success_delete'),
                'balance' => money($cfdi_download->balance, $cfdi_download->currency->code ?? 'MXN', true)->format(),
                'amount_payment' => money($cfdi_download->cfdiDownloadPayments->sum('amount_payment'),
                    $cfdi_download->currency->code ?? 'MXN', true)->format()
            ]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    /**
     * Lista de cfdis por conciliar con banco
     *
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function perReconcilation(Request $request)
    {
        //Variables
        $filter_date_from = $request->filter_date_from;
        $filter_date_to = $request->filter_date_to;
        //Logica
        if ($request->ajax() && !empty($filter_date_from) && !empty($filter_date_to)) {
            $cfdi_type = CfdiType::whereCode('I')->first();

            $filter =[
                'filter_per_reconciliation' => true,
                'filter_date_from' => $filter_date_from,
                'filter_date_to' => $filter_date_to, //Solo pagos en MXN se pueden aplicar a otras monedas
                'filter_cfdi_type_id' => $cfdi_type->id
            ];

            //Consulta
            $results = CfdiDownload::filter($filter)->where('amount_total','>',0)->where('conciled','=',0)->sortable('date')->get();

            $html = view('layouts.partials.cfdi_downloads.per_reconciliation', compact('results'))->render();

            return response()->json(['html' => $html]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    public function wsFielDownload($company){
        //Validacion
        if (empty($company->fiel_file_cer)) {
            throw new \Exception(__('base/company.error_file_cer_empty'));
        }
        if (!\Storage::exists($company->pathFielFileCer())) {
            throw new \Exception(__('base/company.error_file_cer_exists'));
        }
        if (empty($company->fiel_file_key)) {
            throw new \Exception(__('base/company.error_file_key_empty'));
        }
        if (!\Storage::exists($company->pathFielFileKey())) {
            throw new \Exception(__('base/company.error_file_key_exists'));
        }

        //
        $fiel = Fiel::create(
            \Storage::get($company->pathFielFileCer()),
            \Storage::get($company->pathFielFileKey()),
            Crypt::decryptString($company->fiel_password_key)
        );

        /*if($fiel->getRfc() != $company->taxid){
            throw new \Exception(__('base/cfdi_download.error_invalid_fiel_rfc'));
        }*/

        // verificar que la fiel sea válida (no sea CSD y sea vigente acorde a la fecha del sistema)
        if (! $fiel->isValid()) {
            throw new \Exception(__('base/cfdi_download.error_invalid_fiel'));
        }

        // creación del web client basado en Guzzle que implementa WebClientInterface
        // para usarlo necesitas instalar guzzlehttp/guzzle pues no es una dependencia directa
        $webClient = new GuzzleWebClient();

        // creación del objeto encargado de crear las solicitudes firmadas usando una FIEL
        $requestBuilder = new FielRequestBuilder($fiel);

        // Creación y retorno del servicio
        return new Service($requestBuilder, $webClient);
    }

    /**
     * Modal para editar informacion
     *
     * @param Request $request
     * @param CfdiDownload $cfdi_download
     * @return \Illuminate\Http\JsonResponse
     * @throws \Throwable
     */
    public function requestVerify(Request $request, CfdiDownloadRequest $cfdi_download_request)
    {
        //Variables
        $id = $request->id;

        //Logica
        if ($request->ajax() && !empty($id)) {
            $response = true;
            $service = $this->wsFielDownload($cfdi_download_request->company);


            if(!empty($cfdi_download_request->folio)) {
                $verify = $service->verify($cfdi_download_request->folio);

                // revisar que el proceso de verificación fue correcto
                if (!$verify->getStatus()->isAccepted()) {
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_3') . $verify->getStatus()->getMessage()], 422);
                }

                // revisar que la consulta no haya sido rechazada
                if(!$verify->getCodeRequest()->isAccepted()){
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_4') . $verify->getStatus()->getMessage()], 422);
                }

                // revisar el progreso de la generación de los paquetes
                $statusRequest = $verify->getStatusRequest();
                if ($statusRequest->isExpired() || $statusRequest->isFailure() || $statusRequest->isRejected()) {
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_5')], 422);
                }
                if ($statusRequest->isInProgress() || $statusRequest->isAccepted()) {
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_6')], 422);
                }

                if ($statusRequest->isFinished()) {
                    $packageIds = $verify->getPackagesIds();
                    $cfdi_download_request->qty = $verify->getNumberCfdis();
                    $cfdi_download_request->save();

                    //Guarda cada uno de los folios
                    if (!empty($packageIds)) {
                        foreach ($packageIds as $packageId) {
                            $cfdi_download_request_file = CfdiDownloadRequestFile::where('folio_download', '=',$packageId)->first();
                            if (empty($cfdi_download_request_file)) {
                                $cfdi_download_request_file = CfdiDownloadRequestFile::create([
                                    'created_uid' => \Auth::user()->id,
                                    'updated_uid' => \Auth::user()->id,
                                    'cfdi_download_request_id' => $cfdi_download_request->id,
                                    'folio_download' => $packageId,
                                    'status' => 1,
                                ]);
                            }
                        }
                    }
                }
            }

            //si hay folio de metadata tambien lo valida
            if(!empty($cfdi_download_request->folio_metadata)){
                $verify = $service->verify($cfdi_download_request->folio_metadata);

                // revisar que el proceso de verificación fue correcto
                if (!$verify->getStatus()->isAccepted()) {
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_7') . $verify->getStatus()->getMessage()], 422);
                }

                // revisar que la consulta no haya sido rechazada
                if(!$verify->getCodeRequest()->isAccepted()){
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_8') . $verify->getStatus()->getMessage()], 422);
                }

                // revisar el progreso de la generación de los paquetes
                $statusRequest = $verify->getStatusRequest();
                if ($statusRequest->isExpired() || $statusRequest->isFailure() || $statusRequest->isRejected()) {
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_9')], 422);
                }
                if ($statusRequest->isInProgress() || $statusRequest->isAccepted()) {
                    $response = false;
                    return response()->json(['error' => __('base/cfdi_download_request.error_request_verify_10')], 422);
                }
                if ($statusRequest->isFinished()) {
                    $packageIds = $verify->getPackagesIds();

                    //Guarda cada uno de los folios
                    if (!empty($packageIds)) {
                        foreach ($packageIds as $packageId) {
                            $cfdi_download_request_file = CfdiDownloadRequestFile::where('folio_download', '=',$packageId)->first();
                            if (empty($cfdi_download_request_file)) {
                                $cfdi_download_request_file = CfdiDownloadRequestFile::create([
                                    'created_uid' => \Auth::user()->id,
                                    'updated_uid' => \Auth::user()->id,
                                    'cfdi_download_request_id' => $cfdi_download_request->id,
                                    'folio_download_metadata' => $packageId,
                                    'status' => 1,
                                ]);
                            }
                        }
                    }
                }
            }

            //
            return response()->json(['response' => $response,'qty' => $cfdi_download_request->qty]);
        }

        return response()->json(['error' => __('general.error_general')], 422);
    }

    public function requestDownload(Request $request, CfdiDownloadRequest $cfdi_download_request){
        $company = $cfdi_download_request->company;
        $service = $this->wsFielDownload($cfdi_download_request->company);
        $file_xml_download_error = [];

        try {

            //Realizamos primero las descargas si aun no se hacen
            if($cfdi_download_request->cfdiDownloadRequestFiles->isNotEmpty()){
                foreach($cfdi_download_request->cfdiDownloadRequestFiles as $cfdi_download_request_file){
                    if(empty($cfdi_download_request_file->file) && !empty($cfdi_download_request_file->folio_download)){
                        $download = $service->download($cfdi_download_request_file->folio_download);
                        if($download->getStatus()->isAccepted()) {
                            $name_file = Str::random(40) . '.zip';
                            \Storage::put(Helper::setDirectory(CfdiDownloadRequest::PATH_FILES, $company->id) . '/' . $name_file, $download->getPackageContent());
                            $cfdi_download_request_file->file = $name_file;
                            $cfdi_download_request_file->save();
                        }else{
                            flash(__('base/cfdi_download_request.error_request_verify_11') . $download->getStatus()->getMessage())->error();
                        }
                    }
                }
            }

            //Realizamos descarga de metadata
            if($cfdi_download_request->cfdiDownloadRequestFiles->isNotEmpty()){
                foreach($cfdi_download_request->cfdiDownloadRequestFiles as $cfdi_download_request_file){
                    if(empty($cfdi_download_request_file->file_metadata) && !empty($cfdi_download_request_file->folio_download_metadata)){
                        $download = $service->download($cfdi_download_request_file->folio_download_metadata);
                        if($download->getStatus()->isAccepted()) {
                            $name_file = Str::random(40) . '.zip';
                            \Storage::put(Helper::setDirectory(CfdiDownloadRequest::PATH_FILES, $company->id) . '/' . $name_file, $download->getPackageContent());
                            $cfdi_download_request_file->file_metadata = $name_file;
                            $cfdi_download_request_file->save();
                        }else{
                            flash(__('base/cfdi_download_request.error_request_verify_12') . $download->getStatus()->getMessage())->error();
                        }
                    }
                }
            }
        }catch(\Exception $e){
            flash(__('base/cfdi_download.error_download_xml_session_sat') . '<br>' . $e->getMessage())->error();
        }

        //Comienza con descomprimir los archivos
        $path_files_request = Helper::setDirectory(CfdiDownloadRequest::PATH_FILES, $company->id);
        $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES, $company->id);
        $count = 0;

        //Obtenermos informacion de los metadata
        $metadata = [];
        if($cfdi_download_request->cfdiDownloadRequestFiles->isNotEmpty()) {
            foreach ($cfdi_download_request->cfdiDownloadRequestFiles as $cfdi_download_request_file) {
                if(!empty($cfdi_download_request_file->file_metadata)) {
                    $metadataReader = MetadataPackageReader::createFromFile(\Storage::path($path_files_request. '/' . $cfdi_download_request_file->file_metadata));
                    foreach ($metadataReader->metadata() as $uuid => $tmp) {
                        $date_cancel = trim($tmp->fechaCancelacion);
                        $metadata[strtoupper(trim($tmp->uuid))] = [
                            'status' => $tmp->estatus ? 'Vigente' : 'Cancelado',
                            'date_cancel' => !empty($date_cancel) ? trim($tmp->fechaCancelacion): null,
                        ];
                    }
                }
            }
        }

        //Obtenemos informacion de los archivos descargados
        if($cfdi_download_request->cfdiDownloadRequestFiles->isNotEmpty()) {
            foreach ($cfdi_download_request->cfdiDownloadRequestFiles as $cfdi_download_request_file) {
                if (!empty($cfdi_download_request_file->file) && empty($cfdi_download_request_file->completed)) {
                    //Crear directorio temporal
                    $tmp_path = Str::random(15) . '/';
                    if (!\Storage::exists($path_files . '/' . $tmp_path)) {
                        \Storage::makeDirectory($path_files . '/' . $tmp_path, 0777, true, true);
                        @shell_exec('chmod -R 777 ' . \Storage::path($path_files . '/' . $tmp_path));
                    }
                    $log_files = Zipper::make(\Storage::path($path_files_request. '/' . $cfdi_download_request_file->file))->listFiles();

                    //Descomprimir archivos
                    $zip = new ZipArchive();
                    $x = $zip->open(\Storage::path($path_files_request. '/' . $cfdi_download_request_file->file));  // open the zip file to extract
                    if ($x === true) {
                        try {
                            $zip->extractTo(\Storage::path($path_files. '/' . $tmp_path)); // place in the directory with same name
                        } catch (\Exception $e) {
                            throw new \Exception(__('Error al descomprimir al archivo'));
                        }
                        $zip->close();
                        // unlink($targetzip);
                    }

                    //Leer XML's de archivos descomprimidos
                    if(!empty($log_files)){
                        foreach($log_files as $name){
                            if (\Storage::exists($path_files . '/' . $tmp_path . $name)) {
                                $validate_xml_to_array = true;
                                try {
                                    $validate_xml_to_array = Helper::validateXmlToArrayCfdi33($path_files . '/' . $tmp_path . $name);
                                }catch(\Exception $e){
                                    $file_xml_download_error[] = $name;
                                    continue;
                                }
                                if ($validate_xml_to_array) {
                                    $data_xml = [];
                                    try {
                                        $data_xml = Helper::parseXmlToArrayCfdi33($path_files . '/' . $tmp_path . $name);
                                    }catch(\Exception $e){
                                        $file_xml_download_error[] = $name;
                                        continue;
                                    }
                                    if(!empty($data_xml)) {
                                        $uuid = strtoupper($data_xml['data']['uuid']);
                                        $cfdi_download = CfdiDownload::where('company_id', '=', $company->id)->where('uuid', '=', $uuid)->first();
                                        if (empty($cfdi_download)) {
                                            $cfdi_download = CfdiDownload::create([
                                                'created_uid' => \Auth::user()->id,
                                                'updated_uid' => \Auth::user()->id,
                                                'type' => $cfdi_download_request->type,
                                                'uuid' => $uuid,
                                                'file_xml' => $tmp_path . $name,
                                                'file_pdf' => '',
                                                'file_acuse' => '',
                                                'status' => !empty($metadata[$uuid]) ? $metadata[$uuid]['status'] : '',
                                                'is_cancelable' => '',
                                                'company_id' => $company->id,
                                                'date_cancel' => !empty($metadata[$uuid]) ? $metadata[$uuid]['date_cancel'] : null,
                                            ]);
                                            //Leer XML para obtener los datos
                                            $cfdi_download->fill($data_xml['data']);
                                            $cfdi_download->save();
                                        } else {
                                            $cfdi_download->file_xml = $tmp_path . $name;
                                            $cfdi_download->status = !empty($metadata[$uuid]) ? $metadata[$uuid]['status'] : '';
                                            $cfdi_download->date_cancel = !empty($metadata[$uuid]) ? $metadata[$uuid]['date_cancel'] : null;
                                            $cfdi_download->save();
                                        }
                                        $count++;
                                    }
                                }
                            }
                        }
                    }
                    //$cfdi_download_request_file->completed = 1;
                    $cfdi_download_request_file->save();
                }
            }
        }

        //
        $cfdi_download_request->completed = 1;
        $cfdi_download_request->save();

        //Mensaje
        if(!empty($file_xml_download_error)) {
            flash(sprintf(__('base/cfdi_download_request.text_success_cfdi_download_errors'),
                count($file_xml_download_error)))->warning();
        }
        flash(sprintf(__('base/cfdi_download_request.text_success_cfdi_download'), $count))->success();


        //Si ya se ha descargado el archivo lo leemos
        if(!empty($cfdi_download_request->file)){
            //Leemos XML descargados
            /*$cfdiReader = new CfdiPackageReader(\Storage::path($path_files. '/' . $cfdi_download_request->file));
            //Para para xml
            $path_files = Helper::setDirectory(CfdiDownload::PATH_FILES, $company->id);
            $tmp_path = Str::random(10) . '/';
            if (!\Storage::exists($path_files . '/' . $tmp_path)) {
                \Storage::makeDirectory($path_files . '/' . $tmp_path, 0777, true, true);
                @shell_exec('chmod -R 777 ' . \Storage::path($path_files . '/' . $tmp_path));
            }
            $count = 0;
            foreach ($cfdiReader->fileContents() as $name => $content) {
                //Guardamos el archivo
                \Storage::put($path_files . '/' . $tmp_path . $name, $content);

                //Obtenemos la informacion
                if (Helper::validateXmlToArrayCfdi33($path_files . '/' . $tmp_path . $name)) {
                    $data_xml = Helper::parseXmlToArrayCfdi33($path_files . '/' . $tmp_path . $name);
                    $uuid = strtoupper($data_xml['data']['uuid']);
                    $cfdi_download = CfdiDownload::where('company_id','=',$company->id)->where('uuid', '=', $uuid)->first();
                    if (empty($cfdi_download)) {
                        $cfdi_download = CfdiDownload::create([
                            'created_uid' => \Auth::user()->id,
                            'updated_uid' => \Auth::user()->id,
                            'type' => $cfdi_download_request->type,
                            'uuid' => $uuid,
                            'file_xml' => $tmp_path . $name,
                            'file_pdf' => '',
                            'file_acuse' => '',
                            'status' => !empty($metadata[$uuid]) ? $metadata[$uuid]['status'] : '',
                            'is_cancelable' => '',
                            'company_id' => $company->id,
                            'date_cancel' => !empty($metadata[$uuid]) ? $metadata[$uuid]['date_cancel'] : null,
                        ]);
                        //Leer XML para obtener los datos
                        $cfdi_download->fill($data_xml['data']);
                        $cfdi_download->save();
                    }else{
                        $cfdi_download->status = !empty($metadata[$uuid]) ? $metadata[$uuid]['status'] : '';
                        $cfdi_download->date_cancel = !empty($metadata[$uuid]) ? $metadata[$uuid]['date_cancel'] : null;
                        $cfdi_download->save();
                    }
                    $count++;
                }
            }*/
        }

        //Redirecciona
        return redirect()->route('cfdi-downloads/create-cfdi-download-fiel');

    }
}
