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/demo.sports-crowd.com/app/Http/Controllers/FlashTicketController.php
<?php

namespace App\Http\Controllers;

use App\Core\CorporateIdentity\Application\CorporateIdentityService;
use App\Core\Payment\PaymentStatusEnum;
use App\Core\Ticket\Application\TicketService;
use App\Core\Ticket\TicketOriginEnum;
use App\Core\Ticket\TicketStatusEnum;
use App\Core\Ticket\TicketTypesEnum;
use App\Tag;
use App\Team;
use App\Term;
use App\Zone;
use App\Ticket;
use DataTables;
use App\Parameter;
use App\TicketTag;
use App\MatchEvent;
use App\TicketMain;
use App\TicketType;
use App\CorporateIdentity;
use App\DataPolicy;
use Illuminate\Http\Request;
use App\Services\ZonesService;
use App\FlashTicketConfiguration;
use Illuminate\Support\Facades\DB;
use App\FlashTicketConfigurationTag;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\Api\FlashTicketApiController;
use App\Services\WhatsAppService;
use App\TicketParameter;
use Carbon\Carbon;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;

class FlashTicketController extends Controller
{
    private $util;
    private $types = [];
    private $typesAplicationCupon = [];
    private $whatsappService;
    private $ticketService;

    public function __construct()
    {
        $this->util = new UtilController();
        $this->whatsappService = new WhatsAppService();
        $this->ticketService = new TicketService();

        $this->types[] = (object) [
            'name' => 'Todos',
            'value' => 'all'
        ];
        $this->types[] = (object) [
            'name' => 'Web',
            'value' => 'web'
        ];
        $this->types[] = (object) [
            'name' => 'App',
            'value' => 'app'
        ];

        $this->typesAplicationCupon[] = (object) [
            'name' => 'Ninguno',
            'value' => 'none'
        ];
        $this->typesAplicationCupon[] = (object) [
            'name' => 'Precio especial',
            'value' => 'special_price'
        ];
        $this->typesAplicationCupon[] = (object) [
            'name' => 'Ver tribuna',
            'value' => 'tribune'
        ];
    }

    public function index()
    {
        $parameters = Parameter::first();
        $typesAplicationCupon = $this->typesAplicationCupon;

        $corporateIdentity = CorporateIdentityService::get();
        return view('flash_ticket.list', compact('parameters', 'typesAplicationCupon', 'corporateIdentity'));
    }

    public function selling()
    {
        $parameters = Parameter::first();
        $events = MatchEvent::select('match_events.name', 'match_events.event_start', 'flash_ticket_configuration.*', 'zones.name AS zone')
            ->join('flash_ticket_configuration', 'match_events.id', '=', 'flash_ticket_configuration.match_event_id')
            ->leftjoin('zones', 'flash_ticket_configuration.zone_id', '=', 'zones.id')
            ->where([['match_events.active', true], ['flash_ticket_configuration.active', true]])
            ->whereIn('flash_ticket_configuration.show_in', ['all', 'web'])
            ->whereNull('flash_ticket_configuration.deleted_at')
            ->get();

        $ticketTags = TicketTag::select('id', 'name')->where('active', true)->get();

        if ($this->validateRolePermissions('ticketing', 'seller'))
            $types = TicketType::select('id', 'name')->where('active', true)->where('id', TicketTypesEnum::FREE_SALE)->get();
        else
            $types = TicketType::select('id', 'name')->where('active', true)->get();

        $controller = new ServiceChargeController();
        if ($controller->validateServiceCharge()) {
            foreach ($events as $event) {
                $serviceCharge = 0;
                $zone = Zone::find($event->zone_id);
                $requestServiceCharge = new Request([
                    'services'      => 'ticket',
                    'match_events'  => $event->match_event_id,
                    'zones'         => $zone ? [$zone->id, $zone->zone_id] : [],
                    'ticket_types'  => TicketTypesEnum::FREE_SALE
                ]);
                $serviceCharge = $controller->calculateServiceCharge($requestServiceCharge);
                $event->service_charge = $serviceCharge;
            }
        }

        $corporateIdentity = CorporateIdentityService::get();
        return view('flash_ticket.selling', compact('events', 'types', 'parameters', 'ticketTags', 'corporateIdentity'));
    }

