<?php

namespace App\Http\Controllers\Eventmie;

use Classiebit\Eventmie\Http\Controllers\DownloadsController as BaseDownloadsController;
use Auth;
use Illuminate\Http\Request;
use App\Models\Booking;
use Classiebit\Eventmie\Scopes\BulkScope;
use App\Http\Controllers\InvoicesController;
use App\Models\User;
use App\Models\Event;
use ZipArchive;
use Illuminate\Support\Facades\Storage;
class DownloadsController extends BaseDownloadsController
{

    public function __construct()
    {
        parent::__construct();
        
        $this->booking = new Booking;
    }

    /**
     * Show my booking
     *
     * @return array
     */
    public function index($id = NULL, $order_number = NULL)
    {
        if(!empty(setting('booking.hide_ticket_download')) &&(Auth::user()->hasRole('organiser') || Auth::user()->hasRole('customer')))
            abort('404');
            
        $id             = (int) $id;
        $order_number   = trim($order_number);

        // get the booking
         
        //CUSTOM
        if(!Auth::user()->hasRole('admin'))
        {
        //CUSTOM
            $booking = $this->booking->get_event_bookings(['id'=>$id, 'order_number'=>$order_number]);

        //CUSTOM
        }
        else
        {
            $booking = Booking::with(['attendees' => function ($query) {
                $query->where(['status' => 1]);
            }, 'attendees.seat'])->withoutGlobalScope(BulkScope::class)->where(['id'=>$id])->get()->all();
        }
        
        //CUSTOM
        if(empty($booking))
            abort('404');

        $booking = $booking[0];

        // customer can see only their bookings
        if(Auth::user()->hasRole('customer'))
            if($booking['customer_id'] != Auth::id())
                abort('404');

        // organiser can see only their events bookings
        if(Auth::user()->hasRole('organiser'))
            if($booking['organiser_id'] != Auth::id())
                abort('404');
        
        // generate QrCode
        $qrcode_data = $booking['order_number'];
        $this->createQrcode($booking, $qrcode_data);

        // get event data for ticket pdf
        $event      = $this->event->get_event(null, $booking['event_id']);
        $currency   = setting('regional.currency_default');

        //CUSTOM
        if(!empty($event->currency)){
            $currency   = $event->currency;
        }  
        //CUSTOM
        
        // generate PDF
        // test PDF
        // $img_path = '';
        // return view('vendor.eventmie-pro.tickets.pdf', compact('booking', 'event', 'currency', 'img_path'));
        
        // use http url only
        $img_path   = str_replace('https://', 'http://', url(''));
        
        $pdf_html   = (string) \View::make('vendor.eventmie-pro.tickets.pdf', compact('booking', 'event', 'currency', 'img_path'));

        $pdf_name   = $booking['id'].'-'.$booking['order_number'];
        $this->generatePdf($pdf_html, $pdf_name, $booking);

        // // download PDF
        // Detect Storage Disk
        $storageDisk = getDisk();

        $relativePath = 'ticketpdfs/' . $booking['customer_id'] . '/' . $pdf_name . '.pdf';

        if ($storageDisk == 's3') {
            if (!Storage::disk('s3')->exists($relativePath)) {
                abort(404);
            }
            
            // Stream the file from S3 for download
            return response()->streamDownload(function () use ($relativePath) {
                echo Storage::disk('s3')->get($relativePath);
            }, basename($relativePath));

        } else {
            $pdf_file = public_path('/storage/' . $relativePath);

            if (!\File::exists($pdf_file)) {
                abort(404);
            }

            return response()->download($pdf_file);
        }
        
    }

