<?php

namespace App\Http\Controllers;


use App\Models\Booking;
use App\Models\Rooms;
use App\Models\User;
use App\Notifications\NewBookingNotification;
use App\Notifications\BookingReceiptNotification;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use PDF;
use Symfony\Component\HttpFoundation\StreamedResponse;

class BookingController extends Controller
{
    public function index()
    {
        try {
            $bookings = Booking::with(['user', 'room.propertyType.property'])->latest()->get();
            return response()->json(['success' => true, 'data' => $bookings], 200);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }
    public function index2()
    {
        try {
            $bookings = Booking::with(['user','room.propertyType.property'])
            ->where('id_user', auth()->id())
            ->latest()
            ->paginate(5);

            return response()->json([
                'success' => true, 
                'data' => $bookings
            ], 200);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function show($id)
    {
        try {
            $booking = Booking::with(['user', 'room'])->findOrFail($id);
            return response()->json(['success' => true, 'data' => $booking], 200);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Booking not found'], 404);
        }
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'id_room'     => 'required|exists:rooms,id',
            'checkin'     => 'required|date',
            'quantity'    => 'required|integer|min:1',
            'status'      => 'in:waiting,review,success,rejected,cancelled,completed',
        ]);
    
        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }
    
        try {
            // ✅ Ambil room dan cek status
            $room = Rooms::where('id', $request->id_room)
                ->where('status', 'available')
                ->with('propertyType')
                ->first();
    
            if (!$room) {
                return response()->json([
                    'success' => false,
                    'message' => 'Room is not available or already booked.'
                ], 409);
            }
    
            // ✅ Hitung total_price
            $hargaPerUnit = $room->propertyType->harga ?? 0;
            $totalPrice = $hargaPerUnit * $request->quantity;
    
            // ✅ Generate invoice_id otomatis
            $today = now()->format('Ymd');
            $prefix = "MHI-$today-";
            $lastInvoice = Booking::where('invoice_id', 'like', "$prefix%")
                ->orderBy('invoice_id', 'desc')
                ->first();
    
            $lastNumber = $lastInvoice && preg_match('/-(\d+)$/', $lastInvoice->invoice_id, $match)
                ? (int)$match[1]
                : 0;
    
            $nextNumber = str_pad($lastNumber + 1, 4, '0', STR_PAD_LEFT);
            $invoiceId = $prefix . $nextNumber;
    
            // ✅ Simpan booking
            $booking = Booking::create([
                'invoice_id'  => $invoiceId,
                'id_room'     => $request->id_room,
                'id_user'     => auth()->id(),
                'checkin'     => $request->checkin,
                'quantity'    => $request->quantity,
                'total_price' => $totalPrice,
                'status'      => $request->status ?? 'waiting',
            ]);
    
            // ✅ Update status kamar
            $room->status = 'booked';
            $room->save();
    
            // ✅ Response langsung dikirim dulu
            $response = response()->json(['success' => true, 'data' => $booking], 201);
    
            // ✅ Email diproses setelah response dikirim
            register_shutdown_function(function () use ($booking) {
                $user = auth()->user();
                if ($user && $user->email_verified_at) {
                    $user->notify(new BookingReceiptNotification($booking));
                }
    
                $admins = User::whereIn('id_role', [1, 2])
                    ->whereNotNull('email_verified_at')
                    ->get();
    
                foreach ($admins as $admin) {
                    $admin->notify(new NewBookingNotification($booking));
                }
            });
    
            return $response;
    
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    
    
    public function storeAdmin(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'id_room'     => 'required|exists:rooms,id',
            'id_user'     => 'required|exists:users,id',
            'checkin'     => 'required|date',
            'quantity'    => 'required|integer|min:1',
            'status'      => 'in:waiting,review,success,rejected,cancelled,completed',
        ]);
    
        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }
    
        try {
            // ✅ Ambil room dan cek status
            $room = Rooms::where('id', $request->id_room)
                ->where('status', 'available')
                ->with('propertyType')
                ->first();
    
            if (!$room) {
                return response()->json([
                    'success' => false,
                    'message' => 'Room is not available or already booked.'
                ], 409);
            }
    
            // ✅ Hitung total_price
            $hargaPerUnit = $room->propertyType->harga ?? 0;
            $totalPrice = $hargaPerUnit * $request->quantity;
    
            // ✅ Generate invoice_id
            $today = now()->format('Ymd');
            $prefix = "MHI-$today-";
            $lastInvoice = Booking::where('invoice_id', 'like', "$prefix%")
                ->orderBy('invoice_id', 'desc')
                ->first();
    
            $lastNumber = $lastInvoice && preg_match('/-(\d+)$/', $lastInvoice->invoice_id, $match)
                ? (int)$match[1]
                : 0;
    
            $nextNumber = str_pad($lastNumber + 1, 4, '0', STR_PAD_LEFT);
            $invoiceId = $prefix . $nextNumber;
    
            // ✅ Simpan booking
            $booking = Booking::create([
                'invoice_id'  => $invoiceId,
                'id_room'     => $request->id_room,
                'id_user'     => $request->id_user,
                'checkin'     => $request->checkin,
                'quantity'    => $request->quantity,
                'total_price' => $totalPrice,
                'status'      => $request->status ?? 'waiting',
            ]);
    
            // ✅ Update status kamar
            $room->status = 'booked';
            $room->save();
    
            // ✅ Kirim notifikasi langsung (tanpa queue)
            // $user = User::find($request->id_user);
            // if ($user && $user->email_verified_at) {
            //     $user->notify(new BookingReceiptNotification($booking));
            // }
    
            // $admins = User::whereIn('id_role', [1, 2])
            //     ->whereNotNull('email_verified_at')
            //     ->get();
    
            // foreach ($admins as $admin) {
            //     $admin->notify(new NewBookingNotification($booking));
            // }
    
            $response = response()->json(['success' => true, 'data' => $booking], 201);

            // ✅ Email diproses setelah response dikirim
            register_shutdown_function(function () use ($booking, $request) {
                $user = User::find($request->id_user);
                if ($user && $user->email_verified_at) {
                    $user->notify(new BookingReceiptNotification($booking));
                }
            
                $admins = User::whereIn('id_role', [1, 2])
                    ->whereNotNull('email_verified_at')
                    ->get();
            
                foreach ($admins as $admin) {
                    $admin->notify(new NewBookingNotification($booking));
                }
            });
            
            return $response;

    
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }



