/home2/mshostin/hall-management.ms-hostingladz.com/app/Http/Controllers/BookingController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\BookingRequest;
use App\Models\Booking;
use App\Models\Hall;
use App\Services\BookingService;
use App\Services\CustomerService;
use App\Services\InvoiceService;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;

class BookingController extends Controller
{
    protected $customerService;

    protected $bookingService;

    protected $invoiceService;

    public function __construct(CustomerService $customerService, BookingService $bookingService, InvoiceService $invoiceService)
    {
        $this->customerService = $customerService;
        $this->bookingService = $bookingService;
        $this->invoiceService = $invoiceService;

        $this->middleware('permission:view-bookings')->only(['index', 'show', 'invoice']);
        $this->middleware('permission:create-bookings')->only(['create', 'store']);
        $this->middleware('permission:edit-bookings')->only(['edit', 'update']);
        $this->middleware('permission:delete-bookings')->only(['destroy']);
    }

    public function index()
    {
        $this->authorize('viewAny', Booking::class);

        $user = auth()->user();

        // Fetch bookings based on role
        if ($user->isSuperAdmin()) {
            $bookings = Booking::with('customer', 'hall')->get();
            // } elseif ($user->isHallAdmin()) {
            //     $bookings = Booking::with('customer', 'hall')
            //         ->where('hall_id', $user->hall_id)
            //         ->get();
        } else {
            // Other users with view-bookings permission
            // $bookings = Booking::with('customer', 'hall')->get();
            $bookings = Booking::with('customer', 'hall')
                ->where('hall_id', $user->hall_id)
                ->get();
        }

        // Prepare events for FullCalendar
        $calendarEvents = $bookings->map(function ($b) {
            return [
                'id' => $b->id,
                'title' => ($b->customer->name ?? 'Customer').' - '.($b->hall->name ?? 'Hall'),
                'start' => $b->start_datetime,
                'end' => $b->end_datetime,
                'url' => route('bookings.show', $b->id),
            ];
        });

        return view('bookings.index', [
            'bookings' => $bookings,
            'calendarEvents' => $calendarEvents,
        ]);
    }

    public function create()
    {
        $user = auth()->user();

        if ($user->hasRole('super_admin')) {
            $halls = Hall::all();
        } elseif ($user->hasRole('hall_admin')) {

            if ($user->hall_id ?? false) {
                $halls = Hall::where('id', $user->hall_id)->get();
            } elseif ($user->halls()->exists()) {
                $halls = $user->halls;
            } else {
                $halls = collect();
            }
        } else {
            $halls = collect();
        }

        return view('bookings.create', compact('halls'));
    }

    // public function create()
    // {
    //     $halls = \App\Models\Hall::all();
    //     return view('bookings.create', compact('halls'));
    // }

    public function store(BookingRequest $request)
    {
        $customer = $this->customerService->createOrUpdate([
            'name' => $request->customer_name,
            'phone' => $request->customer_phone,
            'email' => $request->customer_email,
            'cnic' => $request->customer_cnic,
            'address' => $request->customer_address,
        ]);

        if (! $this->bookingService->checkAvailability($request->lawn_id, $request->start_datetime, $request->end_datetime)) {
            return back()->withErrors(['lawn_id' => 'Selected lawn is already booked for this time range.'])->withInput();
        }

        $booking = $this->bookingService->createBooking(array_merge(
            $request->only([
                'hall_id', 'start_datetime', 'end_datetime', 'capacity',
                'quote_price', 'booking_price', 'advance_paid', 'payment_status', 'status', 'notes', 'facilities', 'lawn_id',
            ]),
            ['customer_id' => $customer->id]
        ));

        // Generate invoice PDF
        $invoiceData = $this->invoiceService->generateInvoicePdf($booking);
        
        // Generate WhatsApp and Gmail URLs
        $whatsappUrl = $this->invoiceService->generateWhatsAppUrl($booking, url($invoiceData['url']));
        $gmailUrl = $this->invoiceService->generateGmailUrl($booking, url($invoiceData['url']));

        return view('bookings.booking-success', [
            'booking' => $booking,
            'invoiceUrl' => $invoiceData['url'],
            'whatsappUrl' => $whatsappUrl,
            'gmailUrl' => $gmailUrl,
        ]);
    }