    public function webBuying()
    {
        $corporateIdentity = CorporateIdentity::first();
        $parameters = Parameter::select('web_presuscription')->first();
        if (!$parameters->web_presuscription) {
            return view('web_ticketing.notAvailable', compact('corporateIdentity'));
        }
        $events = MatchEvent::select(
            'match_events.id',
            'match_events.name',
            'match_events.code',
            'match_events.event_start',
            'match_events.stadium_to_play',
            'match_events.date_name',
            'teams.name AS team_name',
            'teams.logo AS team_logo',
            'seasons.name AS season_name',
            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')
        )
            ->join('teams', 'teams.id', '=', 'match_events.team_id')
            ->join('seasons', function ($join) {
                $join->on('seasons.id', '=', 'match_events.season_id')->where('seasons.active', 1);
            })
            ->leftjoin('match_event_zone_prices', 'match_event_zone_prices.match_event_id', '=', 'match_events.id')
            ->leftJoin('match_event_tags', 'match_event_tags.match_event_id', '=', 'match_events.id')
            ->leftJoin('tags', function ($join) {
                $join->on('tags.id', '=', 'match_event_tags.tag_id')
                    ->where('tags.active', 1);
            })
            ->where(function ($q) {
                $q->whereNull('match_event_tags.id')
                    ->orWhereNull('tags.id');
            })
            ->where('match_events.active', 1)
            ->where('match_events.event_start_sale', '<=', Carbon::now())
            ->where('match_events.event_end_sale', '>=', Carbon::now())
            ->groupBy('match_events.id')
            ->get();

        $col    = (count($events) ? (12 / count($events)) : 12);
        $team   = Team::select('name', 'logo')->where('is_main', 1)->first();
        $ticketParameters = TicketParameter::where('key', 'sections')->first();
        $backgroundByDefault = TicketParameter::where('key', 'backgroundByDefault')->first();
        $defaultBackgroundImage = null;
        if ($backgroundByDefault->value ?? false) {
            $defaultBackgroundImage = TicketParameter::where('key', 'web_ticketing_background')->first();;
        }
        $sections = json_decode($ticketParameters ? $ticketParameters->value : '', false);
        return view('web_ticketing.buying', compact('events', 'col', 'team', 'corporateIdentity', 'sections', 'backgroundByDefault', 'defaultBackgroundImage'));
    }

    public function ticketSelect($eventCode)
    {
        $corporateIdentity  = CorporateIdentity::first();
        $parameters         = Parameter::select('web_presuscription')->first();
        $matchEvent         = MatchEvent::where('code', $eventCode)->first();
        if (!$parameters->web_presuscription) {
            return view('web_ticketing.notAvailable', compact('corporateIdentity'));
        } else if (!$this->validateEvent($matchEvent)) {
            $message = "Evento no disponible para la venta o no posee precios disponibles para mostrar.";
            return view('web_ticketing.notAvailable', compact('corporateIdentity', 'message'));
        }

        $stadium = null;
        $matchEventIdAuxi = null;
        $validateCouponexits = false;
        $events = [];
        $salesType = $matchEvent->sales_type;
        if ($salesType == 'aleatoria') {
            $matchEventIdAuxi = $matchEvent->id;
            $validateCouponexits = FlashTicketConfiguration::select('id')
                ->where('active', 1)
                ->where('match_event_id', $matchEvent->id)
                ->whereIn('show_in', ['all', 'app'])
                ->where('apply_coupon_type', '!=', 'none')
                ->where('coupon', '!=', null)
                ->count() > 0;
            $events = MatchEvent::select(
                'match_events.id AS event_id',
                'match_events.name',
                'match_events.sales_type',
                'match_events.event_start',
                'match_events.stadium_to_play',
                'match_events.date_name',
                'match_events.note',
                'teams.name AS team_name',
                'teams.logo AS team_logo',
                'seasons.name AS season_name',
                'seasons.id AS season_id',
                'flash_ticket_configuration.*',
                'zones.name AS zone',
            )
                ->join('teams', 'teams.id', '=', 'match_events.team_id')
                ->join('seasons', function ($join) {
                    $join->on('seasons.id', '=', 'match_events.season_id')->where('seasons.active', 1);
                })
                ->join('flash_ticket_configuration', 'match_events.id', '=', 'flash_ticket_configuration.match_event_id')
                ->join('zones', 'flash_ticket_configuration.zone_id', '=', 'zones.id')
                ->where('match_events.id', $matchEvent->id)
                ->where('flash_ticket_configuration.active', 1)
                ->where('flash_ticket_configuration.apply_coupon_type', '!=', 'tribune')
                ->whereIn('flash_ticket_configuration.show_in', ['all', 'web'])
                ->get();
        } else if ($salesType == 'seleccionada') {
            $zonesService = new ZonesService;
            $stadium = $zonesService->getMatchStadiumMap($matchEvent->id);
            $events = MatchEvent::select(
                'match_events.id AS event_id',
                'match_events.name',
                'match_events.sales_type',
                'match_events.event_start',
                'match_events.stadium_to_play',
                'match_events.date_name',
                'match_events.note',
                'teams.name AS team_name',
                'teams.logo AS team_logo',
                'seasons.name AS season_name',
                'seasons.id AS season_id'
            )
                ->join('teams', 'teams.id', '=', 'match_events.team_id')
                ->join('seasons', function ($join) {
                    $join->on('seasons.id', '=', 'match_events.season_id')->where('seasons.active', 1);
                })
                ->where('match_events.id', $matchEvent->id)
                ->get();
        }

        $controller = new ServiceChargeController();
        if ($controller->validateServiceCharge()) {
            foreach ($events as $event) {
                $serviceCharge = 0;
                $zone = Zone::find($event->zone_id);
                $requestServiceCharge = new Request([
                    'services'      => 'ticket',
                    'match_events'  => $event->event_id,
                    'zones'         => $zone ? [$zone->id, $zone->zone_id] : [],
                    'ticket_types'  => TicketTypesEnum::FREE_SALE
                ]);
                $serviceCharge = $controller->calculateServiceCharge($requestServiceCharge);
                $event->service_charge = $serviceCharge;
            }
        }

        $matchEventsController = new MatchEventsController;
        $view = $matchEventsController->getSaleView($salesType);
        $team = Team::select('name', 'logo')->where('is_main', 1)->first();
        $terms = Term::select('url')->where('active', true)->where('type', 'app')->first();
        $ticketParams = TicketParameter::where('key', 'terms')->first();
        if ($ticketParams) {
            $terms->url = $ticketParams->value;
        }
        $dataPolicy = DataPolicy::select('url')->where('active', true)->first();

        return view($view, compact(
            'events',
            'team',
            'corporateIdentity',
            'stadium',
            'matchEventIdAuxi',
            'validateCouponexits',
            'terms',
            'dataPolicy'
        ));
    }

