<?php

namespace App\Http\Controllers;

use App\Models\Booking;
use App\Models\Customer;
use App\Models\ShipmentTracking;
use Illuminate\Http\Request;
use Barryvdh\DomPDF\Facade\Pdf;

use App\Models\Rate;

class BookingController extends Controller
{
    public function index(Request $request)
    {
        $query = Booking::with('customer');

        // Search functionality
        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function($q) use ($search) {
                $q->where('cntr_no', 'like', "%{$search}%")
                  ->orWhere('receiver_name', 'like', "%{$search}%")
                  ->orWhere('receiver_phone', 'like', "%{$search}%")
                  ->orWhereHas('customer', function($q) use ($search) {
                      $q->where('name', 'like', "%{$search}%")
                        ->orWhere('phone', 'like', "%{$search}%")
                        ->orWhere('cnic', 'like', "%{$search}%");
                  });
            });
        }

        // Filters
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        if ($request->filled('payment_status')) {
            $query->where('payment_status', $request->payment_status);
        }

        if ($request->filled('date_from')) {
            $query->whereDate('booking_date', '>=', $request->date_from);
        }

        if ($request->filled('date_to')) {
            $query->whereDate('booking_date', '<=', $request->date_to);
        }

        $bookings = $query->latest()->paginate(10)->withQueryString();
        
        // Get countries for the modal
        $countries = Rate::where('type', 'international')
            ->whereNotNull('country')
            ->distinct()
            ->pluck('country');

        return view('bookings.index', compact('bookings', 'countries'));
    }

    public function create(Request $request)
    {
        $type = $request->query('type', 'domestic');
        $country = $request->query('country');

        $customers = Customer::with(['rates' => function($query) use ($type, $country) {
            $query->where('is_active', true)
                  ->where('type', $type);
            
            if ($type === 'international' && $country) {
                $query->where('country', $country);
            }
        }])->where('is_active', true)->get();
        
        $globalRatesQuery = Rate::whereNull('customer_id')
            ->where('is_active', true)
            ->where('type', $type);
            
        if ($type === 'international' && $country) {
            $globalRatesQuery->where('country', $country);
        }
        
        $globalRates = $globalRatesQuery->get();
        
        return view('bookings.create', compact('customers', 'globalRates', 'type', 'country'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'cntr_no' => 'required|unique:bookings',
            'customer_id' => 'required|exists:customers,id',
            'receiver_name' => 'nullable|string|max:255',
            'receiver_phone' => 'nullable|string|max:20',
            'receiver_city' => 'nullable|string|max:100',
            'receiver_cnic' => 'nullable|string|max:20',
            'booking_date' => 'required|date',
            'loading_date' => 'nullable|date',
            'shipping_date' => 'nullable|date',
            'origin_city' => 'nullable|string|max:100',
            'destination_city' => 'nullable|string|max:100',
            'pickup_location' => 'required|string',
            'delivery_location' => 'required|string',
            'cargo_description' => 'required|string',
            'weight_kg' => 'nullable|numeric',
            'volume_cbm' => 'nullable|numeric',
            'carton_count' => 'nullable|integer',
            'weight_charge' => 'nullable|numeric',
            'volume_charge' => 'nullable|numeric',
            'carton_charge' => 'nullable|numeric',
            'total_amount' => 'required|numeric',
            'discount' => 'nullable|numeric',
            'advance_payment' => 'nullable|numeric|min:0',
            'notes' => 'nullable|string',
            'simple_items' => 'nullable|array',
            'simple_items.*.description' => 'required|string',
            'simple_items.*.quantity' => 'required|numeric',
            'simple_items.*.unit' => 'required|string',
            'simple_items.*.rate' => 'required|numeric',
            'simple_items.*.amount' => 'required|numeric',
        ]);

        // Set pickup_date same as booking_date for backward compatibility
        $validated['pickup_date'] = $validated['booking_date'];
        
        // Calculate due payment and payment status
        $total = $validated['total_amount'];
        $discount = $validated['discount'] ?? 0;
        $advance = $validated['advance_payment'] ?? 0;
        $validated['due_payment'] = $total - $discount - $advance;
        
        if ($advance == 0) {
            $validated['payment_status'] = 'Unpaid';
        } elseif ($advance >= ($total - $discount)) {
            $validated['payment_status'] = 'Paid';
            $validated['due_payment'] = 0;
        } else {
            $validated['payment_status'] = 'Partial';
        }

        $booking = Booking::create($validated);

        // Save Simple Items
        if ($request->has('simple_items')) {
            foreach ($request->simple_items as $item) {
                $booking->items()->create([
                    'description' => $item['description'],
                    'quantity' => $item['quantity'],
                    'unit' => $item['unit'],
                    'cartons' => $item['cartons'] ?? 0,
                    'baggage' => $item['baggage'] ?? 0,
                    'custom_label' => $item['custom_label'] ?? null,
                    'custom_value' => $item['custom_value'] ?? null,
                    'rate' => $item['rate'],
                    'amount' => $item['amount'],
                ]);
            }
        }

        return redirect()->route('bookings.index')->with('success', 'Booking created successfully!');
    }

    public function show(Booking $booking)
    {
        $booking->load('customer', 'tracking');
        return view('bookings.show', compact('booking'));
    }

    public function edit(Booking $booking)
    {
        $customers = Customer::where('is_active', true)->get();
        return view('bookings.edit', compact('booking', 'customers'));
    }

    public function update(Request $request, Booking $booking)
    {
        $validated = $request->validate([
            'cntr_no' => 'required|unique:bookings,cntr_no,' . $booking->id,
            'customer_id' => 'required|exists:customers,id',
            'receiver_name' => 'nullable|string|max:255',
            'receiver_phone' => 'nullable|string|max:20',
            'receiver_city' => 'nullable|string|max:100',
            'receiver_cnic' => 'nullable|string|max:20',
            'booking_date' => 'required|date',
            'pickup_date' => 'nullable|date',
            'delivery_date' => 'nullable|date',
            'loading_date' => 'nullable|date',
            'shipping_date' => 'nullable|date',
            'origin_city' => 'nullable|string|max:100',
            'destination_city' => 'nullable|string|max:100',
            'pickup_location' => 'required|string',
            'delivery_location' => 'required|string',
            'cargo_description' => 'required|string',
            'weight_kg' => 'nullable|numeric',
            'volume_cbm' => 'nullable|numeric',
            'carton_count' => 'nullable|integer',
            'weight_charge' => 'nullable|numeric',
            'volume_charge' => 'nullable|numeric',
            'carton_charge' => 'nullable|numeric',
            'total_amount' => 'required|numeric',
            'discount' => 'nullable|numeric',
            'advance_payment' => 'nullable|numeric|min:0',
            'status' => 'required|in:Pending,Loaded,In Transit,Arrived,Delivered,Damaged',
            'notes' => 'nullable|string',
            'items' => 'nullable|array',
            'items.*.description' => 'required|string',
            'items.*.quantity' => 'nullable|numeric',
            'items.*.unit' => 'nullable|string',
            'items.*.carton_count' => 'nullable|integer',
            'items.*.weight_kg' => 'nullable|numeric',
            'items.*.volume_cbm' => 'nullable|numeric',
            'items.*.rate' => 'nullable|numeric',
            'items.*.amount' => 'nullable|numeric',
        ]);

        // Set pickup_date same as booking_date if not provided
        if (empty($validated['pickup_date'])) {
            $validated['pickup_date'] = $validated['booking_date'];
        }

        // Calculate due payment and payment status
        $total = $validated['total_amount'];
        $discount = $validated['discount'] ?? 0;
        $advance = $validated['advance_payment'] ?? 0;
        $validated['due_payment'] = $total - $discount - $advance;
        
        if ($advance == 0) {
            $validated['payment_status'] = 'Unpaid';
        } elseif ($advance >= ($total - $discount)) {
            $validated['payment_status'] = 'Paid';
            $validated['due_payment'] = 0;
        } else {
            $validated['payment_status'] = 'Partial';
        }

        $booking->update($validated);

        // Sync Items
        if ($request->has('items')) {
            $booking->items()->delete();
            foreach ($request->items as $item) {
                $booking->items()->create([
                    'description' => $item['description'],
                    'quantity' => $item['quantity'] ?? 0,
                    'unit' => $item['unit'] ?? 'PCS',
                    'rate' => $item['rate'] ?? 0,
                    'amount' => $item['amount'] ?? 0,
                ]);
            }
        }

        return redirect()->route('bookings.index')->with('success', 'Booking updated successfully');
    }

    public function destroy(Booking $booking)
    {
        $booking->delete();
        return redirect()->route('bookings.index')->with('success', 'Booking deleted successfully');
    }

    public function downloadPdf(Booking $booking)
    {
        $booking->load('customer', 'tracking');
        $pdf = Pdf::loadView('bookings.invoice', compact('booking'));
        return $pdf->download('invoice-' . $booking->cntr_no . '.pdf');
    }

    public function printInvoice(Booking $booking)
    {
        $booking->load('customer', 'tracking');
        return view('bookings.invoice', compact('booking'));
    }

    public function printCargoSlip(Booking $booking)
    {
        $booking->load('customer', 'tracking');
        return view('bookings.cargo_slip', compact('booking'));
    }

    public function printDeliveryReceipt(Booking $booking)
    {
        $booking->load('customer', 'tracking');
        return view('bookings.delivery_receipt', compact('booking'));
    }

    public function printThermalReceipt(Booking $booking)
    {
        $booking->load('customer', 'tracking');
        return view('bookings.thermal_receipt', compact('booking'));
    }

    public function bulkStatusUpdate()
    {
        return view('bookings.bulk_status');
    }

    public function processBulkStatusUpdate(Request $request)
    {
        $request->validate([
            'cntr_list' => 'required|string',
            'status' => 'required|string',
            'location' => 'required|string',
            'remarks' => 'nullable|string',
        ]);

        $cntr_list = preg_split('/[\r\n,]+/', $request->cntr_list);
        $cntr_list = array_map('trim', $cntr_list);
        $cntr_list = array_filter($cntr_list); // Remove empty lines

        $updatedCount = 0;
        $notFound = [];

        foreach ($cntr_list as $cntr) {
            if (empty($cntr)) continue;

            $booking = Booking::where('cntr_no', $cntr)->first();

            if ($booking) {
                $booking->update([
                    'status' => $request->status,
                    // 'location' is usually part of tracking, but if we update current location field if exists
                    // Assuming booking has a 'current_location' or we just use tracking
                ]);

                // Add tracking history
                $booking->tracking()->create([
                    'status' => $request->status,
                    'location' => $request->location,
                    'remarks' => $request->remarks,
                    'status_date' => now(),
                ]);

                $updatedCount++;
            } else {
                $notFound[] = $cntr;
            }
        }

        $message = "Updated $updatedCount bookings successfully.";
        if (!empty($notFound)) {
            $message .= " CNTRs not found: " . implode(', ', $notFound);
        }

        return redirect()->route('bookings.bulk-status')->with('status', $message);
    }

    public function receiveShipment(Request $request)
    {
        $booking = null;
        if ($request->has('cntr_no')) {
            $booking = Booking::where('cntr_no', $request->cntr_no)->with('customer')->first();
        }
        return view('bookings.receive', compact('booking'));
    }

    public function processReceiveShipment(Request $request, Booking $booking)
    {
        $request->validate([
            'receiver_name' => 'required|string|max:255',
            'receiver_phone' => 'required|string|max:20',
            'receiver_cnic' => 'nullable|string|max:20',
            'location' => 'required|string|max:255',
            'remarks' => 'nullable|string',
            'payment_collected' => 'nullable|numeric|min:0',
        ]);

        // Update Receiver Details
        $booking->receiver_name = $request->receiver_name;
        $booking->receiver_phone = $request->receiver_phone;
        $booking->receiver_cnic = $request->receiver_cnic;
        $booking->status = 'Delivered'; // Auto mark as Delivered
        
        // Handle Payment
        if ($request->filled('payment_collected') && $request->payment_collected > 0) {
            $collected = $request->payment_collected;
            $newAdvance = $booking->advance_payment + $collected;

            // Ensure we don't overpay
            if ($newAdvance > $booking->total_amount) {
                return back()->withInput()->withErrors(['payment_collected' => 'Collected amount exceeds due amount.']);
            }
            
            $booking->advance_payment = $newAdvance;
            
            // Recalculate due
            $booking->due_payment = max(0, $booking->total_amount - $booking->advance_payment);
            
            // Update Payment Status
            if ($booking->due_payment == 0) {
                $booking->payment_status = 'Paid';
            } else {
                $booking->payment_status = 'Partial';
            }
        }

        $booking->save();

        // Add Tracking Entry
        $booking->tracking()->create([
            'status' => 'Delivered',
            'location' => $request->location,
            'remarks' => $request->remarks . ($request->payment_collected > 0 ? " (Payment Collected: {$request->payment_collected})" : ""),
            'status_date' => now(),
        ]);

        return redirect()->route('bookings.receive')->with('success', "Shipment {$booking->cntr_no} received successfully.");
    }

    public function track(Request $request)
    {
        $cntr_no = $request->input('cntr_no');
        $booking = Booking::where('cntr_no', $cntr_no)->with('customer', 'tracking')->first();
        
        return view('bookings.track', compact('booking', 'cntr_no'));
    }

    /**
     * Quick update booking status
     */
    public function updateStatus(Request $request, Booking $booking)
    {
        $request->validate([
            'status' => 'required|in:Pending,Loaded,In Transit,Arrived,Delivered,Damaged'
        ]);

        $booking->update([
            'status' => $request->status
        ]);

        return redirect()->route('bookings.index')->with('success', 'Booking status updated successfully to ' . $request->status);
    }

    /**
     * Quick update booking payment
     */
    public function updatePayment(Request $request, Booking $booking)
    {
        $request->validate([
            'payment_amount' => 'required|numeric|min:0|max:' . $booking->due_payment
        ]);

        $newAdvancePayment = $booking->advance_payment + $request->payment_amount;
        $newDuePayment = $booking->total_amount - $newAdvancePayment;

        // Determine payment status
        $paymentStatus = 'Unpaid';
        if ($newAdvancePayment >= $booking->total_amount) {
            $paymentStatus = 'Paid';
        } elseif ($newAdvancePayment > 0) {
            $paymentStatus = 'Partial';
        }

        $booking->update([
            'advance_payment' => $newAdvancePayment,
            'due_payment' => $newDuePayment,
            'payment_status' => $paymentStatus
        ]);

        return redirect()->route('bookings.index')->with('success', 'Payment updated successfully. New balance due: Rs. ' . number_format($newDuePayment, 2));
    }

}