    //CUSTOM
    public function getQrCode(Request $request)
    {
        $request->validate([
            'booking_id' => 'required|numeric|gt:0'
        ]);

        $id             = (int) $request->booking_id;
        
        // get the booking
        $booking = $this->booking->get_event_bookings(['id'=>$id]);
        if(empty($booking))
            abort('404');

        $booking = $booking[0];

        // customer can see only their bookings
        if(Auth::user()->hasRole('customer'))
            if($booking['customer_id'] != Auth::id())
                abort('404');

        // organiser can see only their events bookings
        if(Auth::user()->hasRole('organiser'))
            if($booking['organiser_id'] != Auth::id())
                abort('404');

        // Detect Storage Disk
        $storageDisk = getDisk(); // Assuming getDisk() is a helper function to determine the storage disk
        $qrcode_filename = $booking['id'] . '-' . $booking['order_number'] . '.png';
        $relativePath = 'qrcodes/' . $booking['customer_id'] . '/' . $qrcode_filename;

        // Check if QR code already exists
        if ($storageDisk == 's3') {
            if (Storage::disk('s3')->exists($relativePath)) {
                // Return the S3 URL for the QR code
                $qrcode_url = Storage::disk('s3')->url($relativePath);
                // Remove the S3 bucket URL prefix
                $qrcode_relative_path = str_replace(config('filesystems.disks.s3.url') ?? env('AWS_URL'), '', $qrcode_url);
                return response()->json(['qrcode_file' => $qrcode_relative_path, 'status' => true]);
            }
        } else {
            $qrcode_file = 'qrcodes/' . $booking['customer_id'] . '/' . $qrcode_filename;
            if (\File::exists(public_path($qrcode_file))) {
                return response()->json(['qrcode_file' => $qrcode_file, 'status' => true]);
            }
        }

        // Generate QR code if it doesn't exist
        $qrcode_data = $booking['order_number'];
        $this->createQrcode($booking, $qrcode_data);

        // Return the QR code path or URL based on storage disk
        if ($storageDisk == 's3') {
            $qrcode_url = Storage::disk('s3')->url($relativePath);
            return response()->json(['qrcode_file' => $qrcode_url, 'status' => true]);
        }

        return response()->json(['qrcode_file' => $qrcode_file, 'status' => true]);
    }

    /**
     * create zip for bulk bookings
     *
     * @return array
     */
    public function create_bulk_zip($ticket_id = NULL, $bulk_code = NULL)
    {
        if(! (Auth::user()->hasRole('admin') || Auth::user()->hasRole('organiser')))
            abort('404');
            
        $ticket_id      = $ticket_id;
        $bulk_code      = $bulk_code;

        $where = [
            'ticket_id' => $ticket_id,
            'bulk_code' => "$bulk_code",
        ];

        if(Auth::user()->hasRole('organiser'))
            $where['organiser_id'] = Auth::id();

        // get the booking
        $bookings = Booking::withoutGlobalScope(BulkScope::class)->where($where)->get()->all();
        
        if(empty($bookings))
            abort('404');

        $select = ['id', 'venue', 'address', 'thumbnail', 'title'];
        $event      = Event::select($select)->where('id', $bookings[0]['event_id'])->first();
        foreach($bookings as $key => $booking)
        {
            // generate QrCode
            $qrcode_data = $booking['order_number'];
            $this->bulk_createQrcode($booking, $qrcode_data);

            // get event data for ticket pdf
            $currency   = setting('regional.currency_default');

            //CUSTOM
            if(!empty($event->currency)){
                $currency   = $event->currency;
            } 
            // use http url only
            $img_path   = str_replace('https://', 'http://', url(''));
            
            // $pdf_html   = (string) \View::make('eventmie::tickets.pdf', compact('booking', 'event', 'currency', 'img_path'));
            $pdf_html   = (string) \View::make('vendor.eventmie-pro.tickets.pdf', compact('booking', 'event', 'currency', 'img_path'));

            $pdf_name   = $booking['id'].'-'.$booking['order_number'];

            $this->generatePdf($pdf_html, $pdf_name, $booking);
        }

        return $this->download_bulk_zip($bookings);
    }

    /**
     * bulk export_attendees 
     */

    public function bulk_export_attendees($ticket_id = null, $bulk_code = null)
    {
        // check event is valid or not
        if(! (Auth::user()->hasRole('admin') || Auth::user()->hasRole('organiser')))
            abort('404');
            
        $ticket_id      = (int) $ticket_id;
        $bulk_code      = (int)($bulk_code);

        $where = [
            'ticket_id' => $ticket_id,
            'bulk_code' => $bulk_code,
        ];

        if(Auth::user()->hasRole('organiser'))
            $where['organiser_id'] = Auth::id();

        // get the booking
        $bookings = Booking::withoutGlobalScope(BulkScope::class)->where($where)->get()->all();

        if(empty($bookings))
            return error_redirect('Booking Not Found!');

        // customize column values
        $bookings_csv = [];
        $bookings_custom = [];
        foreach($bookings as $key => $item)
        {
            $bookings_custom[$key]['ID']                   = $key+1;
            $bookings_custom[$key]['Order Number']         = "'".$item['order_number']."'";
            $bookings_custom[$key]['Event Title']          = $item['event_title'];
            $bookings_custom[$key]['Ticket Title']         = $item['ticket_title'];
            $bookings_custom[$key]['Distributor']  = $item['distributor_tag'];
            $bookings[$key]['A'] = json_encode($bookings_custom[$key]);
        }    

        // convert array to collection for csv
        $bookings = collect($bookings);
        $bookings_custom = collect($bookings_custom);

        // create object of laracsv
        $csvExporter = new \Laracsv\Export();

        
        // create csv 
        $csvExporter->build($bookings_custom, [
            //events fields which will be include
            'ID',
            'Order Number',
            'Event Title',
            'Ticket Title',
            'Distributor',
        ]);
        
        // download csv
        $csvExporter->download($bookings[0]['event_title'].'-'.$bookings[0]['ticket_id'].'-'.$bookings[0]['bulk_code'].'-attendies.csv');
    } 