    public function tableFilter()
    {
        DB::statement("SET sql_mode = ''");
        $obj = $obj = FlashTicketConfiguration::select(
            'flash_ticket_configuration.id',
            'flash_ticket_configuration.price',
            'flash_ticket_configuration.web_price',
            'flash_ticket_configuration.special_price',
            'flash_ticket_configuration.courtesy_price',
            'flash_ticket_configuration.salable_capacity',
            'flash_ticket_configuration.maximum_number_ballots',
            'flash_ticket_configuration.maximum_user_ticket_sales_box_office',
            'flash_ticket_configuration.image',
            'flash_ticket_configuration.coupon',
            'flash_ticket_configuration.apply_coupon_type',
            'flash_ticket_configuration.description',
            'flash_ticket_configuration.created_at',
            'flash_ticket_configuration.active',
            'zone_id',
            'match_event_id',
            'flash_ticket_configuration.show_in',
            'flash_ticket_configuration.show_image',
            DB::raw('GROUP_CONCAT(DISTINCT(tags.name)) AS segmentation')
        )
            ->with('zone', 'match_event')
            ->leftjoin('flash_ticket_configuration_tags', 'flash_ticket_configuration_tags.flash_ticket_id', '=', 'flash_ticket_configuration.id')
            ->leftjoin('tags', function ($join) {
                $join->on('tags.id', '=', 'flash_ticket_configuration_tags.tag_id')->where('tags.active', 1);
            })
            ->groupBy('flash_ticket_configuration.id');
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");

        return DataTables::of($obj)
            ->addColumn('actions', function ($obj) {
                $edit = '<i class="fa fa-pencil iconMini" onClick="clickEdit(' . $obj->id . ')" data-id="' . $obj->id . '" title="Editar"></i>';
                $delete = '<i class="fa fa-trash iconMini" onClick="clickDelete(' . $obj->id . ')" data-id="' . $obj->id . '" title="Eliminar"></i>';

                if ($this->validateRolePermissions('ticketing', 'administrator') || $this->validateRolePermissions('ticketing', 'supervisor'))
                    return $edit . $delete;
                else
                    return '';
            })
            ->editColumn('active', function ($obj) {
                if ($this->validateRolePermissions('ticketing', 'administrator') || $this->validateRolePermissions('ticketing', 'supervisor'))
                    if ($obj->active == 0) {
                        return '<div class="switch"><label><div class="checkbox checbox-switch switch-success"> <label> ' . __('messages.no') . ' <input type="checkbox" onChange="chk(' . $obj->id . ')" data-id="' . $obj->id . '" id="Checkactive' . $obj->id . '" name="Checkactivo" /> <span></span>' . __('messages.yes') . ' </label></div> </label> </div>';
                    } else {
                        return '<div class="switch"><label> <div class="checkbox checbox-switch switch-success"> <label>   ' . __('messages.no') . ' <input type="checkbox" onChange="chk(' . $obj->id . ')" data-id="' . $obj->id . '" id="Checkactive' . $obj->id . '" name="Checkactivo" checked="" />
                        <span></span> ' . __('messages.yes') . ' </label> </div>  </label> </div>';
                    }
                else
                    return $obj->active ? 'SI' : 'NO';
            })
            ->editColumn('image', function ($obj) {
                if (!$obj->image) {
                    return $this->util->generateEmptyImageColumn();
                } else {
                    return $this->util->generateImageColumnRound($obj->image, $obj->zone->name ?? 'Imagen', 'flash_configuration' . $obj->id);
                }
            })
            ->editColumn('show_image', function ($obj) {
                return $obj->show_image ? 'SI' : 'NO';
            })
            ->editColumn('show_in', function ($obj) {
                if ($obj->show_in) {
                    $object = collect($this->types)->where('value', $obj->show_in)->first();
                    if ($object)
                        return $object->name;
                }
                return '';
            })
            ->editColumn('created_at', function ($obj) {
                return Carbon::parse($obj->created_at)->format('Y-m-d h:i:s A');
            })
            ->rawColumns(['active', 'actions', 'image'])
            ->make(true);
    }

