<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Listing;
use App\Models\Booking;
use App\Models\PickupLocation;
use App\Services\BayarcashService;
use App\Services\PlatformFeeService;
use App\Services\GatewayFeeService;
use Carbon\Carbon;

class BookingForm extends Component
{
    public $listingId;
    public $listing;
    public $check_in = '';
    public $check_out = '';
    public $check_in_hour = '10';
    public $check_out_hour = '10';
    public $guests = 1;
    public $payment_channel = 'fpx';
    public $total_price = 0;
    public $days = 0;
    public $platform_fee = 0;
    public $gateway_fee = 0;
    public $booking_amount = 0;
    public $guest_total = 0;

    // Discount and add-ons
    public $subtotal = 0;
    public $discount_amount = 0;
    public $discount_percentage = 0;
    public $selectedAddOns = [];
    public $addOnsTotal = 0;

    // Pickup/Dropoff locations
    public $pickup_location_id = null;
    public $dropoff_location_id = null;

    public function mount($listingId)
    {
        $this->listingId = $listingId;
        $this->listing = Listing::with(['discountTiers', 'addOns', 'pickupLocations'])->findOrFail($listingId);
    }

    public function updatedCheckIn()
    {
        // Validate check-in is not in the past
        if ($this->check_in) {
            $checkInDate = Carbon::parse($this->check_in);
            $tomorrow = Carbon::tomorrow()->startOfDay();

            if ($checkInDate->lessThan($tomorrow)) {
                $this->check_in = '';
                $this->addError('check_in', 'Check-in date cannot be in the past or today. Please select a future date.');
                return;
            }

            // If check-out is set and is before or equal to new check-in, reset it
            if ($this->check_out && Carbon::parse($this->check_out)->lessThanOrEqualTo($checkInDate)) {
                $this->check_out = '';
            }
        }

        $this->calculateTotal();
        $this->checkAvailability();
    }

    public function updatedCheckOut()
    {
        // Validate check-out is after check-in
        if ($this->check_in && $this->check_out) {
            $checkInDate = Carbon::parse($this->check_in);
            $checkOutDate = Carbon::parse($this->check_out);

            if ($checkOutDate->lessThanOrEqualTo($checkInDate)) {
                $this->check_out = '';
                $this->addError('check_out', 'Check-out date must be after check-in date.');
                return;
            }
        }

        $this->calculateTotal();
        $this->checkAvailability();
    }

    public function calculateTotal()
    {
        if ($this->check_in && $this->check_out && $this->check_in_hour !== '' && $this->check_out_hour !== '') {
            // Combine date and hour
            $checkIn = Carbon::parse($this->check_in . ' ' . str_pad($this->check_in_hour, 2, '0', STR_PAD_LEFT) . ':00:00');
            $checkOut = Carbon::parse($this->check_out . ' ' . str_pad($this->check_out_hour, 2, '0', STR_PAD_LEFT) . ':00:00');

            if ($checkOut->greaterThan($checkIn)) {
                // Calculate hours and round up to full days
                // Any partial day counts as a full day
                $totalHours = $checkIn->diffInHours($checkOut);
                $this->days = (int) ceil($totalHours / 24);
                $this->subtotal = $this->days * $this->listing->price_per_day;

                // Apply discount tiers
                $discountInfo = $this->listing->calculatePriceWithDiscount($this->days);
                $this->discount_amount = $discountInfo['discount'];
                $this->discount_percentage = $discountInfo['discount_tier'] ? $discountInfo['discount_tier']->discount_value : 0;

                // Calculate add-ons total (use custom price if available)
                $this->addOnsTotal = 0;
                foreach ($this->selectedAddOns as $addOnId) {
                    $addOn = $this->listing->addOns->find($addOnId);
                    if ($addOn) {
                        $customPrice = $addOn->pivot->custom_price;
                        $this->addOnsTotal += $addOn->calculatePrice($this->days, $this->guests, $customPrice);
                    }
                }

                // Calculate booking amount (after discount + add-ons)
                $this->booking_amount = $discountInfo['total'] + $this->addOnsTotal;

                // Calculate platform fee
                $this->platform_fee = PlatformFeeService::calculateFee($this->booking_amount);
                $this->guest_total = PlatformFeeService::calculateGuestTotal($this->booking_amount);

                // Calculate gateway processing fee
                $this->gateway_fee = GatewayFeeService::calculateFee($this->guest_total);
                $this->total_price = $this->guest_total + $this->gateway_fee;
            }
        }
    }

    public function updatedSelectedAddOns()
    {
        $this->calculateTotal();
    }

    public function updatedGuests()
    {
        $this->calculateTotal();
    }

    public function updatedCheckInHour()
    {
        $this->calculateTotal();
        $this->checkAvailability();
    }

    public function updatedCheckOutHour()
    {
        $this->calculateTotal();
        $this->checkAvailability();
    }

