HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/comfama.sports-crowd.com/app/Http/Controllers/TicketsController.php
<?php

namespace App\Http\Controllers;

use App\CorporateIdentity;
use Excel;
use DB;
use App\Door;
use App\Seat;
use App\Team;
use App\User;
use App\Zone;
use DateTime;
use Madzipper;
use App\Season;
use App\Ticket;
use App\Parameter;
use App\TicketLog;
use Carbon\Carbon;
use App\MatchEvent;
use App\TicketMain;
use App\TicketType;
use App\Tournament;
use App\PreSubscriber;
use App\TicketUserBlock;
use App\MatchEventZonePrice;
use Illuminate\Http\Request;
use App\TicketUserBlockBackup;
use App\Mail\NewSuscriptorMail;
use App\Mail\TicketPurchaseMail;
use App\Mail\TicketPurchaseEmailList;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Collection;
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Response;
use Illuminate\Database\Eloquent\Builder;
use App\Http\Controllers\PrintTicketController;
use App\Http\Controllers\Imports\CancelTicketsImport;
use App\Http\Controllers\Imports\CancelTicketsTemplate;
use App\Http\Controllers\Imports\MatchEventSeatsImport;
use App\Http\Controllers\Imports\MatchEventSeatsTemplate;
use App\Http\Controllers\Imports\MatchEventSpecialTextImport;
use App\Http\Controllers\Imports\MatchEventSpecialTextTemplate;
use App\Http\Controllers\SmsNotificationsController;
use App\Events\SmsNotificationEvent;
use App\Http\Controllers\UtilController;
use App\MatchEventStage;
use DataTables;
use App\Http\Controllers\Exports\ListTickeLogsExport;
use App\Services\TicketsService;
use App\Services\TicketParametersService;
use App\Services\ZonesService;

class TicketsController extends Controller
{
    private $util;
    private $ticketsService;
    private $ticketParametersService;

    private $parameters;
    public $responseCapacityZone;
    private $seatStage = 1;
    private $tribuneBlockingStage = 2;
    private $limitTribuneCapacityStage = 3;
    private $exclusiveTribuneStage = 5;

    public function __construct()
    {
        $this->parameters = Parameter::first();
        $this->util = new UtilController;
        $this->ticketsService = new TicketsService;
        $this->ticketParametersService = new TicketParametersService;
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $list_events = $this->getMatchEvents();
        $events = [];
        foreach ($list_events as $key => $event) {

            // Se oculta un partido para el rol de gana
            $str_event = preg_replace("/\s+/", ",", trim($this->parameters->hide_match));
            $str_replace_event = str_replace('.', ',', trim($str_event));
            $explode_event = explode(',', $str_replace_event);
            $array_event_id_hide = array_filter($explode_event);

            if (is_array($array_event_id_hide)) {
                if (in_array(Auth::user()->rol->id, [$this->__EXTERNAL_OPERATOR_ROL]) && in_array($event->id, $array_event_id_hide)) {
                    continue;
                }
            }

            if ($event->active) {
                $events[] = $event;
            }
        }

        if ($this->validateRolePermissions('ticketing', 'seller'))
            $types = TicketType::select('id', 'name')->where([['id', '!=', 2], ['id', '!=', 3], ['id', '!=', 4], ['active', true]])->get();
        else
            $types = TicketType::select('id', 'name')->where('active', true)->get();

        $parameters = $this->parameters;
        $zonesService = new ZonesService;
        return view('tickets.list', compact('events', 'types', 'parameters'));
    }

    public function getMatchEvents()
    {
        DB::statement("SET sql_mode = ''");
        $presuscription = $this->parameters->presuscription;
        if ($presuscription && Auth::user()) {
            $totalSubscribers = PreSubscriber::where([['email', Auth::user()->email], ['payment', false]])->count();
            $presuscription = $totalSubscribers > 0 ? 1 : 0;
        }
        $matchEvents = MatchEvent::select(
            'match_events.id',
            'match_events.name',
            'match_events.code',
            'match_events.date_name',
            DB::raw('IF(match_events.sales_type = "seleccionada", CONCAT("/select-tickets/", match_events.id), CONCAT("/flash-tickets/", match_events.id)) AS sales'),
            DB::raw('IF(seasons.is_suscription = 1,' . ($presuscription > 0 ? ('CONCAT("/flash-tickets/", match_events.id, "/",' . $presuscription . ')') : '""') . ',"") AS subscriberSales'),
            DB::raw('IF(match_events.sales_type = "seleccionada" && (COUNT(match_event_zone_prices.id) = 0 || match_events.zone_id IS NULL), 1, 0) AS invalidEvent'),
            'match_events.event_start',
            'match_events.stadium_to_play',
            'match_events.active',
            'event_start_sale',
            'event_end_sale',
            'season_id',
            'team_id',
            'stadium.img as stadium',
        )
            ->with('seasonApp', 'teamApp')
            ->join('seasons', 'seasons.id', '=', 'match_events.season_id')
            ->join('tournaments', 'tournaments.id', '=', 'seasons.tournament_id')
            ->leftjoin('zones as stadium', 'stadium.id', '=', 'match_events.zone_id')
            ->leftjoin('match_event_zone_prices', 'match_event_zone_prices.match_event_id', '=', 'match_events.id')
            ->where([['tournaments.active', true], ['seasons.active', true], ['match_events.active', true]]);
        if (Auth::user() && !in_array(Auth::user()->rol->id, [$this->__SUPERADMIN_ROL, $this->__ADMIN_ROL, $this->__TICKET_OFFICE_ROL, $this->__TICKET_OFFICE_ROL_INTERNAL])) {
            $userId = Auth::user()->id;
            $matchEvents = $matchEvents
                ->leftJoin('match_event_tags', 'match_event_tags.match_event_id', '=', 'match_events.id')
                ->leftJoin('user_tags', 'user_tags.tag_id', '=', 'match_event_tags.tag_id')
                ->where(function ($q) use ($userId) {
                    $q->where('user_tags.user_id', $userId)->orWhereNull('match_event_tags.id');
                });
        } else {
            $matchEvents = $matchEvents->where('match_events.sales_type', '=', 'seleccionada');
        }
        $matchEvents = $matchEvents->groupBy('match_events.id')->get();
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
        return $matchEvents;
    }

    public function getTribunesParent($match_event_id = null)
    {
        $stadiumsZone   = Zone::where('active', 1)->whereNull('zone_id')->pluck('id');
        $query          = Zone::select('id', 'name', 'alias', 'is_main', 'is_saleable', 'active')->where('active', 1)->whereIn('zone_id', $stadiumsZone);
        if ($match_event_id) {
            $query = $query->with(['match_event_stage' => function ($q) use ($match_event_id) {
                $q->where('match_event_id', $match_event_id)
                    ->whereIn('stage_type_id', [$this->tribuneBlockingStage, $this->exclusiveTribuneStage]);
            }]);
        }
        $data = $query->get();
        if (Auth::user()) {
            $userId = Auth::user()->id;
            foreach ($data as $zone) {
                if (count($zone->match_event_stage)) {
                    foreach ($zone->match_event_stage as $key => $stage) {
                        if ($stage->stage_type_id == $this->exclusiveTribuneStage) {
                            $stageUser = DB::table('match_event_stages')
                                ->leftJoin('match_event_stage_tags', 'match_event_stage_tags.match_event_stage_id', '=', 'match_event_stages.id')
                                ->leftJoin('user_tags', 'user_tags.tag_id', '=', 'match_event_stage_tags.tag_id')
                                ->where('match_event_stages.id', $stage->id)
                                ->where(function ($q) use ($userId) {
                                    $q->where('user_tags.user_id', $userId)->orWhereNull('match_event_stage_tags.id');
                                })->count();
                            if ($stageUser)
                                unset($zone->match_event_stage[$key]);
                        }
                    }
                }
            }
        }
        return $data;
    }

    public function loadStadiumZones(Request $request)
    {
        return $this->ticketsService->loadStadiumZones($request);
    }