    public function add()
    {
        $stadiumsZone       = Zone::where('active', 1)->whereNull('zone_id')->pluck('id');
        DB::statement("SET sql_mode = ''");
        $tribunes           = Zone::select('zones.id', 'zones.name', 'zones.salable_capacity', 'stadiums.name as stadium')
            ->join('zones AS stadiums', 'stadiums.id', '=', 'zones.zone_id')
            ->whereIn('zones.zone_id', $stadiumsZone)
            ->where('zones.active', 1)
            ->groupBy('zones.id')
            ->orderBy('zones.salable_capacity', 'DESC')
            ->orderBy('zones.name', 'ASC')
            ->get();
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
        $matchEvents        = MatchEvent::select('id', 'name')->where('active', true)->get();
        $multiselectItems   = Tag::select('id', 'name')->where('active', true)->get();
        $types              = $this->types;
        $typesAplicationCupon = $this->typesAplicationCupon;
        return view('flash_ticket.create', compact('tribunes', 'matchEvents', 'multiselectItems', 'types', 'typesAplicationCupon'));
    }

    public function create(Request $request)
    {
        $tags = $request["tags"];
        $request->request->remove('tags');
        $flash = FlashTicketConfiguration::where([['match_event_id', $request->all()['match_event_id']], ['zone_id', $request->all()['zone_id']]])->first();
        if ($flash) {
            $this->setSegmentation($tags, $flash->id);
            $this->registerLog(Auth::user()->id, 'Crear configuración venta boleteria', json_encode($request->all()), "Create", $this->getModule($request));
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.already_exists_stage'), "data" => null));
        } else {
            if ($team = FlashTicketConfiguration::create(array_merge($request->all()))) {
                $this->setSegmentation($tags, $team->id);
                $this->registerLog(Auth::user()->id, 'Crear configuración venta boleteria', json_encode($request->all()), "Create", $this->getModule($request));
                return response(array("r" => true, "type" => "success", "title" => "", "m" => __('messages.created_successfully'), "data" => $team->id));
            } else {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_creating'), "data" => null));
            }
        }
    }