    /**
     * Check availability in real-time when dates are selected
     */
    public function checkAvailability()
    {
        // Clear any previous availability errors
        $this->resetErrorBag(['check_in', 'check_out']);

        // Only check if all required fields are filled
        if (!$this->check_in || !$this->check_out || $this->check_in_hour === '' || $this->check_out_hour === '') {
            return;
        }

        // Combine date and hour
        $checkInDateTime = $this->check_in . ' ' . str_pad($this->check_in_hour, 2, '0', STR_PAD_LEFT) . ':00:00';
        $checkOutDateTime = $this->check_out . ' ' . str_pad($this->check_out_hour, 2, '0', STR_PAD_LEFT) . ':00:00';

        // Check availability
        if (!$this->listing->isAvailableForDates($checkInDateTime, $checkOutDateTime)) {
            $bufferMessage = $this->listing->buffer_hours > 0
                ? " (includes {$this->listing->buffer_hours} hour preparation time)"
                : '';
            $this->addError('check_out', 'This listing is not available for the selected dates' . $bufferMessage . '. Please choose different dates.');
        }
    }

    public function book()
    {
        // Check if email is verified
        if (!auth()->user()->hasVerifiedEmail()) {
            $this->addError('check_in', 'Please verify your email address before booking. Check your inbox for the verification link.');
            return;
        }

        // Check if phone number is provided
        if (empty(auth()->user()->phone)) {
            $this->addError('check_in', 'Please add your phone number to your profile before booking.');
            return;
        }

        // Validate pickup/dropoff locations (if applicable)
        $requiresPickupLocation = $this->listing->pickupLocations && $this->listing->pickupLocations->count() > 0;

        $validationRules = [
            'check_in' => 'required|date|after:today',
            'check_out' => 'required|date|after:check_in',
            'guests' => 'required|integer|min:1|max:' . $this->listing->capacity,
            'payment_channel' => 'required|in:fpx,tng', // card,boost - commented out for future use
        ];

        if ($requiresPickupLocation) {
            $validationRules['pickup_location_id'] = 'required|exists:pickup_locations,id';
            $validationRules['dropoff_location_id'] = 'required|exists:pickup_locations,id';
        }

        $this->validate($validationRules);

        // Combine date and hour for database storage
        $checkInDateTime = $this->check_in . ' ' . str_pad($this->check_in_hour, 2, '0', STR_PAD_LEFT) . ':00:00';
        $checkOutDateTime = $this->check_out . ' ' . str_pad($this->check_out_hour, 2, '0', STR_PAD_LEFT) . ':00:00';

        // Check availability using new method (includes buffer_hours)
        if (!$this->listing->isAvailableForDates($checkInDateTime, $checkOutDateTime)) {
            $bufferMessage = $this->listing->buffer_hours > 0
                ? " (includes {$this->listing->buffer_hours} hour preparation time)"
                : '';
            $this->addError('check_in', 'This listing is not available for the selected dates' . $bufferMessage . '. Please choose different dates.');
            return;
        }

        // Create booking
        $bookingData = [
            'listing_id' => $this->listing->id,
            'user_id' => auth()->id(),
            'check_in' => $checkInDateTime,
            'check_out' => $checkOutDateTime,
            'guests' => $this->guests,
            'total_price' => $this->guest_total, // Guest pays the total including platform fee
            'status' => 'pending',
            'discount_amount' => $this->discount_amount,
            'discount_percentage' => $this->discount_percentage,
            'platform_fee' => $this->platform_fee,
        ];

        // Add pickup/dropoff information if applicable
        if ($requiresPickupLocation) {
            $bookingData['pickup_location_id'] = $this->pickup_location_id;
            $bookingData['dropoff_location_id'] = $this->dropoff_location_id;
            // Use the check-in/check-out hours for pickup/dropoff times
            $bookingData['pickup_time'] = str_pad($this->check_in_hour, 2, '0', STR_PAD_LEFT) . ':00:00';
            $bookingData['dropoff_time'] = str_pad($this->check_out_hour, 2, '0', STR_PAD_LEFT) . ':00:00';
        }

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

        // Attach selected add-ons to booking (use custom price if available)
        foreach ($this->selectedAddOns as $addOnId) {
            $addOn = $this->listing->addOns->find($addOnId);
            if ($addOn) {
                $customPrice = $addOn->pivot->custom_price;
                $booking->addOns()->attach($addOnId, [
                    'quantity' => 1,
                    'price_paid' => $addOn->calculatePrice($this->days, $this->guests, $customPrice),
                ]);
            }
        }

        // Create payment intent with Bayarcash
        $bayarcashService = new BayarcashService();
        $result = $bayarcashService->createPaymentIntent($booking, $this->payment_channel);

        // Redirect to payment URL
        return redirect()->to($result['payment_url']);
    }

    public function render()
    {
        // Get booking calendar data for visual indicators
        $calendarData = $this->listing->getBookingCalendarData();

        return view('livewire.custom-booking-calendar', [
            'calendarData' => $calendarData,
        ]);
    }
}