    public function listTribunesParent($match_event_id)
    {
        try {
            $tribunesParent = $this->getTribunesParent($match_event_id);
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $tribunesParent));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "listTribunesParen", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function getTribunesByZone($parent_zone_id)
    {
        try {
            $zones = Zone::where('zone_id', $parent_zone_id)->where('active', true)->get();
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $zones));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getTribunesByZone", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function getSeatByZone($zone_id)
    {
        try {
            $seats = Seat::where('zone_id', $zone_id)->with('letter')->get();
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $seats));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getSeatByZone", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function getSeatFreeByZone($zone_id, $match_event_id)
    {
        try {
            $matchEvent = MatchEvent::with('season')->where('id', $match_event_id)->first();
            $parameters = Parameter::select('presuscription')->first();
            $presubscriptionActive = $parameters->presuscription && $matchEvent->season->is_suscription;

            $seats = Seat::with('letter')
                ->where('zone_id', $zone_id)
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('ticket_user_blocks')->where('match_event_id', $match_event_id);
                }) // Sin bloqueos
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('tickets')->where('match_event_id', $match_event_id)->whereIn('ticket_status_id', [1, 2]);
                }) // Que no este vendida
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('match_event_stages')->where('match_event_id', $match_event_id)->where('stage_type_id', $this->seatStage);
                }) // Que no este bloqueada para el evento
                ->when($presubscriptionActive, function ($query) {
                    $query->whereNotIn('id', function ($query) {
                        $query->select('seat_id')->from('pre_subscribers');
                    });
                }) // Que no este reservada para un abonado
                ->get();

            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $seats));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getSeatFreeByZone", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function getParentZones($zone_id)
    {
        try {
            $current_zone = Zone::select('zone_id')->where('id', $zone_id)->first();
            $zones = Zone::where('zone_id', $current_zone->zone_id)->with('zone')->get();
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $zones));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getZones", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function getSubZones($zone_id, $event_id)
    {
        try {
            DB::statement("SET sql_mode = ''");
            $sql = "SELECT z.id, z.name, z.alias, z.active, z.is_saleable, z.zone_id, z.salable_capacity, z.total_capacity,
                    (z.salable_capacity - SUM(IF(t.id, 1, 0) + IF(tu.id, 1, 0) + IF(me.id, 1, 0))) AS available_seats
                FROM zones z
                LEFT JOIN seats s ON s.zone_id = z.id
                LEFT JOIN tickets t ON t.seat_id = s.id AND t.match_event_id = " . $event_id . " AND t.ticket_status_id IN (1,2)
                LEFT JOIN ticket_user_blocks tu ON tu.seat_id = s.id AND tu.match_event_id = " . $event_id . "
                LEFT JOIN match_event_stages me ON me.seat_id = s.id AND me.match_event_id = " . $event_id . "
                WHERE z.zone_id = " . $zone_id . " AND z.active = true
                GROUP BY z.id";
            $zones = DB::select(DB::raw($sql));
            DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $zones));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getZones", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function getSeatsCount($zone_id, $event_id)
    {
        try {
            $count = 0;
            // se valida la capacidad de la localidad no este superada
            if (!$this->salableCapacityZone($zone_id, $event_id)) {
                return 0;
            }
            $seats = Seat::select('seats.id', DB::raw('IF(t.id, 1, 0) AS ticket'), DB::raw('IF(tu.id, 1, 0) AS ticket_user_block'))
                ->where([['seats.zone_id', $zone_id], ['active', true]])
                ->leftJoin('tickets AS t', function ($join) use ($event_id) {
                    $join->on('seats.id', '=', 't.seat_id')->where('t.match_event_id', $event_id)
                        ->whereIn('t.ticket_status_id', [1, 2]);
                })
                ->leftJoin('ticket_user_blocks AS tu', function ($join) use ($event_id) {
                    $join->on('seats.id', '=', 'tu.seat_id')->where('tu.match_event_id', $event_id);
                })
                ->get();

            foreach ($seats as $seat) {
                if ($this->isAvailable($seat)) {
                    $count++;
                }
            }
            return $count;
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getSeats", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function isAvailable($seat)
    {
        $flag = true;
        if ($seat->ticket || $seat->ticket_user_block) {
            $flag = false;
        }
        return $flag;
    }

    public function getSeats($zone_id, $event_id, $is_reassign = false)
    {
        try {
            // se valida la capacidad de la localidad no este superada
            if (!$this->salableCapacityZone($zone_id, $event_id)) {
                if ($is_reassign) {
                    $response = json_decode($this->responseCapacityZone->getContent());
                    return response(array("r" => true, "type" => "error", "title" => "", "m" => $response->m, "data" => []));
                }
                return $this->responseCapacityZone;
            }
            $parameters = Parameter::select('presuscription')->first();
            $presubscriptionActive = $parameters->presuscription;
            $event = MatchEvent::with('season')->where('id', $event_id)->first();
            $user = Auth::user();
            $seats = Seat::select(
                'seats.id',
                'seats.code',
                'seats.letter_id',
                'seats.zone_id',
                DB::raw('IF(t.id, 1, 0) AS ticket'),
                DB::raw('IF(tu.id, 1, 0) AS ticket_user_block'),
                't.ticket_type_id',
                'tu.is_social_distancing',
                DB::raw('IF(presub.id, 1, 0) AS presubscription')
            )
                ->with(['letter' => function ($q) {
                    $q->select('id', 'name');
                }])
                ->with(['match_event_stage' => function ($q) use ($event_id) {
                    $q->where('match_event_id', $event_id);
                }])
                ->leftJoin('tickets AS t', function ($join) use ($event_id) {
                    $join->on('seats.id', '=', 't.seat_id')->where('t.match_event_id', $event_id)
                        ->whereIn('t.ticket_status_id', [1, 2]);
                })
                ->leftJoin('ticket_user_blocks AS tu', function ($join) use ($event_id) {
                    $join->on('seats.id', '=', 'tu.seat_id')->where('tu.match_event_id', $event_id);
                })
                ->leftJoin('pre_subscribers AS presub', function ($join) use ($presubscriptionActive, $user, $event) {
                    $join->on('seats.id', '=', 'presub.seat_id');
                    if (!$presubscriptionActive || !$event->season->is_suscription) {
                        $join->whereNull('presub.seat_id');
                    }
                    if ($user) {
                        $join->where('presub.email', '!=', $user->email);
                    }
                })
                ->where('seats.zone_id', $zone_id)
                ->where('seats.active', 1)
                ->orderBy('seats.letter_id', 'desc')
                ->orderBy('seats.code', 'asc')
                ->get();
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $seats));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getSeats", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function isPreabonado($document)
    {
        try {
            if (!User::where([['document', $document], ['active', true]])->first()) {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "isPreabonado", "m" => "Debes ingresar todos los datos en tu perfil.", "data" => null));
            }
            $listPreSubcriber = PreSubscriber::where([['document', $document], ['payment', 0]])->get();
            if (count($listPreSubcriber) <= 0) {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "isPreabonado", "m" => $this->parameters->presuscription_msj, "data" => null));
            }
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $listPreSubcriber));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "isPreabonado", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function isPreabonadoByEmail(Request $request)
    {
        try {
            $listPreSubcriber = PreSubscriber::where('email', $request->email)->get();
            if (count($listPreSubcriber) <= 0) {
                $message = $this->parameters->is_exclusive_subscriber_login ? $this->parameters->msj_exclusive_subscriber_login : null;
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "isPreabonadoByEmail", "m" => $message, "data" => null));
            }
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => null));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "isPreabonadoByEmail", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function isPreabonadoByDocSuscription(Request $request)
    {
        try {
            $listPreSubcriber = PreSubscriber::where('document', $request->suscriptionDoc)->get();
            if (count($listPreSubcriber) <= 0) {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "isPreabonadoByEmail", "m" => $this->parameters->presuscription_msj, "data" => null));
            }
            foreach ($listPreSubcriber as $item) {
                $item->email = $request->email;
                $item->update();
            }
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => null));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "isPreabonadoByEmail", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function getSeatPrice($zone_id, $event_id)
    {
        try {
            $matchEventPrice = MatchEventZonePrice::select('id', 'match_event_id', 'price', 'price_suscription', 'zone_id')
                ->where([['zone_id', $zone_id], ['match_event_id', $event_id]])->first();
            if (!$matchEventPrice) {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateSell", "m" => __('messages.error_validation_tickets.zone_no_saleable'), "data" => null));
            }

            $parameters = Parameter::select('presuscription')->first();
            $presubscriptionActive = $parameters->presuscription;
            if (!$presubscriptionActive) {
                $matchEventPrice->price_suscription = 0;
                $matchEventPrice->subscriberPrices = [];
            } else {
                $user = Auth::user();
                $subscriberPrices = PreSubscriber::select('s.id AS seat_id', 'pre_subscribers.price AS price_suscription')
                    ->join('seats as s', 's.id', '=', 'pre_subscribers.seat_id')
                    ->join('zones as z', 'z.id', '=', 's.zone_id')
                    ->where('z.id', $zone_id)
                    ->where(function ($q) use ($user) {
                        if ($user) {
                            $q->where('pre_subscribers.email', $user->email);
                        }
                    })
                    ->groupBy('s.id', 'pre_subscribers.price')
                    ->get();
                $matchEventPrice->subscriberPrices = $subscriberPrices;
            }

            $controller = new ServiceChargeController();
            if ($matchEventPrice && $controller->validateServiceCharge()) {
                $zone = Zone::select('zone_id')->where('id', $zone_id)->first();
                $request = new Request([
                    'services'      => 'ticket',
                    'match_events'  => $event_id,
                    'zones'         => [$zone_id, $zone->zone_id],
                ]);
                $serviceCharge = $controller->calculateServiceCharge($request);
                $matchEventPrice->service_charge = $serviceCharge;
            }

            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $matchEventPrice));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getSeatPrice", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function searchUser(Request $request, $document, $match_event_id = null, $ticket_type_id = null)
    {
        try {
            $user = new UserController($request);
            $search = $user->searchUser($document);

            $isPreabonado = null;
            if ($this->parameters->presuscription) {
                $isPreabonado = $this->isPreabonado($document);
            }
            if ($match_event_id && $search) {
                $tickets = Ticket::where('match_event_id', $match_event_id)
                    ->where('user_id', $search->id)
                    ->where('ticket_type_id', $ticket_type_id)
                    ->count();

                return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $search, 'tickets' => $tickets, "isPreabonado" => $isPreabonado));
            }

            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $search, "isPreabonado" => $isPreabonado));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "searchUser", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }


    public function exchangeTicketsToUsers(Request $request, $document, $match_event_id = null, $ticket_type_id = null)
    {
        try {
            $user = new UserController($request);
            $search = $user->searchUser($document);
            $isPreabonado = null;
            if ($this->parameters->presuscription) {
                $isPreabonado = $this->isPreabonado($document);
            }
            if ($search->document) {
                $searchUser = User::where('document', '=', $search->document)->get();
                return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $searchUser, 'tickets' => $searchUser, "isPreabonado" => $isPreabonado));
            }
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => $searchUser, "isPreabonado" => $isPreabonado));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "searchUser", "m" => __('messages.error_creating'), "data" => $th->getMessage()));
        }
    }

    public function createBlockTicket($seat_id, $match_event_id, $user_id, $ticket_type_id, $ticket_main_id, $zone_id, $pin = false, $is_social_distancing = false, $price = false)
    {
        try {
            $minutesToBlock = 0;

            // Se procesa el bloqueo
            $minutesToBlock = $this->parameters->maximum_sale_blocking_time;
            $this->processBlockGeneralTicket($seat_id, $match_event_id, $user_id, $minutesToBlock, $ticket_type_id, $ticket_main_id, $zone_id, $is_social_distancing, $price);

            // mensaje mostrando el tiempo limite que tiene para efectuar la compra
            $messageBlockMinutes = Carbon::now()->addMinutes($minutesToBlock)->format('h:i:s A');
            $message = __($this->parameters->msj_waiting_time_for_seat_blocking ?? 'messages.create_block', ['dateblock' => $messageBlockMinutes]);

            if ($pin) {
                $message = $message . "\n" . __('messages.create_block_2') . $pin;
            } else {
                $message = $message . __('messages.create_block_3');
            }
            return array("r" => true, "type" => "success", "title" => "", "origin" => "createBlockTicket", "m" => $message, "data" => null);
        } catch (\Throwable $th) {
            return array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createBlockTicket", "m" => __('messages.error_global'), "data" => $th->getMessage());
        }
    }

    public function getSeatBlockdistancing_x($index_init, $array_search)
    {
        // definimos el index de inicio de bloqueo a la izquierda y derecha deacuerdo al parametro de numero de sillas a bloquear
        $init_block_left = $index_init - $this->parameters->social_distancing_number_seat_x;
        $init_block_right = $index_init + $this->parameters->social_distancing_number_seat_x;

        $list_block_distancing = [];

        foreach ($array_search as $key2 => $id) {
            if ($this->parameters->social_distancing_left) {
                if ($key2 >= $init_block_left && $key2 < $index_init) {
                    $list_block_distancing[] = $id;
                }
            }

            if ($this->parameters->social_distancing_right) {
                if ($key2 > $index_init && $key2 <= $init_block_right) {
                    $list_block_distancing[] = $id;
                }
            }
        }

        return $list_block_distancing;
    }

    public function getSeatBlockdistancing_y($index_init, $array_search, $array_file_origin)
    {
        $number_differente = 0;
        // definimos el index de inicio de bloqueo de arriba y abajo deacuerdo al parametro de numero de sillas a bloquear
        if (count($array_file_origin) != count($array_search)) {
            $number_differente = count($array_search) - count($array_file_origin);
        }
        if ($number_differente) {
            $index_init = $index_init + ($number_differente / 2);
        }

        $init_block_left = $index_init - $this->parameters->social_distancing_number_seat_y;
        $init_block_right = $index_init + $this->parameters->social_distancing_number_seat_y;

        $list_block_distancing = [];

        foreach ($array_search as $key2 => $id) {
            if ($key2 == $index_init) {
                $list_block_distancing[] = $id;
            }

            if ($key2 >= $init_block_left && $key2 < $index_init) {
                $list_block_distancing[] = $id;
            }

            if ($key2 > $index_init && $key2 <= $init_block_right) {
                $list_block_distancing[] = $id;
            }
        }

        return $list_block_distancing;
    }

    public function getGroupSeatByLetter($zone_id, $letter_id)
    {
        $resp = [];
        // $c = Seat::where([['zone_id',$zone_id],['letter_id', $letter_id]])->pluck('code')->toArray();
        $c = Seat::where([['zone_id', $zone_id], ['letter_id', $letter_id]])->pluck('id')->toArray();
        if ($c) {
            $resp = $c;
        }
        return $resp;
    }

    public function searchNeighbour($seat_id, $zone_id)
    {
        $list_block_distancing = [];
        $seat = Seat::where('id', $seat_id)->first();
        if ($seat) {
            $seats_group = Seat::where('zone_id', $zone_id)->distinct()->pluck('letter_id')->toArray();
            $ids_x_group = $this->getGroupSeatByLetter($zone_id, $seat->letter_id);

            // buscamos la fila vecina de arriba y la de abajo
            $letter_id_top = 0;
            $letter_id_bottom = 0;
            foreach ($seats_group as $key => $letter) {
                if ($letter == $seat->letter_id) {
                    if (isset($seats_group[$key + 1]) && $this->parameters->social_distancing_top) {
                        $letter_id_top = $seats_group[$key + 1];
                    }
                    if (isset($seats_group[$key - 1]) && $this->parameters->social_distancing_bottom) {
                        $letter_id_bottom = $seats_group[$key - 1];
                    }
                }
            }

            // buscamos el index de la silla de la fila origen a comprar por el usuario
            // $index_seat_buy = array_search($seat->code, $ids_x_group);
            $index_seat_buy = array_search($seat->id, $ids_x_group);

            // Consultamos la sillas a bloquear en el eje x basado en el index de la silla a comprar por el cliente
            $list_block_distancing = array_merge($this->getSeatBlockdistancing_x($index_seat_buy, $ids_x_group), $list_block_distancing);

            // Consultamos la sillas a bloquear en el eje y basado en el index de la silla a comprar por el cliente
            if ($letter_id_top != 0 && $this->parameters->social_distancing_top) {
                $ids_top_group = $this->getGroupSeatByLetter($zone_id, $letter_id_top);
                $list_block_distancing = array_merge($this->getSeatBlockdistancing_y($index_seat_buy, $ids_top_group, $ids_x_group), $list_block_distancing);
            }

            if ($letter_id_bottom != 0 && $this->parameters->social_distancing_bottom) {
                $ids_bottom_group = $this->getGroupSeatByLetter($zone_id, $letter_id_bottom);
                $list_block_distancing = array_merge($this->getSeatBlockdistancing_y($index_seat_buy, $ids_bottom_group, $ids_x_group), $list_block_distancing);
            }
        }
        return $list_block_distancing;
    }


    public function deleteBlock($seat_id, $match_event_id, $user_id)
    {
        try {
            TicketUserBlock::where([['seat_id', $seat_id], ['match_event_id', $match_event_id], ['user_id', $user_id]])->delete();
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "deleteBlock", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function deleteBlockBackup($seat_id, $match_event_id, $user_id)
    {
        try {
            TicketUserBlockBackup::where([['seat_id', $seat_id], ['match_event_id', $match_event_id], ['user_id', $user_id]])->delete();
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "deleteBlockBackup", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    private function createNewBlock($data)
    {
        TicketUserBlock::create($data);
    }

    private function processBlockGeneralTicket($seat_id, $match_event_id, $user_id, $minutesToBlock, $ticket_type_id, $ticket_main_id, $zone_id, $is_social_distancing, $custom_price)
    {
        $price = 0;
        if ($custom_price) {
            $price = $custom_price;
        } else {
            if (!$is_social_distancing && $ticket_type_id != 3) {
                $zonePrice = MatchEventZonePrice::where([['zone_id', $zone_id], ['match_event_id', $match_event_id]])->first();
                if ($zonePrice && $ticket_type_id != 2) {
                    $price = $zonePrice->price;
                } else if ($zonePrice && $ticket_type_id == 2) {
                    $price = $zonePrice->price_suscription;
                }
            }
        }
        $data = [
            'seat_id'               =>  $seat_id,
            'match_event_id'        =>  $match_event_id,
            'user_id'               =>  $user_id,
            'zone_id'               =>  $zone_id,
            'start_block'           =>  Carbon::now(),
            'end_block'             =>  Carbon::now()->addMinutes($minutesToBlock),
            'is_social_distancing'  =>  $is_social_distancing,
            'price'                 =>  $price,
            'ticket_type_id'        =>  $ticket_type_id,
            'ticket_main_id'        =>  $ticket_main_id,
        ];
        $this->createNewBlock($data);
    }

    public function getEventsSubscription($seasonId = null, $matchEventId = null)
    {
        $listMatchEvents = [];
        if (!$seasonId && !$matchEventId) {
            $tournaments = Tournament::where('active', true)->get();
            foreach ($tournaments as $tournament) {
                $listSeasons = Season::where([['tournament_id', $tournament->id], ['is_suscription', true], ['active', true]])->orderBy('start', 'asc')->get();
                foreach ($listSeasons as $season) {
                    $events = MatchEvent::where([['season_id', $season->id], ['event_start', '>', Carbon::now()]])->with('team')->orderBy('event_start', 'asc')->get();
                    if ($events) {
                        $listMatchEvents[] = $events;
                    }
                }
            }
        } else if ($seasonId) {
            $events = MatchEvent::where([['season_id', $seasonId], ['event_start', '>', Carbon::now()]])->with('team')->orderBy('event_start', 'asc')->get();
            if ($events) {
                $listMatchEvents[] = $events;
            }
        } else if ($matchEventId) {
            $matchEvent = MatchEvent::find($matchEventId);
            $events = MatchEvent::where([['season_id', $matchEvent->season_id], ['event_start', '>', Carbon::now()]])->with('team')->orderBy('event_start', 'asc')->get();
            if ($events) {
                $listMatchEvents[] = $events;
            }
        }
        $result = array_flatten($listMatchEvents);
        return collect($result)->sortBy('event_start')->values();
    }

    // Genera Pin aleatorio gane.
    public function generatepin($seat_id = 1)
    {
        $date = Carbon::now();
        $date->addSeconds($seat_id);
        // return $date->getTimestamp() . rand(10,99) . rand(0,9);
        return intval($date->getPreciseTimestamp(3));
    }

    public function createTicket(
        $seat_id,
        $match_event_id,
        $user_id,
        $ticket_type_id,
        $ticket_main_id,
        $price,
        $is_from_massive = false,
        $special_text = null,
        $is_an_email_sent = false
    ) {
        try {
            $current_seat = Seat::select('code', 'zone_id', 'letter_id')->with('letter')->where('id', $seat_id)->first();
            $zone = Zone::select('id', 'name', 'door_id', 'zone_id')->where('id', $current_seat->zone_id)->first();
            $event = MatchEvent::select('code')->where('id', $match_event_id)->first();
            $door_name = null;
            if ($zone && $zone->door_id) {
                $c_q = Door::select('name')->where('id', $zone->door_id)->first();
                if ($c_q) {
                    $door_name = $c_q->name;
                }
            }
            if (!$special_text) {
                $stage = MatchEventStage::where([['match_event_id', $match_event_id], ['stage_type_id', 4]])->whereIn('zone_id', [$zone->id, $zone->zone_id])->first();
                if ($stage) {
                    $special_text = $stage->special_text;
                }
            }

            if (Ticket::where([['seat_id', $seat_id], ['match_event_id', $match_event_id], ['ticket_status_id', 1]])->first()) {
                return;
            }

            $ticket = Ticket::create([
                'code_ticket'       => config('app.client') . $this->generatepin($seat_id),
                'seat_id'           => $seat_id,
                'match_event_id'    => $match_event_id,
                'user_id'           => $user_id,
                'ticket_type_id'    => $ticket_type_id,
                'ticket_status_id'  => 1,
                'price'             => $price,
                'zone'              => $zone->name,
                'letter_seat'       => $current_seat->letter->name,
                'code_seat'         => $current_seat->code,
                'code_event'        => $event->code,
                'door'              => $door_name,
                'ticket_main_id'    => $ticket_main_id,
                'special_text'      => $special_text,
                'is_an_email_sent'  => $is_an_email_sent
            ]);


            if ($ticket && !$is_from_massive) {
                if (Auth::user()) {
                    $this->registerLog(Auth::user()->id, 'Se creo boleta', json_encode($ticket), "Create", 'Boleteria');
                } else {
                    $this->registerLog($user_id, 'Se creo boleta', json_encode($ticket), "Create", 'Boleteria');
                }
                $this->createLogTicket(1, $ticket->id);
                $message = __('messages.create_ticket');
                return array("r" => true, "type" => "success", "title" => "", "origin" => "createTicket", "m" => $message, "data" => null);
            }

            if ($is_from_massive) {
                if (Auth::user()) {
                    $this->registerLog(Auth::user()->id, 'Se creo boleta desde masivo', json_encode($ticket), "Create", 'Boleteria');
                } else {
                    $this->registerLog(null, 'Se creo boleta desde masivo', json_encode($ticket), "Create", 'Boleteria');
                }
                $this->createLogTicket(1, $ticket->id);
                return $ticket;
            }

            return array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createTicket", "m" => __('messages.error_global'), "data" => null);
        } catch (\Throwable $th) {
            return array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createTicket", "m" => __('messages.error_global'), "data" => $th->getMessage());
        }
    }

    public function existsTicket($seat_id, $event_id, $user_id)
    {
        if ($this->parameters->is_social_distancing) {
            return Ticket::where([['seat_id', $seat_id], ['match_event_id', $event_id], ['user_id', '=', $user_id]])->whereIn('ticket_status_id', [1, 2])->latest()->first();
        } else {
            return Ticket::where([['seat_id', $seat_id], ['match_event_id', $event_id]])->whereIn('ticket_status_id', [1, 2])->latest()->first();
        }
    }

    public function existsBlock($seat_id, $event_id, $user_id)
    {
        if ($this->parameters->is_social_distancing) {
            return TicketUserBlock::where([['seat_id', $seat_id], ['match_event_id', $event_id], ['is_social_distancing', false], ['user_id', '!=', $user_id]])->latest()->first();
        } else {
            return TicketUserBlock::where([['seat_id', $seat_id], ['match_event_id', $event_id]])->latest()->first();
        }
    }

    public function infoSeat($seat_id)
    {
        return Seat::where('id', $seat_id)->with('letter')->first();
    }

    public function validateBlockDistancing($ticket_main_id)
    {
        $distancing = TicketUserBlock::where([['ticket_main_id', $ticket_main_id], ['is_social_distancing', true]])->get();
        foreach ($distancing as $item) {
            $item->end_block = null;
            $item->update();
        }
    }

    // Retorna la cantidad de sillas vendibles de una tribuna
    // $currentTickets = el numero de boletas que se van a comprar en la transaccion actual
    public function salableCapacityZone($zone_id, $event_id, $currentTickets = 0, $userId = null)
    {
        $zone = Zone::where('id', $zone_id)
            ->with(['match_event_stage' => function ($q) use ($event_id) {
                $q->where('match_event_id', $event_id);
            }])
            ->first();

        $salable_capacity = $zone->salable_capacity;
        $zoneActive = $zone->active;
        if ($zone && count($zone->match_event_stage)) {
            $stage = $zone->match_event_stage->last();
            if ($stage->stage_type_id == $this->tribuneBlockingStage) {
                $zoneActive = $stage->active;
            }
            if ($stage->stage_type_id == $this->limitTribuneCapacityStage) {
                $salable_capacity = $stage->salable_capacity;
            }
            if ($stage->stage_type_id == $this->exclusiveTribuneStage) {
                $validExclusiveTribuneStage = false;
                if (Auth::user() || $userId) {
                    $userId = Auth::user() ? Auth::user()->id : $userId;
                    $stageUser = DB::table('match_event_stages')
                        ->leftJoin('match_event_stage_tags', 'match_event_stage_tags.match_event_stage_id', '=', 'match_event_stages.id')
                        ->leftJoin('user_tags', 'user_tags.tag_id', '=', 'match_event_stage_tags.tag_id')
                        ->where('match_event_stages.id', $stage->id)
                        ->where(function ($q) use ($userId) {
                            $q->where('user_tags.user_id', $userId)->orWhereNull('match_event_stage_tags.id');
                        })->count();
                    if ($stageUser) {
                        $validExclusiveTribuneStage = true;
                    }
                }
                if (!$validExclusiveTribuneStage) {
                    $this->responseCapacityZone = response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "salableCapacityZone", "m" => __('messages.error_validation_10'), "data" => null));
                    return false;
                }
            }
        }

        if ($salable_capacity == 0 || !$zoneActive) {
            $this->responseCapacityZone = response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "salableCapacityZone", "m" => __('messages.error_validation_10'), "data" => null));
            return false;
        }
        $tickets = Ticket::where('match_event_id', $event_id)
            ->whereHas('seat', function (Builder $query) use ($zone_id) {
                $query->where('zone_id', $zone_id)->whereIn('ticket_status_id', [1, 2]);
            })->count();
        $blocks = TicketUserBlock::where('match_event_id', $event_id)
            ->whereHas('seat', function (Builder $query) use ($zone_id) {
                $query->where('zone_id', $zone_id);
            })->count();

        if ($tickets + $blocks >= $salable_capacity) {
            $this->responseCapacityZone = response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "salableCapacityZone", "m" => __('messages.error_validation_8'), "data" => null));
            return false;
        }

        if ($currentTickets !== 0 && $currentTickets + $tickets + $blocks > $salable_capacity) {
            $available = $salable_capacity - ($tickets + $blocks);
            $this->responseCapacityZone = response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "salableCapacityZone", "m" => __('messages.error_validation_11', ['number' => $available]), "data" => null));
            return false;
        }

        return true;
    }

    // Retorna la suma actual de bloqueos y tickets que tiene un usuario para un evento
    public function getSumBlocksAndTicketsByUser($ticket_type_id, $user_id, $event_id)
    {
        $countTickets = Ticket::where([['ticket_type_id', $ticket_type_id], ['match_event_id', $event_id], ['user_id', $user_id]])->whereIn('ticket_status_id', [1, 2])->count();
        $countBlocks = TicketUserBlock::where([['ticket_type_id', $ticket_type_id], ['match_event_id', $event_id], ['user_id', $user_id], ['is_social_distancing', false]])->count();
        return $countTickets + $countBlocks;
    }

    public function getSumTicketsByUserFlashConfiguration($match_event_id, $user_id)
    {
        $availableTickets = DB::table('flash_ticket_configuration')
            ->select('flash_ticket_configuration.zone_id', 'flash_ticket_configuration.id', DB::raw('flash_ticket_configuration.maximum_number_ballots - COUNT(ob1.id) AS available_tickets'))
            ->leftJoin(DB::raw('(SELECT t.id, zones.zone_id FROM tickets t JOIN seats ON t.seat_id = seats.id JOIN zones ON zones.id = seats.zone_id WHERE t.user_id = ' . $user_id . ' AND t.match_event_id = ' . $match_event_id . ') as ob1'), function ($join) {
                $join->on('ob1.zone_id', '=', 'flash_ticket_configuration.zone_id');
            })
            ->where('flash_ticket_configuration.match_event_id', '=', $match_event_id)
            ->groupBy('flash_ticket_configuration.zone_id', 'flash_ticket_configuration.id', 'flash_ticket_configuration.maximum_number_ballots')
            ->get();

        return $availableTickets;
    }

    public function validateSell($zone_id, $event_id, $seat_id, $user_id, $ticket_type_id, $ticket_main_id, $type_process, $price, $pin = false, $is_transaction = false)
    {
        if ($is_transaction) {
            DB::beginTransaction();
        }
        try {
            // se valida la capacidad de la localidad no este superada
            if (!$this->salableCapacityZone($zone_id, $event_id, 0, $user_id)) {
                return $this->responseCapacityZone;
            }

            // se consulta y valida si existe un ticket o un bloqueo para esa silla
            $ticket_current = $this->existsTicket($seat_id, $event_id, $user_id);
            $ticket_block = $this->existsBlock($seat_id, $event_id, $user_id);

            if ($ticket_current) {
                $seat = $this->infoSeat($seat_id);
                $name_seat = "";
                if ($seat) {
                    $name_seat = $seat->letter->name . $seat->code;
                }
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateSell", "m" => __('messages.error_validation_3', ['seat' => $name_seat]), "data" => null));
            }

            if ($ticket_block) {
                $seat = $this->infoSeat($seat_id);
                $name_seat = "";
                if ($seat) {
                    $name_seat = $seat->letter->name . $seat->code;
                }
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateSell", "m" => __('messages.error_validation_4', ['seat' => $name_seat]), "data" => null));
            }

            // si esta activo la logica de compra con distanciamiento social
            if ($this->parameters->is_social_distancing) {
                // buscamos los vecinos de la silla origen, para validar si pueden ser bloqueadas
                $list_block_distancing = $this->searchNeighbour($seat_id, $zone_id);
                foreach ($list_block_distancing as $item) {
                    $current_block = $this->existsBlock($item, $event_id, $user_id);
                    $current_ticket = $this->existsTicket($item, $event_id, $user_id);
                    if ($current_block || $current_ticket) {
                        $seat = $this->infoSeat($seat_id);
                        $name_seat = "";
                        if ($seat) {
                            $name_seat = $seat->letter->name . $seat->code;
                        }
                        return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateSell", "m" => __('messages.error_validation_9', ['seat' => $name_seat]), "data" => $item));
                        break;
                    }
                }
            }

            if ($type_process == "ticket") {
                $transaction = $this->createTicket($seat_id, $event_id, $user_id, $ticket_type_id, $ticket_main_id, $price);
                if ($this->parameters->is_social_distancing) {
                    $this->validateBlockDistancing($ticket_main_id);
                }
                if ($is_transaction) {
                    if ($transaction["r"]) {
                        DB::commit();
                    } else {
                        DB::rollback();
                    }
                }
                return response($transaction);
            } else {
                $transaction = $this->createBlockTicket($seat_id, $event_id, $user_id, $ticket_type_id, $ticket_main_id, $zone_id, $pin, false, $price);
                if ($this->parameters->is_social_distancing) {
                    // se realiza el bloqueo de las sillas vecinas por distanciamiento
                    foreach ($list_block_distancing as $item) {
                        // se consulta si la silla vecina actual en el ciclo es una silla de las que se va a comprar, para no realizar el bloqueo
                        $is_buy_seat = TicketUserBlock::where([['seat_id', $item], ['user_id', $user_id], ['match_event_id', $event_id], ['is_social_distancing', false]])->first();
                        if (!$is_buy_seat) {
                            $this->createBlockTicket($item, $event_id, $user_id, $ticket_type_id, $ticket_main_id, $zone_id, $pin, true, $price);
                        }
                    }
                    // se elimina cualquier bloqueo de la silla a comprar si es del mismo usuario y tiene bloqueo por distanciamiento
                    $list_distancing = TicketUserBlock::where([
                        ['seat_id', $seat_id],
                        ['user_id', $user_id],
                        ['match_event_id', $event_id],
                        ['is_social_distancing', true]
                    ])->get();
                    foreach ($list_distancing as $d_seat) {
                        $d_seat->delete();
                    }
                }
                if ($is_transaction) {
                    if ($transaction["r"]) {
                        DB::commit();
                    } else {
                        DB::rollback();
                    }
                }
                return response($transaction);
            }
        } catch (\Throwable $th) {
            if ($is_transaction) {
                DB::rollback();
            }
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateSell", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function createBlock(Request $request, $origin)
    {
        DB::beginTransaction();
        try {
            // se valida la capacidad de la localidad no este superada
            if (!$this->salableCapacityZone($request->input('tickets')[0]["seat"]["zone_id"], $request->input('tickets')[0]["match_event_id"], count($request->input('tickets')))) {
                DB::rollback();
                return $this->responseCapacityZone;
            }

            $userController = new UserController($request);
            $user = $userController->searchUser($request->document, $request->email, $request->first_name, $request->last_name, $request->phone);
            if (!$user) {
                $current_user = $userController->createClient($request, true);
                if ($current_user["r"]) {
                    $user = $current_user["d"];
                } else {
                    DB::rollback();
                    return response($current_user);
                }
            }
            $user_id = $user->id;

            $sumTicketsBlocks = $this->getSumBlocksAndTicketsByUser($request->input('ticket_type_id'), $user_id, $request->input('tickets')[0]["match_event_id"]) + count($request->input('tickets'));
            $flashController = new FlashTicketController;
            $matchEventsController = new MatchEventsController;
            $maximum = !$matchEventsController->validateSaleByCapacity($request->input('tickets')[0]["match_event_id"]) ? $this->parameters->maximum_number_ballots : $flashController->getMaximumTicketsToBuy($request->input('tickets')[0]["match_event_id"]);
            // Valida el numero maximo de boletas que puede comprar el usuario.
            if ($request->input('ticket_type_id') == 1 && $sumTicketsBlocks > $maximum) {
                DB::rollback();
                $available = $maximum - ($sumTicketsBlocks - count($request->input('tickets')));
                if ($available < 0) $available = 0;
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createBlock", "m" => __('messages.error_validation_5', ['number' => $available]), "data" => null));
            }

            // Valida el numero máximo de abonos.
            if ($request->input('ticket_type_id') == 2 && $sumTicketsBlocks > $this->parameters->maximum_number_suscription) {
                DB::rollback();
                $available = $this->parameters->maximum_number_suscription - ($sumTicketsBlocks - count($request->input('tickets')));
                if ($available < 0) $available = 0;
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createBlock", "m" => __('messages.error_validation_6', ['number' => $available]), "data" => null));
            }

            $pin = null;
            $pin_tercero = null;
            $pin_internal = null;
            if ($origin == 'external') {
                $pin_tercero = $this->generatepin();
                $pin = $pin_tercero;
            }

            if ($origin == 'internal') {
                $pin_internal = $this->generatepin();
                $pin = $pin_internal;
            }
            $seller_id = null;
            if (Auth::user()->rol_id != 4) {
                $seller_id = Auth::user()->id;
            }
            $subtotal = $request->input('subtotal') ?? 0;
            $serviceCharge = $request->input('serviceCharge') ?? 0;
            $total = $request->input('amount') ?? $request->input('total') ?? 0;

            $main = TicketMain::create([
                'subtotal'          => $subtotal,
                'service_charge'    => $serviceCharge,
                'total'             => $total,
                'pin_internal'      => $pin_internal,
                'pin_tercero'       => $pin_tercero,
                'user_id_log'       => $user_id,
                'seller_user_id'    => $seller_id,
                'origin'            => 'web',
            ]);

            $log_tickets_main = "";

            if ($request->input('ticket_type_id') != 2) {
                foreach ($request->input('tickets') as $ticket) {
                    $zone_id    = $ticket["seat"]["zone_id"];
                    $event_id   = $ticket["match_event_id"];
                    $seat_id    = $ticket["seat"]["id"];

                    $log_tickets_main = $log_tickets_main . "zone: " . $zone_id . "event: " . $event_id . "seat: " . $seat_id . "\n";

                    // creamos los bloqueos
                    $data = $this->validateSell($zone_id, $event_id, $seat_id, $user_id, $ticket["ticket_type_id"], $main->id, $request->input('type_process'), 0, $pin);
                    $response = json_decode($data->getContent());
                    if (!$response->r) {
                        DB::rollback();
                        return $data;
                        break;
                    }
                }
            } else {
                $log_tickets_main = 'Abonado, user_id: ' . $user_id;
                $listEvents = $this->getEventsSubscription($request->input('season_id'), $request->input('match_event_id'));
                if ($listEvents && count($listEvents) > 0) {
                    foreach ($request->input('tickets') as $ticket) {
                        foreach ($listEvents as $event) {
                            $zone_id    = $ticket["seat"]["zone_id"];
                            $event_id   = $event->id;
                            $seat_id    = $ticket["seat"]["id"];

                            if (isset($ticket["dataTicket"]) && !$ticket["dataTicket"]["checkedCtrl"]) {
                                if (!$user_id) {
                                    $user = $userController->searchUser($ticket["dataTicket"]["document"], $ticket["dataTicket"]["email_user"], $ticket["dataTicket"]["first_name"], $ticket["dataTicket"]["last_name"], $ticket["dataTicket"]["phone"], true);
                                    if (!$user) {
                                        $custom_request = new Request([
                                            'first_name'   => $ticket["dataTicket"]["first_name"],
                                            'last_name' => $ticket["dataTicket"]["last_name"],
                                            'phone' => $ticket["dataTicket"]["phone"],
                                            'email' => $ticket["dataTicket"]["email_user"],
                                            'password' => $ticket["dataTicket"]["phone"] + $ticket["dataTicket"]["document"],
                                            'document' => $ticket["dataTicket"]["document"],
                                        ]);
                                        $current_user = $userController->createClient($custom_request, true);
                                        if ($current_user["r"]) {
                                            $user = $current_user["d"];
                                            $user_id = $user->id;
                                        } else {
                                            DB::rollback();
                                            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateUserByTicket", "m" => __('messages.error_global'), "data" => $current_user));
                                            break;
                                        }
                                    }
                                }
                                $ticket["dataTicket"]["checkedCtrl"] = true;
                            }

                            // creamos los bloqueos
                            $data = $this->validateSell($zone_id, $event_id, $seat_id, $user_id, $ticket["ticket_type_id"], $main->id, $request->input('type_process'), 0, $pin);
                            $response = json_decode($data->getContent());
                            if (!$response->r) {
                                DB::rollback();
                                return $data;
                                break;
                            }
                        }
                    }
                }
            }

            $main->comment_purchase_log = $log_tickets_main;
            $main->update();

            DB::commit();
            return $data;
        } catch (\Throwable $th) {
            DB::rollback();
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createBlock", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function getMatchEventsSuscription(Request $request)
    {
        try {
            $list_match_events = $this->getEventsSubscription($request->input('season_id'), $request->input('match_event_id'));
            $team_main = Team::where([['is_main', true], ['active', true]])->first();
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => array('list_match_events' => $list_match_events, 'team_main' => $team_main)));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "getMatchEventsSuscription", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    /*
        @tickets Type TicketUserBlock listado de bloqueos.
        @ticket_main_id Type int id de la cabecera de ticketes.
    */
    public function generateTickets($tickets, $ticket_main_id, $isBackup = false)
    {
        DB::beginTransaction();
        try {
            // Validar reserva de abonos para fijar que ya estan pagos y tiene asociados los tiquetes
            $parameters = Parameter::select('presuscription', 'web_presuscription')->first();
            if ($parameters->presuscription || $parameters->web_presuscription) {
                $seats = $tickets->where('ticket_type_id', 2)->pluck('seat_id');
                if (count($seats) > 0) {
                    try {
                        $user = User::where('id', $tickets[0]->user_id)->first();
                        PreSubscriber::where([['payment', 0], ['document', $user->document]])->whereIn('seat_id', $seats)->update(['payment' => 1]);
                        Mail::to($user->email)->send(new NewSuscriptorMail($user->first_name . " " . $user->last_name));
                    } catch (\Exception $err) {
                        $log = array(
                            'error'         => $err->getMessage(),
                            'user'          => $user,
                        );
                        $util = new UtilController();
                        $util->logFile(json_encode($log), 'sendListMail');
                    }
                }
            }

            $data = response(array("r" => false, "type" => "", "title" => "", "m" => "No se ha podido generar las boletas.", "data" => ""));
            $ticketMain = TicketMain::select('origin')->where('id', $ticket_main_id)->first();
            $notifyBuyTickets = $this->ticketParametersService->validateSendingEmailTickets($ticketMain->origin);
            foreach ($tickets as $key => $t) {
                // eliminamos el bloqueo.
                if (!$isBackup) {
                    $this->deleteBlock($t->seat_id, $t->match_event_id, $t->user_id);
                } else {
                    $this->deleteBlockBackup($t->seat_id, $t->match_event_id, $t->user_id);
                }

                // Validamos la silla y creamos el ticket
                $data = $this->validateSell($t->zone_id, $t->match_event_id, $t->seat_id, $t->user_id, $t->ticket_type_id, $ticket_main_id, 'ticket', $t->price);
                $response = json_decode($data->getContent());
                if (!$response->r) {
                    if ($isBackup) {
                        // Validar si hay alguna silla disponible, caso contrario hacer ROLLBACK
                        $dataOptional = $this->validateOptionalSeatForSell($t);
                        $responseOptional = json_decode($dataOptional->getContent());
                        if ($responseOptional->r) {
                            $data = $dataOptional;
                            continue;
                        }
                        DB::rollback();
                        return $data;
                        break;
                    }
                    DB::rollback();
                    return false;
                    break;
                }
            }
            DB::commit();
            // se envian los correos con el link de las boletas
            if ($notifyBuyTickets) {
                $listTickets = Ticket::where('ticket_main_id', $ticket_main_id)->get();
                $totalTickets = count($listTickets);
                if ($totalTickets > 0) {
                    $ticketsToSendByMail = new Collection();
                    foreach ($listTickets as $index => $ticket) {
                        if ($totalTickets == 1) {
                            try {
                                $this->sendSingleEmailTicket($ticket->user_id, $ticket->code_ticket);
                            } catch (\Exception $exx1) {
                                $util = new UtilController();
                                $util->logFile('sendSingleEmailTicket: ' . json_encode($exx1->getMessage()));
                            }
                        } else {
                            $obj                = new \stdClass();
                            $obj->user_id       = $ticket->user_id;
                            $obj->code_ticket   = $ticket->code_ticket;
                            $ticketsToSendByMail->push($obj);
                            if ($totalTickets == ($index + 1)) {
                                try {
                                    $this->sendEmailMultipleTickets($ticket->user_id, $ticketsToSendByMail, $ticket->ticket_type_id, $ticket->match_event_id);
                                } catch (\Exception $exx1) {
                                    $util = new UtilController();
                                    $util->logFile('sendEmailMultipleTickets: ' . json_encode($exx1->getMessage()));
                                }
                            }
                        }
                        $smsNotifications = new SmsNotificationsController();
                        if ($smsNotifications->activeStatusSendSms()) {
                            try {
                                $this->sendMassSmsNotifications($ticket->user_id, $ticket->code_ticket);
                            } catch (\Exception $exx2) {
                                $util = new UtilController();
                                $util->logFile('sendMassSmsNotifications: ' . json_encode($exx2->getMessage()));
                            }
                        }
                    }
                }
            }

            if ($isBackup) {
                return $data;
            }
            return true;
        } catch (\Throwable $th) {
            DB::rollback();
            return false;
        }
    }

    public function createLogTicket($state_id, $ticket_id)
    {
        try {
            $ticketLog = TicketLog::create(['ticket_id' => $ticket_id, 'ticket_status_id' => $state_id]);
            if (Auth::user()) {
                $this->registerLog(Auth::user()->id, 'Actualizó estado boleta', json_encode($ticketLog), "Update", 'Boleteria');
            } else {
                $this->registerLog(null, 'Actualizó estado boleta', json_encode($ticketLog), "Update", 'Boleteria');
            }
            return response(array("r" => true, "type" => "success", "title" => "", "m" => "", "data" => null));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "createLogTicket", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function changeStateTicket(Request $request)
    {
        try {
            if ($request->state_id != 3 && $request->state_id != 4) {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.state_invalid'), "data" => null));
            }

            $ticket = Ticket::where('id', $request->ticket_id)->with('seat')->first();

            if ($ticket->update(['ticket_status_id' => $request->state_id])) {
                $this->createLogTicket($request->state_id, $request->ticket_id);
            }
            return response(array("r" => true, "type" => "success", "title" => "Ok", "m" => __('messages.updated_successfully'), "data" => null));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_global'), "data" => $th->getMessage()));
        }
    }

    public function massBallotStatusChange(Request $request)
    {
        try {
            $file = new CancelTicketsImport;
            $file->request = $request;
            Excel::import($file, $request->archivo);
            return response(array("r" => true, 'd' => $file->answer, "m" => __('messages.match_event_tickets.title_24'), "data" => null));
        } catch (\Exception $e) {
            return response(array('r' => false, 'd' => null, 'm' => trans('messages.match_event_tickets.title_25') . $request->name_file . "  " . $e->getMessage()));
        }
    }

    /**
     * Update the specified resource in storage.
     *
     */
    public function update(Request $request)
    {
        $user = User::find($request["user_id"]);
        $user->first_name = $request["first_name"];
        $user->last_name = $request["last_name"];
        $user->document = $request["document"];
        $user->phone = $request["phone"];
        $user->email = $request["email"];
        $user->update();

        if ($user) {
            return array('r' => true, 'd' => array('id' => $user->id), 'm' => trans('messages.updated_successfully'));
        } else {
            return array('r' => false, 'd' => null, 'm' => trans('messages.error_updating'));
        }
    }

    public function toUpdateUsersWithTickets(Request $request)
    {
        $results = Ticket::where([
            'match_event_id' => $request->id_event,
            'user_id' => $request->userIdError,
            'code_ticket' => $request->id_code,
        ])->update(['user_id' => $request['usertIdValid']]);
        if ($results) {
            return array('r' => true, 'd' => array('id' => 1), 'm' => trans('messages.updated_successfully'));
        } else {
            return array('r' => false, 'd' => null, 'm' => trans('messages.error_updating'));
        }
    }

    public function sendSingleEmailTicket($userId, $code)
    {
        try {
            $user = User::find($userId);
            Mail::to($user->email)->send(new TicketPurchaseMail($user, $code));
            $this->updateSentEmailIndicatorInTicket($code);
            return array('s' => true, 'm' => 'Mail enviado');
        } catch (\Exception $err) {
            $log = array(
                'error'         => $err->getMessage(),
                'user'          => $user,
                'code'          => $code
            );
            $util = new UtilController();
            $util->logFile(json_encode($log), 'sendSingleEmailTicket');
            return array('s' => false, 'm' => 'Mail no enviado');
        }
    }

    public function sendEmailMultipleTickets($userId, $ticketsToSendByMail, $ticket_type_id, $match_event_id)
    {
        try {
            $user = User::find($userId);
            Mail::to($user->email)->send(new TicketPurchaseEmailList($ticketsToSendByMail, $ticket_type_id, $match_event_id, $user));
            $this->updateSentEmailIndicatorInTickets($ticketsToSendByMail);
            return array('s' => true, 'm' => 'Mail enviado');
        } catch (\Exception $err) {
            $log = array(
                'error'                     => $err->getMessage(),
                'user'                      => $user,
                'ticketsToSendByMail'       => $ticketsToSendByMail,
                'ticket_type'               => $ticket_type_id,
                'match_event'               => $match_event_id
            );
            $util = new UtilController();
            $util->logFile(json_encode($log), 'sendEmailMultipleTickets');
            return array('s' => false, 'm' => 'Mail no enviado');
        }
    }

    private function updateSentEmailIndicatorInTicket($codeTicket)
    {
        $ticket = Ticket::where('code_ticket', $codeTicket)->first();
        $ticket->is_an_email_sent = 1;
        $ticket->update();
    }

    private function updateSentEmailIndicatorInTickets($tickets)
    {
        foreach ($tickets as $ticket) {
            $this->updateSentEmailIndicatorInTicket($ticket->code_ticket);
        }
    }

    public function validateMails()
    {
        DB::statement("SET sql_mode = ''");
        $origins = [];
        if ($this->ticketParametersService->validateSendingEmailTickets('app')) {
            array_push($origins, 'app');
        }
        if ($this->ticketParametersService->validateSendingEmailTickets('web')) {
            array_push($origins, 'web');
        }

        $sql = "SELECT tm.id, tm.origin, GROUP_CONCAT(DISTINCT(t.user_id)) AS user_id, GROUP_CONCAT(DISTINCT(t.ticket_type_id)) AS ticket_type_id,
                GROUP_CONCAT(DISTINCT(t.match_event_id)) AS match_event_id, GROUP_CONCAT(DISTINCT(t.code_ticket)) AS codes
            FROM tickets t
            JOIN ticket_mains tm ON tm.id = t.ticket_main_id
            JOIN match_events me ON me.id = t.match_event_id
            WHERE t.is_an_email_sent = 0 AND t.ticket_status_id = 1 AND t.ticket_type_id IN (1,3) 
                    AND me.event_end_sale > convert_tz(now(),'system','America/Bogota')
                    AND t.created_at > DATE_SUB(convert_tz(now(),'system','America/Bogota'), INTERVAL 2 HOUR) 
                    " . (count($origins) > 0 ? " AND tm.origin IN ('" . implode("','", $origins) . "')" : ' AND tm.origin IS NULL ') . "
            GROUP BY tm.id";
        $tickets = DB::select(DB::raw($sql));
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");

        foreach ($tickets as $ticket) {
            $codes = explode(',', $ticket->codes);
            if (count($codes) > 1) {
                $ticketsToSendByMail = new Collection();
                foreach ($codes as $code) {
                    $obj                = new \stdClass();
                    $obj->user_id       = $ticket->user_id;
                    $obj->code_ticket   = $code;
                    $ticketsToSendByMail->push($obj);
                }
                $this->sendEmailMultipleTickets($ticket->user_id, $ticketsToSendByMail, $ticket->ticket_type_id, $ticket->match_event_id);
            } else {
                $this->sendSingleEmailTicket($ticket->user_id, $codes[0]);
            }
        }

        return array(
            'r' => true,
            'data' => null,
            'm' => 'Se validaron ' . count($tickets) . ' boletas pendientes de envio de correo.'
        );
    }

    public function sendMassSmsNotifications($userId, $code)
    {
        try {
            $dataUser = User::select('id', 'first_name', 'phone')->find($userId);
            event(new SmsNotificationEvent($dataUser, $code));
            return array('r' => true, 'm' => trans('SMS enviado'));
        } catch (\Exception $e) {
            return array('r' => false, 'm' => trans('SMS no enviado'));
        }
    }

    public function getAttachment($idUserEmail, $code)
    {
        $prinkTickets = new PrintTicketController;
        return $prinkTickets->printTicketForMassMail($idUserEmail, $code);
    }

    public function getPin($url_key)
    {
        $corporateIdentity = CorporateIdentity::first();
        return view("tickets.getPin", compact('url_key', 'corporateIdentity'));
    }

    public function getAttachmentFromPublic(Request $request)
    {
        $decrypted  = "";
        $url_key    = $request->url_key;
        $key        = $request->key;

        try {
            $decrypted = Crypt::decryptString($url_key);
        } catch (\Exception $exx) {
            return array('Error');
        }

        if (!$decrypted) {
            return array('Error');
        }

        $decrypted = explode('|', $decrypted);

        if ($decrypted[0] != $key) {
            return array('Pin no válido. Revisa el pin enviado a tu correo');
        }

        if ($decrypted[3] == 'lista') {
            $user_id        = $decrypted[1];
            $match_event_id = $decrypted[2];
            $ticket_type_id = $decrypted[4];

            $tickets = Ticket::select('id', 'code_ticket', 'user_id')
                ->where('user_id', $user_id)
                ->where('match_event_id', $match_event_id)
                ->where('ticket_type_id', $ticket_type_id) // posicion 4 tiene el ticket type
                ->whereIn('ticket_status_id', [1, 2])
                ->get();

            return $this->downloadZipTickets($tickets, $user_id, $match_event_id);
        }

        if ($decrypted[3] == 'cortesia') {
            $user_id = $decrypted[1];
            $match_event_id = $decrypted[2];

            $tickets = Ticket::select('id', 'code_ticket', 'user_id')
                ->where('user_id', $user_id)
                ->where('match_event_id', $match_event_id)
                ->where('ticket_type_id', 3) // 3 = Tipo ticket cortesia
                ->whereIn('ticket_status_id', [1, 2])
                ->get();

            return $this->downloadZipTickets($tickets, $user_id, $match_event_id);
        }

        if ($decrypted[3] == 'ticket') {
            $code = $decrypted[2];
            return $this->printTicket($code);
        }
    }

    public function printTicket($code)
    {
        $prinkTickets = new PrintTicketController;
        return $prinkTickets->printTicketForMassMail($code);
    }

    public function downloadZipTickets($tickets, $user_id, $match_event_id, $fileName = "")
    {
        if ($tickets) {
            $prinkTickets = new PrintTicketController;
            $pdfAttachment = [];

            // Generar todos los PDF, uno por uno
            foreach ($tickets as $t) {
                $pdfAttachment[] = $prinkTickets->printTicketForMassMail($t->code_ticket, "file");
            }

            // Los comprimo y envío a descargar.
            $zipFilename = "tickets-$user_id-$match_event_id-$fileName.zip";
            Madzipper::make("tickets_tmp/$zipFilename")->add($pdfAttachment)->close();

            $file = public_path() . "/tickets_tmp/$zipFilename";
            $headers = array('Content-Type: application/zip');
            return Response::download($file, "$zipFilename", $headers);
        }
    }

    public function getPinMultiple($url_key)
    {
        $corporateIdentity = CorporateIdentity::first();
        return view("tickets.getPinMultiple", compact('url_key', 'corporateIdentity'));
    }

    function countTicketsAndGetLinks(Request $request)
    {
        $decrypted = "";
        $url_key  = $request->url_key;
        $key = $request->key;

        try {
            $decrypted = Crypt::decryptString($url_key);
        } catch (\Exception $exx) {
            return array('Error');
        }

        if (!$decrypted) {
            return array('Error');
        }

        $decrypted = explode('|', $decrypted);

        if ($decrypted[0] != $key) {
            return array('Pin no válido. Revisa el pin enviado a tu correo');
        }

        if ($decrypted[3] == 'multiple') {
            $user_id = $decrypted[1];
            $match_event_id = $decrypted[2];
            $ticket_type_id = $decrypted[4];

            $user = User::find($user_id);
            $match = MatchEvent::find($match_event_id);
            $ticket_type = TicketType::find($ticket_type_id);

            if (!$user) {
                return array('Error' => 'Revise datos usuario');
            }

            if (!$match) {
                return array('Error' => 'Revise datos evento');
            }

            if (!$ticket_type) {
                return array('Error' => 'Revise datos tipo ticket');
            }

            $total = Ticket::select('id', 'code_ticket', 'user_id')
                ->where('user_id', $user_id)
                ->where('match_event_id', $match_event_id)
                ->where('ticket_type_id', $ticket_type_id) // 3 = Tipo ticket cortesia
                ->whereIn('ticket_status_id', [1, 2])
                ->count();

            $limitPerPage = 100;
            $pages = ceil($total /  $limitPerPage);
            $skip = 0;

            $arrayLinks = array();
            for ($i = 0; $i < $pages; $i++) {
                $arrayLinks[] = "/download_ticket_for_user/links/$user_id/$match_event_id/$ticket_type_id/$limitPerPage/$skip";
                $skip = $skip + $limitPerPage;
            }

            return view('tickets.links')
                ->with('total', $total)
                ->with('links', $arrayLinks)
                ->with('user', $user)
                ->with('match', $match)
                ->with('ticket_type', $ticket_type);
        }
        return array('Error');
    }

    function downloadLinks($user_id, $match_event_id, $ticket_type_id, $take, $skip)
    {
        $tickets = Ticket::select('id', 'code_ticket', 'user_id')
            ->where('user_id', $user_id)
            ->where('match_event_id', $match_event_id)
            ->where('ticket_type_id', $ticket_type_id) // 3 = Tipo ticket cortesia
            ->whereIn('ticket_status_id', [1, 2])
            ->skip($skip)
            ->take($take)
            ->get();
        return $this->downloadZipTickets($tickets, $user_id, $match_event_id, (($skip / 100) + 1));
    }

    function validateDownloadPanelTickets($email, $match_event_id, $from_date = null, $to_date = null, $type = null)
    {
        $user = User::select('id')->where('email', $email)->first();
        if (!$user) {
            $error_message = "No se ha encontrado usuario para este mail.";
            return response()->json(['success' => false, 'message' => $error_message]);
        }
        if ($from_date && is_numeric($from_date)) {
            $type = $from_date;
            $from_date = null;
        }
        $tickets = DB::table('tickets')
            ->select(['tickets.id', 'tickets.code_ticket', 'tickets.user_id'])
            ->where('tickets.user_id', $user->id)
            ->where('tickets.match_event_id', $match_event_id)
            ->whereIn('tickets.ticket_status_id', [1, 2])
            ->where(function ($query) use ($from_date, $to_date, $type) {
                if ($from_date && $to_date) {
                    $query->whereBetween('tickets.created_at', [$from_date, $to_date]);
                }
                if ($type) {
                    $query->where('tickets.ticket_type_id', $type);
                }
            })
            ->count();
        if ($tickets == 0) {
            return response()->json(['success' => false, 'message' => 'No existen boletas a generar para el usuario']);
        }
        return response()->json(['success' => true, 'message' => 'Validación OK', 'data' => $tickets]);
    }

    function downloadPanelTickets($email, $match_event_id, $from_date = null, $to_date = null, $type = null)
    {
        $user = User::select('id')->where('email', $email)->first();
        if ($from_date && is_numeric($from_date)) {
            $type = $from_date;
            $from_date = null;
        }
        $tickets = DB::table('tickets')
            ->select(['tickets.id', 'tickets.code_ticket', 'tickets.user_id'])
            ->where('tickets.user_id', $user->id)
            ->where('tickets.match_event_id', $match_event_id)
            ->whereIn('tickets.ticket_status_id', [1, 2])
            ->where(function ($query) use ($from_date, $to_date, $type) {
                if ($from_date && $to_date) {
                    $query->whereBetween('tickets.created_at', [$from_date, $to_date]);
                }
                if ($type) {
                    $query->where('tickets.ticket_type_id', $type);
                }
            })
            ->get();
        $fecha = new DateTime();
        return $this->downloadZipTickets($tickets, $user->id, $match_event_id, $fecha->getTimestamp());
    }

    public function deleteTicketTemplate()
    {
        return Excel::download(new CancelTicketsTemplate, trans('messages.match_event_tickets.title_22') . '.xlsx');
    }

    public function ticketSeatLocationFullText($ticket)
    {
        $seat = '';
        if ($ticket) {
            $seat = $ticket->seat->zone->zone->name . ' - ' . $ticket->seat->zone->name . ' - ' . $ticket->seat->letter->name . $ticket->seat->code;
        }
        return $seat;
    }

    public function validateOptionalSeatForSell($ticket)
    {
        $mainZone = null;
        if ($ticket->seat && $ticket->seat->zone)
            $mainZone = $ticket->seat->zone->zone_id;
        $secondaryZone = $ticket->zone_id;

        $zoneController = new ZonesController();
        $zones = $zoneController->getAvailableZones($mainZone, $secondaryZone, $ticket->match_event_id, true);
        foreach ($zones as $zone) {
            $masive = new MassiveFansController();
            $seats = $masive->getSeatsAvailableFromLocationAndEvent($zone, 1, $ticket->match_event_id);
            if (count($seats) > 0) {
                $seat_id = $seats[0]->id;
                $data = $this->validateSell($zone, $ticket->match_event_id, $seat_id, $ticket->user_id, $ticket->ticket_type_id, $ticket->ticket_main_id, 'ticket', $ticket->price);
                $response = json_decode($data->getContent());
                if ($response->r) {
                    return $data;
                }
            }
        }
        return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "validateOptionalSeatForSell", "data" => $ticket));
    }

    public function getPendingMatchesTickets($ticket_id_origin, $tribune_id_final, $zone_id_final, $seat_id_final)
    {
        $userTicket = Ticket::with("match_event:id,season_id")->select("id", "user_id", "match_event_id", "seat_id", "ticket_type_id")->where('id', $ticket_id_origin)->first();
        $pendingTickets = [];

        if ($userTicket->ticket_type_id == 2) {
            $pendingTickets = Ticket::select("id", "code_ticket", "seat_id", "match_event_id", "door", "zone", "letter_seat", "code_seat")
                ->with("match_event:id,event_start,date_name,name")
                ->whereHas('match_event', function ($match_event) use ($userTicket) {
                    $match_event->where('event_start', '>=', Carbon::now());
                    $match_event->where('season_id', $userTicket->match_event->season_id);
                })
                ->where('seat_id', $userTicket->seat_id)
                ->where('user_id', $userTicket->user_id)
                ->where('ticket_type_id', 2)
                ->get();
        } else {
            $pendingTickets = Ticket::select("id", "code_ticket", "seat_id", "match_event_id", "door", "zone", "letter_seat", "code_seat")
                ->with("match_event:id,date_name,name")
                ->where('id', $userTicket->id)
                ->get();
        }

        return $pendingTickets;
    }

    public function postChangeSeat(Request $request)
    {

        $current_seat = Seat::select('code', 'zone_id', 'letter_id')->with('letter')->where('id', $request->seat_id_final)->first();
        $name_seat = $current_seat->letter->name . $current_seat->code;
        $zone = Zone::select('name', 'door_id')->where('id', $current_seat->zone_id)->first();

        $door_name = null;
        if ($zone && $zone->door_id) {
            $c_q = Door::select('name')->where('id', $zone->door_id)->first();
            if ($c_q) {
                $door_name = $c_q->name;
            }
        }

        $userTicket = Ticket::with("match_event:id,season_id")->select("id", "user_id", "match_event_id", "seat_id", "ticket_type_id")->where('id', $request->ticket_id_origin)->first();

        // Abonados
        if ($userTicket->ticket_type_id == 2) {
            $pendingTickets = Ticket::select("id", "code_ticket", "seat_id", "match_event_id", "door", "zone", "letter_seat", "code_seat")->with("match_event:id,event_start,date_name,name")
                ->whereHas('match_event', function ($match_event) use ($userTicket) {
                    $match_event->where('event_start', '>=', Carbon::now());
                    $match_event->where('season_id', $userTicket->match_event->season_id);
                })
                ->where('seat_id', $userTicket->seat_id)
                ->where('user_id', $userTicket->user_id)
                ->where('ticket_type_id', 2)
                ->get();
        } else {
            $pendingTickets = Ticket::select("id", "code_ticket", "seat_id", "match_event_id", "door", "zone", "letter_seat", "code_seat")
                ->where('id', $userTicket->id)
                ->get();
        }


        try {
            DB::beginTransaction();
            foreach ($pendingTickets as $p) {
                $ticket_current = $this->existsTicket($request->seat_id_final, $p->match_event_id, $userTicket->user_id);
                $ticket_block = $this->existsBlock($request->seat_id_final, $p->match_event_id, $userTicket->user_id);

                if ($ticket_current) {
                    DB::rollback();
                    return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "postChangeSeat", "m" => __('messages.error_validation_3', ['seat' => $name_seat]), "data" => null, 't' => $ticket_current));
                }

                if ($ticket_block) {
                    DB::rollback();
                    return response(array("r" => false, "type" => "error", "title" => "Oops...", "origin" => "postChangeSeat", "m" => __('messages.error_validation_4', ['seat' => $name_seat]), "data" => null, 't' => $ticket_block));
                }

                // Buscar ticket y actualizar.
                $ticketToChange = Ticket::find($p->id);

                $ticketToChange->seat_id = $request->seat_id_final;
                $ticketToChange->zone = $zone->name;
                $ticketToChange->letter_seat = $current_seat->letter->name;
                $ticketToChange->code_seat = $current_seat->code;
                $ticketToChange->door = $door_name;

                $ticketToChange->update();
            }
            DB::commit();
        } catch (\Exception $exx) {
            DB::rollback();
            return array('r' => false, 'm' => $exx->getMessage());
        }


        return array('r' => true, 'm' => 'Proceso exitoso');
    }

    public function getTotalByMatchCode($match_code)
    {
        $m = MatchEvent::select('id', 'name', 'event_start')->where('code', $match_code)->first();

        if (!$m) {
            return array('error' => 'El evento no existe');
        }

        $ticketsVendidos = Ticket::where('match_event_id', $m->id)
            ->where('ticket_status_id', [1, 2])
            ->count();

        $ticketsAnulados = Ticket::where('match_event_id', $m->id)
            ->where('ticket_status_id', 3)
            ->count();

        return array(
            'Evento' => $m->name,
            'Hora inicio evento' => $m->event_start,
            'Total vendidos - anulados' => $ticketsVendidos,
            'Total anulados' => $ticketsAnulados,
            'Total tickets vendidos + anulados' => ($ticketsVendidos + $ticketsAnulados)
        );
    }

    public function exportMatchEventSeatsTemplate()
    {
        return Excel::download(new MatchEventSeatsTemplate, trans('messages.match_event_tickets.title_31') . '.xlsx');
    }

    public function importMatchEventSeats(Request $request)
    {
        try {
            $file = new MatchEventSeatsImport($request->matchEventId);
            $file->request = $request;
            Excel::import($file, $request->archivo);
            return array('r' => true, 'd' => $file->answer, 'm' => trans('messages.match_event_tickets.title_33') . ' ' . $file->edit['actualizados'] . ' actualizados.');
        } catch (\Exception $e) {
            return array('r' => false, 'd' => null, 'm' => trans('messages.match_event_tickets.title_34') . $request->name_file . "  " . $e->getMessage());
        }
    }

    public function exportMatchEventSpecialTextTemplate()
    {
        return Excel::download(new MatchEventSpecialTextTemplate, trans('messages.match_event_tickets.title_37') . '.xlsx');
    }

    public function importMatchEventSpecialText(Request $request)
    {
        try {
            $file = new MatchEventSpecialTextImport($request->matchEventId);
            $file->request = $request;
            Excel::import($file, $request->archivo);
            return array('r' => true, 'd' => $file->answer, 'm' => trans('messages.match_event_tickets.title_33') . ' ' . $file->edit['actualizados'] . ' actualizados.');
        } catch (\Exception $e) {
            return array('r' => false, 'd' => null, 'm' => trans('messages.match_event_tickets.title_34') . $request->name_file . "  " . $e->getMessage());
        }
    }

    public function getSeatFreeByZonesOrSeat($match_event_id, $zones, $seat = null)
    {
        $matchEvent = MatchEvent::with('season')->where('id', $match_event_id)->first();
        $parameters = Parameter::select('presuscription')->first();
        $presubscriptionActive = $parameters->presuscription && $matchEvent->season->is_suscription;

        $freeSeat = null;
        if ($seat) {
            $freeSeat = Seat::with('letter')
                ->where('id', $seat)
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('ticket_user_blocks')->where('match_event_id', $match_event_id);
                }) // Sin bloqueos
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('tickets')->where('match_event_id', $match_event_id)->whereIn('ticket_status_id', [1, 2]);
                }) // Que no este vendida
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('match_event_stages')->where('match_event_id', $match_event_id)->where('stage_type_id', $this->seatStage);
                }) // Que no este bloqueada para el evento
                ->when($presubscriptionActive, function ($query) {
                    $query->whereNotIn('id', function ($query) {
                        $query->select('seat_id')->from('pre_subscribers');
                    });
                }) // Que no este reservada para un abonado
                ->first();
        }
        if (!$freeSeat) {
            $freeSeat = Seat::with('letter')
                ->whereIn('zone_id', $zones)
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('ticket_user_blocks')->where('match_event_id', $match_event_id);
                }) // Sin bloqueos
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('tickets')->where('match_event_id', $match_event_id)->whereIn('ticket_status_id', [1, 2]);
                }) // Que no este vendida
                ->whereNotIn('id', function ($query) use ($match_event_id) {
                    $query->select('seat_id')->from('match_event_stages')->where('match_event_id', $match_event_id)->where('stage_type_id', $this->seatStage);
                }) // Que no este bloqueada para el evento
                ->when($presubscriptionActive, function ($query) {
                    $query->whereNotIn('id', function ($query) {
                        $query->select('seat_id')->from('pre_subscribers');
                    });
                }) // Que no este reservada para un abonado
                ->first();
        }
        return $freeSeat;
    }

    public function changeFreeSeatToTicket($ticket, $freeSeat, $specialTicket = null)
    {
        $current_seat = Seat::select('code', 'zone_id', 'letter_id')->with('letter')->where('id', $freeSeat)->first();
        $name_seat = $current_seat->letter->name . $current_seat->code;
        $zone = Zone::select('name', 'door_id')->where('id', $current_seat->zone_id)->first();

        $door_name = null;
        if ($zone && $zone->door_id) {
            $c_q = Door::select('name')->where('id', $zone->door_id)->first();
            if ($c_q) {
                $door_name = $c_q->name;
            }
        }

        $userTicket = Ticket::with("match_event:id,season_id")->select("id", "user_id", "match_event_id", "seat_id", "ticket_type_id")->where('id', $ticket)->first();

        $pendingTickets = array();
        // Abonados
        if ($userTicket->ticket_type_id == 2) {
            $pendingTickets = Ticket::select("id", "code_ticket", "seat_id", "match_event_id", "door", "zone", "letter_seat", "code_seat")->with("match_event:id,event_start,date_name,name")
                ->whereHas('match_event', function ($match_event) use ($userTicket) {
                    $match_event->where('event_start', '>=', Carbon::now());
                    $match_event->where('season_id', $userTicket->match_event->season_id);
                })
                ->where('seat_id', $userTicket->seat_id)
                ->where('user_id', $userTicket->user_id)
                ->where('ticket_type_id', 2)
                ->get();
        } else if ($userTicket->ticket_type_id == 1) {
            $pendingTickets = Ticket::select("id", "code_ticket", "seat_id", "match_event_id", "door", "zone", "letter_seat", "code_seat")
                ->where('id', $userTicket->id)
                ->get();
        }

        if (count($pendingTickets) === 0) {
            $pendingTickets[] = $userTicket;
        }

        try {
            foreach ($pendingTickets as $p) {
                $ticket_current = $this->existsTicket($freeSeat, $p->match_event_id, $userTicket->user_id);
                $ticket_block = $this->existsBlock($freeSeat, $p->match_event_id, $userTicket->user_id);

                if ($ticket_current) {
                    return array("r" => false, "m" => __('messages.error_validation_3', ['seat' => $name_seat]));
                }

                if ($ticket_block) {
                    return array("r" => false, "m" => __('messages.error_validation_4', ['seat' => $name_seat]));
                }

                // Buscar ticket y actualizar.
                $ticketToChange = Ticket::find($p->id);

                $ticketToChange->seat_id = $freeSeat;
                $ticketToChange->zone = $zone->name;
                $ticketToChange->letter_seat = $current_seat->letter->name;
                $ticketToChange->code_seat = $current_seat->code;
                $ticketToChange->door = $door_name;
                if ($specialTicket != null)
                    $ticketToChange->special_text = $specialTicket;

                $ticketToChange->update();
            }
        } catch (\Exception $exx) {
            return array('r' => false, 'm' => $exx->getMessage());
        }

        return array('r' => true, 'm' => 'Proceso exitoso');
    }

    public function parameterViewTicket()
    {
        $parameters = $this->ticketParametersService->getParameterObject();
        return view('tickets.parameters', compact('parameters'));
    }

    public function saveParameters(Request $request)
    {
        return $this->ticketParametersService->saveParameters($request);
    }

    public function tableFilterTicketUserLogs($events = null, $from_date = null, $to_date = null)
    {
        DB::statement("SET sql_mode = ''");
        $obj = $obj = DB::table('ticket_user_logs')
            ->select(
                'ticket_user_logs.id',
                'ticket_user_logs.ticket_id',
                'ticket_user_logs.previous_user_id AS previousUser',
                'ticket_user_logs.new_user_id AS newUser',
                'ticket_user_logs.payment_reference',
                'ticket_user_logs.number_transfers',
                'tickets.code_ticket AS codeTicket',
                'previous_user.email AS previousUserEmail',
                'new_user.email AS newUserEmail',
                DB::raw('CONCAT(match_events.name, " - ",DATE_FORMAT(match_events.event_start, "%Y-%m-%d %h:%i %p")) AS event_'),
                DB::raw('DATE_FORMAT(ticket_user_logs.created_at, "%Y-%m-%d %h:%i %p") AS date_')
            )
            ->leftjoin('tickets', 'tickets.id', '=', 'ticket_user_logs.ticket_id')
            ->leftjoin('users AS previous_user', 'previous_user.id', '=', 'ticket_user_logs.previous_user_id')
            ->leftjoin('users AS new_user', 'new_user.id', '=', 'ticket_user_logs.new_user_id')
            ->leftjoin('match_events', 'match_events.code', '=', 'tickets.code_event');
        if ($events && $events != 'null') {
            $obj->whereIn('match_events.id', explode(',', $events));
        }
        if ($from_date && $from_date != 'null') {
            $obj->whereDate('ticket_user_logs.created_at', '>=', $from_date);
        }
        if ($to_date && $to_date != 'null') {
            $obj->whereDate('ticket_user_logs.created_at', '<=', $to_date);
        }
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");

        return DataTables::of($obj)
            ->addColumn('actions', function ($obj) {
                return '
                    <i class="fa fa-pencil iconMini" onClick="clickEdit(' . $obj->id . ')" data-id="' . $obj->id . '" data-toggle="tooltip" data-placement="bottom"  style="cursor:pointer;"></i>
                    <i class="fa fa-trash iconMini" onClick="clickDelete(' . $obj->id . ')" data-id="' . $obj->id . '" data-toggle="tooltip" data-placement="bottom"  style="cursor:pointer;"></i>
                ';
            })
            ->rawColumns(['actions'])
            ->make(true);
    }

    public function listTicketUserLogs()
    {
        $events = MatchEvent::select('id', 'name', DB::raw('DATE_FORMAT(event_start, "%Y-%m-%d %h:%i %p") as event_start'))
            ->orderBy('name', 'ASC')
            ->get();

        return view('tickets.listTicketUserLog')->with('events', $events);
    }


    public function createTicketsMatchByQuery($matchEventReferenceId, $type = 2, $matchEventCopyId)
    {
        $query = 'SELECT * FROM `tickets` WHERE `match_event_id` = ' . $matchEventReferenceId . ' AND `ticket_type_id` = ' . $type . ';';
        $matchEventId = $matchEventCopyId;
        try {
            if (in_array(Auth::user()->rol->id, [$this->__SUPERADMIN_ROL])) {
                DB::statement("SET sql_mode = ''");
                $tickets = DB::select($query);
                $response = [];
                foreach ($tickets as $ticket) {
                    $response[] = $this->createTicket($ticket->seat_id, $matchEventId, $ticket->user_id, $ticket->ticket_type_id, $ticket->ticket_main_id, $ticket->price);
                }
                DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
                return 'Proceso ejecutado exitosamente: Total boletas generadas => ' . count($response);
            }
            return 'Proceso no ejecutado por permisos';
        } catch (\Throwable $th) {
            return $th->getMessage();
        }
    }

    public function generateTicketsByReferenceOrTicketMain($reference = null, $ticketMainId = null)
    {
        if (in_array(Auth::user()->rol->id, [$this->__SUPERADMIN_ROL])) {
            if ($reference)
                $ticketMain = TicketMain::where('payment_reference', $reference)
                    ->with(['ticket_user_block_backups' => function ($q) {
                        $q->where('ticket_user_block_backups.is_social_distancing', false);
                    }])
                    ->first();
            if ($ticketMainId)
                $ticketMain = TicketMain::where('id', $ticketMainId)
                    ->with(['ticket_user_block_backups' => function ($q) {
                        $q->where('ticket_user_block_backups.is_social_distancing', false);
                    }])
                    ->first();
            if ($ticketMain && !$ticketMain->ticket_user_block_backups->isEmpty()) {
                $statusGenerateTickets = $this->generateTickets($ticketMain->ticket_user_block_backups, $ticketMain->id, true);
                $response = json_decode($statusGenerateTickets->getContent());
                if ($response->r) {
                    $ticketMain->payment_state = "CONFIRMED";
                    $ticketMain->payment_comment = 'APPROVED';
                    $ticketMain->update();
                    return array('r' => true, 'm' => 'Proceso ejecutado exitosamente: ' . json_encode($response));
                }
                return array('r' => false, 'm' => 'Proceso no ejecutado, debido a: ' . json_encode($response));
            }
            return array('r' => false, 'm' => 'Proceso no ejecutado, debido a que no tiene tickets');
        }
        return array('r' => false, 'm' => 'Proceso no ejecutado por permisos');
    }

    public function getDetailNameZonesEvent($eventIdOrCode)
    {
        $query = 'SELECT CONCAT(z1.name, IF(t.special_text IS NOT NULL,CONCAT("_",t.special_text),"")) AS tags, COUNT(*) AS total
                FROM tickets t
                JOIN seats s ON s.id = t.seat_id
                JOIN zones z ON z.id = s.zone_id
                JOIN zones z1 ON z1.id = z.zone_id
                WHERE t.ticket_status_id = 1 AND t.code_event = "' . $eventIdOrCode . '"
                GROUP BY tags
                ORDER BY total ASC';
        DB::statement("SET sql_mode = ''");
        $data = DB::select($query);
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
        $table = '<table>
        <tr>
          <th>Tribuna</th>
          <th></th>
          <th>Boletas</th>
        </tr>';
        $totalTickets = 0;
        foreach ($data as $item) {
            $table .= '<tr>' .
                '<td>' . $item->tags . '</td>' .
                '<td>' . '</td>' .
                '<td>' . $item->total . '</td>' .
                '</tr>';
            $totalTickets += $item->total;
        }
        $table .= '<tr>
                        <th>Total</th>
                        <th></th>
                        <th>' . $totalTickets . '</th>
                    </tr>';
        $table .= '</table>';
        return $table;
    }

    public function getEventCapacity($eventIdOrCode)
    {
        $query = 'SELECT zz.name AS tribune, z.name AS sector, z.salable_capacity AS capacity, COUNT(t.id) AS sold, (z.salable_capacity - COUNT(t.id)) AS available
                FROM tickets t
                JOIN seats s ON s.id = t.seat_id
                JOIN zones z ON z.id = s.zone_id
                JOIN zones zz ON zz.id = z.zone_id
                WHERE t.ticket_status_id = 1 AND t.code_event = "' . $eventIdOrCode . '" OR t.match_event_id = "' . $eventIdOrCode . '"
                GROUP BY sector
                ORDER BY sector ASC, tribune ASC';
        DB::statement("SET sql_mode = ''");
        $data = DB::select($query);
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
        $table = '<table>
        <tr>
            <th>Tribuna</th>
            <th>Sector</th>
            <th>Capacidad</th>
            <th>Boletas vendidas</th>
            <th>Boletas disponibles</th>
        </tr>';
        $totalCapacity = 0;
        $totalSold = 0;
        $totalAvailable = 0;
        foreach ($data as $item) {
            $table .= '<tr>' .
                '<td>' . $item->tribune . '</td>' .
                '<td>' . $item->sector . '</td>' .
                '<td>' . $item->capacity . '</td>' .
                '<td>' . $item->sold . '</td>' .
                '<td>' . $item->available . '</td>' .
                '</tr>';
            $totalCapacity += $item->capacity;
            $totalSold += $item->sold;
            $totalAvailable += $item->available;
        }
        $table .= '<tr>
                        <th>Total</th>
                        <th></th>
                        <th>' . $totalCapacity . '</th>
                        <th>' . $totalSold . '</th>
                        <th>' . $totalAvailable . '</th>
                    </tr>';
        $table .= '</table>';
        return $table;
    }

    public function validateExport(Request $request)
    {
        if ($request['query']) {
            $results = $this->util->getGenericData($request["query"], $request["bindings"]);
            if (count($results) > 0) {
                $name = 'ReporteRepositorioDocumental' . time() . '.xlsx';
                Excel::store(new ListTickeLogsExport($results), $name, 'public');
                return response()->json(['success' => true, 'message' => 'Validación OK', 'data' => $name]);
            }
        }

        return response()->json(['success' => false, 'message' => 'No existen datos a exportar']);
    }

    public function export($name)
    {
        return $this->util->export($name);
    }
}