<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Booking;
use App\Models\Payment;
use App\Models\OfflinePayment;
use App\Models\Package;
use App\Models\Setting;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use App\Mail\BookingConfirmationMail;
use App\Mail\PaymentRequestMail;
use Illuminate\Support\Str;

class BookingController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'package_id' => 'required|exists:packages,id',
            'first_name' => 'required|string|max:255',
            'last_name' => 'required|string|max:255',
            'email' => 'required|email|max:255',
            'phone' => 'required|string|max:20',
            'country' => 'required|string|max:100',
            'travel_date' => 'required|date|after:today',
            'number_of_people' => 'required|integer|min:1',
            'payment_method' => 'required|in:flutterwave,whatsapp,offline',
            'special_requests' => 'nullable|string|max:1000',
            'traveler_details' => 'nullable|array',
            'traveler_details.*.name' => 'required|string|max:255',
            'traveler_details.*.age' => 'required|integer|min:0|max:120',
            'traveler_details.*.passport_number' => 'nullable|string|max:50',
        ]);

        try {
            $package = Package::findOrFail($validated['package_id']);
            
            // Check package availability
            if (!$package->is_available) {
                return back()->with('error', __('This package is currently not available for booking.'))
                    ->withInput($request->except('traveler_details'));
            }

            // Check if package can accommodate the requested number of people
            if (!$package->canBook($validated['number_of_people'])) {
                return back()->with('error', __('This package cannot accommodate the requested number of people.'))
                    ->withInput($request->except('traveler_details'));
            }

            // Calculate total price
            $pricePerPerson = $package->has_discount ? $package->discount_price : $package->price;
            $totalPrice = $pricePerPerson * $validated['number_of_people'];

            // Create booking
            $booking = Booking::create([
                'user_id' => Auth::id() ?? null,
                'package_id' => $package->id,
                'first_name' => $validated['first_name'],
                'last_name' => $validated['last_name'],
                'email' => $validated['email'],
                'phone' => $validated['phone'],
                'country' => $validated['country'],
                'travel_date' => $validated['travel_date'],
                'number_of_people' => $validated['number_of_people'],
                'total_price' => $totalPrice,
                'currency' => $package->currency,
                'payment_method' => $validated['payment_method'],
                'special_requests' => $validated['special_requests'] ?? null,
                'traveler_details' => $validated['traveler_details'] ?? null,
            ]);

            // Create payment record
            $payment = Payment::create([
                'booking_id' => $booking->id,
                'amount' => $totalPrice,
                'currency' => $package->currency,
                'payment_method' => $validated['payment_method'],
                'status' => 'pending',
            ]);

            // Send booking confirmation email
            try {
                Mail::to($booking->email)->send(new BookingConfirmationMail($booking, $package));
                
                // Send notification to admin
                $adminEmail = Setting::get('site_email', 'info@tourism.com');
                Mail::to($adminEmail)->send(new BookingConfirmationMail($booking, $package, true));
                
            } catch (\Exception $e) {
                \Log::error('Booking confirmation email failed: ' . $e->getMessage());
            }

            // Handle different payment methods
            if ($validated['payment_method'] === 'flutterwave') {
                // Redirect to Flutterwave payment initialization
                return redirect()->route('payment.initialize', ['reference' => $payment->payment_reference])
                    ->with('success', __('Booking created successfully! Please complete payment.'));
            } elseif ($validated['payment_method'] === 'offline') {
                // Redirect to offline payment submission
                return redirect()->route('offline-payment.show', $booking->booking_reference)
                    ->with('success', __('Booking created successfully! Please submit your payment proof.'));
            } else {
                // Handle WhatsApp payment
                $whatsappNumber = Setting::get('whatsapp_number', '+1234567890');
                $whatsappMessage = $payment->generateWhatsAppMessage();
                
                $whatsappUrl = "https://wa.me/" . str_replace(['+', '-', ' ', '(', ')'], '', $whatsappNumber) . 
                              "?text=" . urlencode($whatsappMessage);

                return redirect()->route('booking.success', $booking->booking_reference)
                    ->with('success', __('Booking created successfully! Please complete payment via WhatsApp.'))
                    ->with('whatsapp_url', $whatsappUrl)
                    ->with('payment_reference', $payment->payment_reference);
            }

        } catch (\Exception $e) {
            \Log::error('Booking creation error: ' . $e->getMessage());
            return back()->with('error', __('Failed to create booking. Please try again.'))
                ->withInput($request->except('traveler_details'));
        }
    }

    public function success($reference)
    {
        $booking = Booking::with(['package', 'payment'])
            ->where('booking_reference', $reference)
            ->firstOrFail();

        return view('booking.success', compact('booking'));
    }

    public function failed($reference)
    {
        $booking = Booking::with(['package', 'payment'])
            ->where('booking_reference', $reference)
            ->firstOrFail();

        return view('booking.failed', compact('booking'));
    }

    public function confirmPayment(Request $request, $reference)
    {
        $payment = Payment::with(['booking', 'booking.package'])
            ->where('payment_reference', $reference)
            ->firstOrFail();

        if ($payment->status !== 'pending') {
            return back()->with('error', __('Payment has already been processed.'));
        }

        $request->validate([
            'admin_notes' => 'nullable|string|max:1000',
            'payment_proof' => 'nullable|file|mimes:jpg,jpeg,png,pdf|max:2048',
        ]);

        try {
            $paymentData = [
                'status' => 'completed',
                'confirmed_at' => now(),
                'admin_notes' => $request->admin_notes,
            ];

            // Handle payment proof upload
            if ($request->hasFile('payment_proof')) {
                $file = $request->file('payment_proof');
                $filename = 'payment_proof_' . $payment->payment_reference . '_' . time() . '.' . $file->getClientOriginalExtension();
                $path = $file->storeAs('payment_proofs', $filename, 'public');
                $paymentData['payment_proof'] = ['path' => $path, 'original_name' => $file->getClientOriginalName()];
            }

            $payment->update($paymentData);

            // Confirm booking
            $payment->booking->confirm();

            // Send payment confirmation email
            try {
                Mail::to($payment->booking->email)->send(new PaymentRequestMail($payment, true));
            } catch (\Exception $e) {
                \Log::error('Payment confirmation email failed: ' . $e->getMessage());
            }

            return back()->with('success', __('Payment confirmed successfully! Booking has been confirmed.'));

        } catch (\Exception $e) {
            \Log::error('Payment confirmation error: ' . $e->getMessage());
            return back()->with('error', __('Failed to confirm payment. Please try again.'));
        }
    }

    public function rejectPayment(Request $request, $reference)
    {
        $payment = Payment::with(['booking', 'booking.package'])
            ->where('payment_reference', $reference)
            ->firstOrFail();

        if ($payment->status !== 'pending') {
            return back()->with('error', __('Payment has already been processed.'));
        }

        $request->validate([
            'rejection_reason' => 'required|string|max:1000',
        ]);

        try {
            $payment->update([
                'status' => 'failed',
                'admin_notes' => $request->rejection_reason,
            ]);

            // Send payment rejection email
            try {
                Mail::to($payment->booking->email)->send(new PaymentRequestMail($payment, false));
            } catch (\Exception $e) {
                \Log::error('Payment rejection email failed: ' . $e->getMessage());
            }

            return back()->with('success', __('Payment rejected and customer has been notified.'));

        } catch (\Exception $e) {
            \Log::error('Payment rejection error: ' . $e->getMessage());
            return back()->with('error', __('Failed to reject payment. Please try again.'));
        }
    }

    public function generateWhatsAppPayment($reference)
    {
        $payment = Payment::with(['booking', 'booking.package'])
            ->where('payment_reference', $reference)
            ->firstOrFail();

        if ($payment->status !== 'pending') {
            return response()->json(['error' => __('Payment has already been processed.')]);
        }

        $whatsappNumber = Setting::get('whatsapp_number', '+1234567890');
        $whatsappMessage = $payment->generateWhatsAppMessage();
        
        $whatsappUrl = "https://wa.me/" . str_replace(['+', '-', ' ', '(', ')'], '', $whatsappNumber) . 
                      "?text=" . urlencode($whatsappMessage);

        return response()->json([
            'whatsapp_url' => $whatsappUrl,
            'message' => $whatsappMessage,
            'payment_reference' => $payment->payment_reference,
        ]);
    }

    public function checkBookingStatus($reference)
    {
        $booking = Booking::with(['package', 'payment'])
            ->where('booking_reference', $reference)
            ->firstOrFail();

        return response()->json([
            'booking_status' => $booking->status,
            'payment_status' => $booking->payment_status,
            'confirmed_at' => $booking->confirmed_at,
            'payment_confirmed_at' => $booking->payment->confirmed_at,
        ]);
    }

    public function cancelBooking(Request $request, $reference)
    {
        $booking = Booking::with(['package', 'payment'])
            ->where('booking_reference', $reference)
            ->firstOrFail();

        // Check if user can cancel this booking
        if (Auth::id() !== $booking->user_id && !Auth::user()->is_admin) {
            return back()->with('error', __('You are not authorized to cancel this booking.'));
        }

        if ($booking->status === 'cancelled') {
            return back()->with('error', __('Booking is already cancelled.'));
        }

        if ($booking->status === 'completed') {
            return back()->with('error', __('Cannot cancel a completed booking.'));
        }

        // Check cancellation policy (e.g., can cancel up to 48 hours before travel date)
        $cancellationDeadline = $booking->travel_date->subHours(48);
        if (now()->greaterThan($cancellationDeadline)) {
            return back()->with('error', __('Cannot cancel booking less than 48 hours before travel date.'));
        }

        $request->validate([
            'cancellation_reason' => 'required|string|max:1000',
        ]);

        try {
            $booking->cancel($request->cancellation_reason);

            // Refund payment if paid
            if ($booking->payment_status === 'paid') {
                $booking->payment->refund();
            }

            // Send cancellation email
            try {
                Mail::to($booking->email)->send(new \App\Mail\BookingCancellationMail($booking));
            } catch (\Exception $e) {
                \Log::error('Cancellation email failed: ' . $e->getMessage());
            }

            return back()->with('success', __('Booking cancelled successfully.'));

        } catch (\Exception $e) {
            \Log::error('Booking cancellation error: ' . $e->getMessage());
            return back()->with('error', __('Failed to cancel booking. Please try again.'));
        }
    }
}