    public function update(Request $request, $id)
    {
        $booking = Booking::find($id);
        if (!$booking) {
            return response()->json(['success' => false, 'message' => 'Booking not found'], 404);
        }

        $validator = Validator::make($request->all(), [
            'id_room'     => 'sometimes|exists:rooms,id',
            'id_user'     => 'nullable|exists:users,id',
            'checkin'     => 'sometimes|date',
            'start_date'  => 'sometimes|date',
            'end_date'    => 'sometimes|date|after_or_equal:start_date',
            'quantity'    => 'sometimes|integer|min:1',
            'total_price' => 'sometimes|numeric|min:0',
            'status'      => 'in:waiting,review,success,rejected,cancelled,completed',
        ]);

        if ($validator->fails()) {
            return response()->json(['success' => false, 'errors' => $validator->errors()], 422);
        }

        try {
            // Simpan status sebelum update
            $oldStatus = $booking->status;
        
            $booking->update($request->all());
        
            // Reset payment verification jika status berubah
            if ($oldStatus !== $booking->status) {
                \App\Models\Payment::where('invoice_id', $booking->invoice_id)
                    ->update(['verified_at' => null, 'status' => $booking->status]);
            }
            return response()->json(['success' => true, 'data' => $booking], 200);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function destroy($id)
    {
        try {
            $booking = Booking::findOrFail($id);
            $booking->delete();
            return response()->json(['success' => true, 'message' => 'Booking deleted'], 200);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function trashed()
    {
        try {
            $trashed = Booking::onlyTrashed()
                ->with(['user', 'room.propertyType.property'])
                ->latest()
                ->get();

            return response()->json([
                'success' => true,
                'data' => $trashed
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve trashed bookings.',
                'error' => $e->getMessage()
            ], 500);
        }
    }
    public function restore($id)
    {
        try {
            $booking = Booking::onlyTrashed()->findOrFail($id);
            $booking->restore();

            return response()->json([
                'success' => true,
                'message' => 'Booking restored successfully',
                'data' => $booking
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to restore booking.',
                'error' => $e->getMessage()
            ], 500);
        }
    }
    public function forceDelete($id)
    {
        try {
            $booking = Booking::withTrashed()->findOrFail($id);

            // Cek apakah booking ini digunakan pada tabel payment
            $hasPayment = \App\Models\Payment::where('invoice_id', $booking->invoice_id)->exists();
            if ($hasPayment) {
                return response()->json([
                    'success' => false,
                    'message' => 'Tidak dapat dihapus permanen karena masih terkait dengan data pembayaran.'
                ], 422);
            }

            $booking->forceDelete();

            return response()->json([
                'success' => true,
                'message' => 'Booking permanently deleted'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to permanently delete booking.',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Export individual booking to PDF
     */
    public function exportPdf($id)
    {
        try {
            $booking = Booking::with(['user', 'room.propertyType.property'])->findOrFail($id);
            
            $data = [
                'booking' => $booking,
                'title' => 'Detail Booking - ' . $booking->invoice_id
            ];

            $pdf = PDF::loadView('exports.booking_detail', $data);
            
            return $pdf->download('booking-' . $booking->invoice_id . '.pdf');
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to generate PDF: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Export all bookings to Excel/CSV
     */
    public function exportExcel()
    {
        $fileName = 'bookings_' . date('Y-m-d_H-i-s') . '.csv';

        $response = new StreamedResponse(function () use ($fileName) {
            $handle = fopen('php://output', 'w');

            // Header CSV
            fputcsv($handle, [
                'No', 'Invoice ID', 'Penyewa', 'Room', 'Property', 'Check-in', 
                'Start Date', 'End Date', 'Duration', 'Total Price', 'Status', 'Created At'
            ]);

            try {
                Booking::with(['user', 'room.propertyType.property'])->chunk(500, function ($bookings) use ($handle) {
                    $counter = 1;
                    foreach ($bookings as $booking) {
                        fputcsv($handle, [
                            $counter++,
                            $booking->invoice_id,
                            $booking->user ? $booking->user->name : 'Unknown',
                            $booking->room ? $booking->room->kode_kamar : 'Unknown',
                            $booking->room && $booking->room->propertyType && $booking->room->propertyType->property 
                                ? $booking->room->propertyType->property->prop_name 
                                : 'Unknown',
                            $booking->checkin,
                            $booking->start_date,
                            $booking->end_date,
                            $booking->quantity,
                            number_format($booking->total_price, 0, ',', '.'),
                            $booking->status,
                            $booking->created_at
                        ]);
                    }
                });
            } catch (\Exception $e) {
                fclose($handle);
                return response()->json(['error' => 'Failed to generate CSV: ' . $e->getMessage()], 500);
            }

            fclose($handle);
        });

        $response->headers->set('Content-Type', 'text/csv');
        $response->headers->set('Content-Disposition', 'attachment; filename="' . $fileName . '"');

        return $response;
    }
}