    /**
     *  create qrcode for bulk booking
     */

    protected function bulk_createQrcode($data = [], $qrcode_data = [])
    {
        $path           = '/storage/qrcodes/'.$data['customer_id'];
        // first check if directory exists or not
        if (! \File::exists(public_path().$path))
            \File::makeDirectory(public_path().$path, 0755, true);
    
        $qrcode_file    = public_path().$path.'/'.$data['id'].'-'.$data['order_number'].'.png';
        
        // generate QrCode
        \QrCode::format('png')->size(256)->generate($qrcode_data, $qrcode_file);

        return TRUE;
    }

    /**
     *   download bulk zip
     */

    protected function download_bulk_zip($bookings = NULL)
    {
        // Define Dir Folder
        $public_dir  = public_path().'/storage/zip';

        // Zip File Name
        $zipFileName = $bookings[0]['event_title'].'-'.$bookings[0]['ticket_id'].'-'.$bookings[0]['bulk_code'].'.zip';
        
        // first check if directory exists or not
        if (! \File::exists($public_dir))
            \File::makeDirectory($public_dir, 0755, true);
        
        // Create ZipArchive Obj
        $zip = new ZipArchive;

        if($zip->open($public_dir.'/'.$zipFileName, ZipArchive::CREATE) === TRUE) 
        {
            foreach($bookings as $key => $data)
            {
                $path           = '/storage/ticketpdfs/'.$data['customer_id'];
                $pdf_file    = public_path().$path.'/'.$data['id'].'-'.$data['order_number'].'.pdf';
                
                $zip->addFile($pdf_file, $bookings[0]['bulk_code'].'/'.$data['id'].'-'.$data['order_number'].'.pdf');
                // Add File in ZipArchive
                
            }
    
            // Close ZipArchive     
            $zip->close();
        }
        
        // Set Header
        $headers = array(
            'Content-Type' => 'application/octet-stream',
        );


        $filetopath = $public_dir.'/'.$zipFileName;

        // Create Download Response
        if(file_exists($filetopath))
        {
            return response()->download($filetopath,$zipFileName,$headers);
        }
    }

    /**
     *  download inovoice
     */

    public function downloadInvoice(Booking $booking)
    {
        $common_order = $booking['common_order'];

        // if have no common_order then update
        if(empty($common_order))
            $booking->common_order = time().rand(1,988);

        $booking->save();

        $common_order = $booking->refresh()->common_order;

        
        
        // get the booking
         
        //CUSTOM
        if(!Auth::user()->hasRole('admin'))
        {
        //CUSTOM
            
            $bookings = Booking::with(['attendees' => function ($query) {
                $query->where(['status' => 1]);
            }, 'attendees.seat'])->where(['common_order' => $common_order])->get();
        
        //CUSTOM
        }
        else
        {
            
            $bookings = Booking::with(['attendees' => function ($query) {
                $query->where(['status' => 1]);
            }, 'attendees.seat'])->withoutGlobalScope(BulkScope::class)->where(['common_order' => $common_order])->get();
        }

    
        //CUSTOM
        if($bookings->isEmpty())
            abort('404');

        $booking = $bookings[0];

        // customer can see only their bookings
        if(Auth::user()->hasRole('customer'))
            if($booking['customer_id'] != Auth::id())
                abort('404');

        // organiser can see only their events bookings
        if(Auth::user()->hasRole('organiser'))
            if($booking['organiser_id'] != Auth::id())
                abort('404');
        
        $common_order = $booking['common_order'];
                
        $file = public_path('/storage/invoices/'.$booking['customer_id'].'/'.$booking['common_order'].'-invoice.pdf');
        
        if(!\File::exists($file)) 
        {
            $img_path      = str_replace('https://', 'http://', url(''));

            $organizer     = User::where(['id' => $booking['organiser_id']])->first();

            //buyer
            $customer      = User::where(['id' => $booking['customer_id']])->first();
           
            // test
            // $img_path      = '';
            // return view('invoice.invoice', compact('booking', 'organizer', 'customer', 'img_path'));
            $pdf_html      = (string) \View::make('invoice.invoice', compact('bookings', 'organizer', 'customer', 'img_path'));
            
            $pdf_name      = 'invoices/'.$booking['customer_id'];
    
            $invoice       = new  InvoicesController;
            $file          = $invoice->generatePdf($pdf_html, $pdf_name, $booking);
        }
        
        return response()->download($file);
        
    }
}