    public function show(Booking $booking)
    {
        $this->authorize('view', $booking);
        $booking->load(['customer', 'hall', 'lawn']);

        // Generate URLs
        $filename = 'invoice_' . $booking->formatted_booking_number . '.pdf';
        $invoiceUrl = \Illuminate\Support\Facades\Storage::disk('public')->url('invoices/' . $filename);
        $fullInvoiceUrl = url($invoiceUrl);
        
        $whatsappUrl = $this->invoiceService->generateWhatsAppUrl($booking, $fullInvoiceUrl);
        $gmailUrl = $this->invoiceService->generateGmailUrl($booking, $fullInvoiceUrl);

        return view('bookings.show', compact('booking', 'whatsappUrl', 'gmailUrl', 'invoiceUrl'));
    }

    public function edit(Booking $booking)
    {
        $start = $booking->start_datetime;
        $end = $booking->end_datetime;

        $hall = $booking->hall;
        $lawns = $hall->lawns()->select('id', 'name', 'capacity')->get();

        if ($start && $end) {
            $startDate = \Carbon\Carbon::parse($start);
            $endDate = \Carbon\Carbon::parse($end);

            $lawns->transform(function ($lawn) use ($startDate, $endDate) {
                // Check if any booking overlaps in time
                $booking = Booking::where('lawn_id', $lawn->id)
                    ->where(function ($query) use ($startDate, $endDate) {
                        $query->where('start_datetime', '<', $endDate)
                            ->where('end_datetime', '>', $startDate);
                    })
                    ->first();

                if ($booking) {
                    $lawn->available = false;
                    $lawn->booked_from = $booking->start_datetime->format('d M Y h:i A');
                    $lawn->booked_to = $booking->end_datetime->format('d M Y h:i A');
                } else {
                    $lawn->available = true;
                    $lawn->booked_from = null;
                    $lawn->booked_to = null;
                }

                return $lawn;
            });
        } else {
            $lawns->transform(function ($lawn) {
                $lawn->available = true;
                $lawn->booked_from = null;
                $lawn->booked_to = null;

                return $lawn;
            });
        }

        $halls = \App\Models\Hall::all();
        $booking->load('customer');

        return view('bookings.edit', compact('booking', 'halls', 'lawns'));
    }

    public function update(BookingRequest $request, Booking $booking)
    {
        $customer = $this->customerService->createOrUpdate([
            'name' => $request->customer_name,
            'phone' => $request->customer_phone,
            'email' => $request->customer_email,
            'cnic' => $request->customer_cnic,
            'address' => $request->customer_address,
        ], $booking->customer_id);

        if (! $this->bookingService->checkAvailability($request->lawn_id, $request->start_datetime, $request->end_datetime, $booking->id)) {
            return back()->withErrors(['lawn_id' => 'Selected lawn is already booked for this time range.'])->withInput();
        }

        $this->bookingService->updateBooking($booking, array_merge(
            $request->only([
                'hall_id', 'start_datetime', 'end_datetime', 'capacity',
                'quote_price', 'booking_price', 'advance_paid', 'payment_status', 'status', 'notes', 'facilities', 'lawn_id',
            ]),
            ['customer_id' => $customer->id]
        ));

        return redirect()->route('bookings.show', $booking->id)->with('success', 'Booking updated successfully.');
    }

    public function invoice(Booking $booking)
    {
        $this->authorize('view', $booking);
        $booking->load(['customer', 'hall', 'lawn']);

        return view('bookings.invoice', compact('booking'));
    }
}