    public function edit($id)
    {
        $event              = FlashTicketConfiguration::findOrFail($id);
        $stadiumsZone       = Zone::where('active', 1)->whereNull('zone_id')->pluck('id');
        DB::statement("SET sql_mode = ''");
        $tribunes           = Zone::select('zones.id', 'zones.name', 'zones.salable_capacity', 'stadiums.name as stadium')
            ->join('zones AS stadiums', 'stadiums.id', '=', 'zones.zone_id')
            ->whereIn('zones.zone_id', $stadiumsZone)
            ->where('zones.active', 1)
            ->groupBy('zones.id')
            ->orderBy('zones.salable_capacity', 'DESC')
            ->orderBy('zones.name', 'ASC')
            ->get();
        DB::statement("SET sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'");
        $matchEvents        = MatchEvent::select('id', 'name')->where('active', 1)->get();
        $multiselectItems   = Tag::select('id', 'name')->where('active', 1)->get();
        $multiselectValues  = FlashTicketConfigurationTag::select('tag_id')
            ->where('flash_ticket_id', $id)
            ->pluck('tag_id')
            ->toArray();
        $types              = $this->types;
        $typesAplicationCupon = $this->typesAplicationCupon;
        return view('flash_ticket.edit', compact('event', 'tribunes', 'matchEvents', 'multiselectItems', 'multiselectValues', 'types', 'typesAplicationCupon'));
    }

    public function update(Request $request, $id)
    {
        $tags = $request["tags"];
        $request->request->remove('tags');
        $flash = FlashTicketConfiguration::where([['match_event_id', $request->all()['match_event_id']], ['zone_id', $request->all()['zone_id']]])->first();
        if ($flash && $flash->id !== intval($id)) {
            $this->setSegmentation($tags, $id);
            $this->registerLog(Auth::user()->id, 'Editar configuración venta boleteria', json_encode($request->all()), "Update", $this->getModule($request));
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.already_exists_stage'), "data" => null));
        } else {
            if (FlashTicketConfiguration::where('id', $id)->update(array_slice($request->all(), 1))) {
                $this->setSegmentation($tags, $id);
                $this->registerLog(Auth::user()->id, 'Editar configuración venta boleteria', json_encode($request->all()), "Update", $this->getModule($request));
                return response(array("r" => true, "type" => "success", "title" => "", "m" => __('messages.updated_successfully'), "data" => null));
            } else {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_updating'), "data" => null));
            }
        }
    }

    private function setSegmentation($tags, $id)
    {
        FlashTicketConfigurationTag::where('flash_ticket_id', $id)->delete();
        if ($tags != null) {
            foreach ($tags as $tagId) {
                FlashTicketConfigurationTag::create([
                    'tag_id' => $tagId,
                    'flash_ticket_id' => $id
                ]);
            }
        }
    }

    public function destroy(Request $request, $id)
    {
        try {
            $configuration = FlashTicketConfiguration::find($id);
            if (FlashTicketConfiguration::where('id', $id)->delete()) {
                $this->registerLog(Auth::user()->id, 'Eliminar configuración venta boleteria', json_encode($configuration), "Delete", $this->getModule($request));
                return response(array("r" => true, "type" => "success", "title" => "", "m" => __('messages.deleted_successfully'), "data" => null));
            } else {
                return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_removing'), "data" => null));
            }
        } catch (\Illuminate\Database\QueryException $e) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.delete_relation_data'), "data" => null));
        }
    }

    public function activate(Request $request)
    {
        try {
            $id = $request['id'];
            $state = $request['state'];

            $configuration = FlashTicketConfiguration::find($id);
            $configuration->active = $state;
            $configuration->update();

            $this->registerLog(Auth::user()->id, 'Activar/Desactivar configuración venta boleteria', json_encode($configuration), "Update", $this->getModule($request));
            return array('r' => true, 'd' => null, 'm' => __('messages.updated_successfully'));
        } catch (\Throwable $th) {
            return array('r' => false, 'd' => null, 'm' => __('messages.error_updating'));
        }
    }

    public function buy(Request $request)
    {
        $flash_ticket_configuration = FlashTicketConfiguration::where('id', $request['flash_ticket_configuration_id'])->with('zone')->first();
        $web_amount = $request['web_amount'];
        $special_amount = $request['special_amount'];
        $courtesy_amount = $request['courtesy_amount'];
        $quantity = $web_amount + $special_amount + $courtesy_amount;

        $flashTicketApiController = new FlashTicketApiController;
        $flash_ticket_configuration->quantity = $quantity;
        $parentZone = [$flash_ticket_configuration];

        $requestValidateSeats = new Request();
        $requestValidateSeats->merge($parentZone);
        $zoneWithSeats = json_decode(
            $flashTicketApiController->validateSeatsAvailableByCapacity($requestValidateSeats)->content(),
            true
        );

        $seats = null;
        foreach ($zoneWithSeats as $zone) {
            if ($zone['seats'] && count($zone['seats']) >= $quantity) {
                $seats = $zone['seats'];
                break;
            }
        }

        if (!$seats) {
            return array('r' => false, 'd' => null, 'm' => 'No hay sufientes boletas disponibles');
        }

        $zoneId = $seats[0]['zone_id'];
        $massiveFansController = new MassiveFansController;

        $ticket_main = new TicketMain;
        $ticket_main->origin = TicketOriginEnum::WEB;
        $ticket_main->subtotal = $request->input('subtotal', 0);
        $ticket_main->service_charge = $request->input('service_charge', 0);
        $ticket_main->total = $request->input('total', 0);
        $ticket_main->payment_attempts = 0;
        $ticket_main->payment_state = PaymentStatusEnum::CONFIRMED;
        $ticket_main->seller_user_id = Auth::user()->id;
        $ticket_main->pin = $this->gen_uid();
        $ticket_main->save();

        $ticket_main->payment_reference = strtoupper(hash("md5", (string) $ticket_main->id)) . '_' . $ticket_main->pin;
        $ticket_main->update();

        $userController = new UserController();
        $userResponse = $userController->createClient(new Request([
            'first_name'    => 'Web',
            'last_name'     => 'Ticketing',
            'email'         => 'webticketing@gmail.com',
            'phone'         => '1234',
            'document'      => 0,
            'document_type' => '',
            'direction'     => 'WebTicketing'
        ]));

        $userId = $userResponse['d']->id;
        $matchEventId = $flash_ticket_configuration->match_event_id;
        $ticketCodes = [];

        if ($web_amount) {
            $result = $massiveFansController->generateRamdomTickets(
                [
                    'quantity' => $web_amount,
                    'user_id' => $userId,
                    'zone_id' => $zoneId,
                    'match_event_id' => $matchEventId,
                    'ticket_type_id' => TicketTypesEnum::FREE_SALE,
                    'price' => $flash_ticket_configuration->web_price,
                    'ticket_main_id' => $ticket_main->id,
                    'special_text' => null,
                    'send_email' => false,
                ]
            );
            if (isset($result['d']) && is_array($result['d'])) {
                $ticketCodes = array_merge($ticketCodes, $result['d']);
            } else {
                return array('r' => false, 'm' => $result['m'] . ' Origen: ' . $result['d']);
            }
        }

        if ($special_amount) {
            $result = $massiveFansController->generateRamdomTickets(
                [
                    'quantity' => $special_amount,
                    'user_id' => $userId,
                    'zone_id' => $zoneId,
                    'match_event_id' => $matchEventId,
                    'ticket_type_id' => TicketTypesEnum::FREE_SALE,
                    'price' => $flash_ticket_configuration->special_price,
                    'ticket_main_id' => $ticket_main->id,
                    'special_text' => $request['special_text'],
                    'send_email' => false,
                ]
            );
            if (isset($result['d']) && is_array($result['d'])) {
                $ticketCodes = array_merge($ticketCodes, $result['d']);
            } else {
                return array('r' => false, 'm' => $result['m'] . ' Origen: ' . $result['d']);
            }
        }

        if ($courtesy_amount) {
            $result = $massiveFansController->generateRamdomTickets(
                [
                    'quantity' => $courtesy_amount,
                    'user_id' => $userId,
                    'zone_id' => $zoneId,
                    'match_event_id' => $matchEventId,
                    'ticket_type_id' => TicketTypesEnum::FREE_SALE,
                    'price' => $flash_ticket_configuration->courtesy_price,
                    'ticket_main_id' => $ticket_main->id,
                    'special_text' => $request['courtesy_text'],
                    'send_email' => false,
                ]
            );
            if (isset($result['d']) && is_array($result['d'])) {
                $ticketCodes = array_merge($ticketCodes, $result['d']);
            } else {
                return array('r' => false, 'm' => $result['m'] . ' Origen: ' . $result['d']);
            }
        }
        return array('r' => true, 'd' => $ticketCodes, 'm' => __('messages.flash_ticket.tickets_generated'), 'ticket_main_id' => $ticket_main->id);
    }

    public function getSoldCount($eventId, $zoneId)
    {
        $tickets = Ticket::where('match_event_id', $eventId)
            ->join('seats', 'seats.id', '=', 'tickets.seat_id')
            ->join('zones', 'zones.id', '=', 'seats.zone_id')
            ->leftjoin('zones AS tribunes', 'tribunes.id', '=', 'zones.zone_id')
            ->where(function ($query) use ($zoneId) {
                $query->where('zones.id', $zoneId)->orWhere('tribunes.id', $zoneId);
            })
            ->whereIn('tickets.ticket_status_id', [TicketStatusEnum::PURCHASED, TicketStatusEnum::CREATED])
            ->count();
        return array('r' => true, 'd' => $tickets);
    }

    public function getMaximumTicketsToBuy($matchEventId, $show_in = 'app')
    {
        $data = FlashTicketConfiguration::select(DB::raw('SUM(maximum_number_ballots) AS maximum_number_ballots'))
            ->where([['active', 1], ['match_event_id', $matchEventId]])
            ->whereIn('show_in', ['all', $show_in])
            ->first();
        $parameters = Parameter::select('maximum_number_ballots')->first();
        $maximum = $data->maximum_number_ballots ?? $parameters->maximum_number_ballots;
        return $maximum;
    }

    public function saveImage(Request $request)
    {
        try {
            $extension = $request->file('image')->getClientOriginalExtension();
            $filenametostore = $request->id . '.' . $extension;
            Storage::disk('s3')->put(config('s3.default') . '/ticketing/flash/' . $filenametostore, fopen($request->file('image'), 'r+'), 'public');
            $url = config('filesystems.disks.s3.url') . '/ticketing/flash/' . $filenametostore;
            FlashTicketConfiguration::where('id', $request->id)->update(['image' => $url]);
            return response(array("r" => true, "type" => "success", "title" => "", "m" => __('messages.updated_successfully'), "data" => null));
        } catch (\Throwable $th) {
            return response(array("r" => false, "type" => "error", "title" => "Oops...", "m" => __('messages.error_updating'), "data" => $th->getMessage()));
        }
    }
    public function procesarCupon($cupon, $hasCoupon, $matchEventIdAuxi)
    {
        $matchEventId = $matchEventIdAuxi;
        $coupon = $cupon;

        $events = MatchEvent::select(
            'match_events.name',
            'match_events.event_start',
            'match_events.stadium_to_play',
            'match_events.event_start',
            'match_events.date_name',
            'flash_ticket_configuration.*',
            'zones.name AS zone',
            'seasons.name AS season_name',
            'seasons.id AS season_id',
            'teams.name AS team_name',
            'teams.logo AS team_logo'
        )
            ->join('flash_ticket_configuration', 'match_events.id', '=', 'flash_ticket_configuration.match_event_id')->where('flash_ticket_configuration.active', true)->whereIn('flash_ticket_configuration.show_in', ['all', 'web'])
            ->join('teams', 'teams.id', '=', 'match_events.team_id')
            ->leftjoin('seasons', function ($join) {
                $join->on('seasons.id', '=', 'match_events.season_id')->where('seasons.active', 1);
            })
            ->leftjoin('zones', 'flash_ticket_configuration.zone_id', '=', 'zones.id')
            ->where('match_events.id', $matchEventId)
            ->where('match_events.event_end_sale', '>=', Carbon::now())

            ->where([['flash_ticket_configuration.active', 1], ['flash_ticket_configuration.match_event_id', $matchEventId]])
            ->whereIn('flash_ticket_configuration.show_in', ['all', 'web'])
            ->Where('flash_ticket_configuration.coupon', $coupon)
            ->get();
        return $events;
    }

    public function sendByEmail(Request $request)
    {
        try {
            $request->validate(['email' => 'required|email', 'url' => 'required|url']);

            Mail::send('mails.listTickets', [
                'url' => $request->url
            ], function ($message) use ($request) {
                $message->from('noreply@sports-crowd.com', 'Sports Crowd');
                $message->to($request->email);
                $message->subject("Boletas");
            });

            $id = $request->has('ticket_main_id') ? (int) $request->input('ticket_main_id') : null;
            $this->ticketService->updateContactInformation($id, 'Correo: ' . $request->email);

            return response()->json([
                'r' => true,
                'd' => "",
                'm' => "Correo electrónico enviado"
            ]);
        } catch (\Throwable $e) {
            Log::error('sendByEmail error', ['message' => $e->getMessage()]);

            return response()->json([
                'r' => false,
                'd' => "",
                'm' => "No se pudo enviar el correo electrónico"
            ], 500);
        }
    }

    public function show()
    {
        $ticketParameters = TicketParameter::where('key', 'sections')->first();
        $backgroundByDefault = TicketParameter::where('key', 'backgroundByDefault')->first();
        return view('flash_ticket_builder.create', compact('ticketParameters', 'backgroundByDefault'));
    }

    public function builderSubmit(Request $request)
    {
        $sections  = json_decode($request->sections ?? '[]', true);
        if (count($request->files) > 0) {
            $dataFiles = json_decode($request->dataFiles, true);
            foreach ($dataFiles as $key => $fileData) {
                $selectedSecton = $fileData['section'];
                $selectedSetting = $fileData['setting'];
                $selectedName = $fileData['name'];
                $image = $request->file($selectedName);
                $namePublication = $selectedName;
                $compressedImg = null;
                if (!$compressedImg) {
                    $compressedImg = $image;
                }
                $compressedSize = filesize($compressedImg);

                $compressedSizeMB = number_format($compressedSize / 1048576, 2);
                if ($compressedSizeMB > 3) {
                    return response([
                        "r" => false,
                        "type" => "error",
                        "title" => "Oops...",
                        "m" => __('messages.photos_club.size_photos'),
                        "data" => null
                    ]);
                }

                $extension = $image->getClientOriginalExtension();
                $filenametostore = $selectedName . '.' . $extension;
                Storage::disk('s3')->put(config('s3.default') . '/web_ticketing/personalization/' . $namePublication . '/' . $filenametostore, fopen($compressedImg, 'r+'), 'public');
                $url = config('filesystems.disks.s3.url') . '/web_ticketing/personalization/' . $namePublication . '/' . $filenametostore . '?t=' . time();

                $sections[$selectedSecton]['settings'][$selectedSetting]['imageUrl'] = $url;
            }
        }
        if (json_last_error() !== JSON_ERROR_NONE) {
            return response()->json(['error' => 'Invalid JSON format'], 400);
        }
        $request->merge([
            'sections' => $sections,
            'backgroundByDefault' => $request->backgroundByDefault == 'true'
        ]);

        $this->createOrUpdateParam($request, 'sections');
        $this->createOrUpdateParam($request, 'backgroundByDefault');
        return response()->json(['message' => 'Parameters updated successfully']);
    }

    public function sendByWhatsApp(Request $request)
    {
        try {
            $request->validate([
                'phone' => 'required|string',
                'tickets' => 'required|string'
            ]);
            $data = [];

            $phone = $request->phone;
            $tickets = $request->tickets;

            $url = config('app.url') . '/download_ticket_for_user/' . Crypt::encryptString($tickets);
            // $url = $this->util->shorterUrl($url);

            $this->whatsappService->greeting($phone);

            try {
                $ticketsController = new TicketsController;
                $tickets = explode(',', $tickets);
                foreach ($tickets as $ticket) {
                    $filePath = $ticketsController->printTicket($ticket, "file");

                    $uploadResponse = $this->whatsappService->uploadFile($filePath);
                    if (!isset($uploadResponse['id'])) {
                        return response()->json([
                            'r' => false,
                            'd' => $uploadResponse,
                            'm' => 'No se pudo subir el archivo a WhatsApp'
                        ], 500);
                    }

                    $documentId = $uploadResponse['id'];
                    $data = $this->whatsappService->sendFile($phone, $documentId, basename($filePath));
                }
            } catch (\Throwable $e) {
                Log::error('sendByWhatsApp error', ['message' => $e->getMessage()]);
            }

            $this->whatsappService->farewell($phone, [$url]);

            $id = $request->has('ticket_main_id') ? (int) $request->input('ticket_main_id') : null;
            $this->ticketService->updateContactInformation($id, 'WhatsApp: ' . $phone);

            return response()->json([
                'r' => true,
                'd' => $data,
                'm' => "Boleta(s) enviada por WhatsApp correctamente, al $phone"
            ]);
        } catch (\Throwable $e) {
            Log::error('sendByWhatsApp error', ['message' => $e->getMessage()]);

            return response()->json([
                'r' => false,
                'd' => $e->getMessage(),
                'm' => "No se pudo enviar el mensaje por WhatsApp"
            ], 500);
        }
    }

    private function createOrUpdateParam(Request $request, $key)
    {
        if (!is_null($request[$key])) {
            TicketParameter::updateOrCreate(
                ['key' => $key],
                ['key' => $key, 'value' => json_encode($request[$key])]
            );
        }
    }

    private function validateEvent($matchEvent)
    {
        $now = Carbon::now()->format('Y-m-d H:i:s');
        if (!$matchEvent) {
            return false;
        } else if (!$matchEvent->active) {
            return false;
        } else if ($matchEvent->event_start_sale > $now) {
            return false;
        } else if ($matchEvent->event_end_sale < $now) {
            return false;
        }
        return true;
    }
}