<?php

namespace App\Http\Controllers\Frontend;

use App\Enums\GatewayType;
use App\Enums\TxnStatus;
use App\Enums\TxnType;
use App\Http\Controllers\Controller;
use App\Models\Booking;
use App\Models\Gateway;
use App\Models\PaymentMethod;
use App\Models\Space;
use App\Models\Transaction;
use App\Traits\ImageUpload;
use App\Traits\NotifyTrait;
use App\Traits\Payment;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use App\Enums\BookingStatus;

class BookingController extends Controller
{
    use ImageUpload, NotifyTrait, Payment;

    public function bookings()
    {
        $bookings = Booking::where('user_id', Auth::id())->latest()->paginate(10);

        return view('frontend::user.bookings.bookings', compact('bookings'));
    }

    public function checkout(Request $request, $id = null)
    {
        $space = Space::where('id', $id !== null ? decrypt($id) : 0)->first();

        $spaces = Space::where('status', true)->get();

        return view('frontend::user.checkout.checkout', compact('space', 'spaces'));
    }
 
    public function place(Request $request, $id)
    {
        // Validate request data
        $request->validate([
            'from_date' => 'required|date_format:d/m/Y h:i A|before:to_date',
            'to_date' => 'required|date_format:d/m/Y h:i A|after:from_date',
            'stock' => 'required',
            'duration' => 'required',
            'facilities' => 'nullable|array',
            'first_name' => 'required',
            'last_name' => 'required',
            'email' => 'required|email',
            'phone' => 'required',
            'address' => 'required',
        ]);

        // Get space details
        $space = Space::findOrFail($id);
        if($space->stock < $request->stock){
            notify()->error(__('Stock Unavailable.'));
            return back();
        }
  
        // Convert dates to Carbon instances for comparison
        $fromDate = Carbon::createFromFormat('d/m/Y h:i A', $request->get('from_date'));
        $toDate = Carbon::createFromFormat('d/m/Y h:i A', $request->get('to_date'));

        // Format dates for storage
        $fromDateFormatted = $fromDate->format('d M Y h:i A');
        $toDateFormatted = $toDate->format('d M Y h:i A');

        // Get base price
        $basePrice = $space->price;

        // Get facilities
        $facilities = $space->facilities ?? [];

        // Calculate duration based on the price type
        $durationInUnits = $request->integer('duration');

        // Calculate total cost
        $totalCost = $durationInUnits * $basePrice * $request->stock;
        $selectedFacilities = [];

        // Calculate total cost for each facility
        foreach ($request->facilities ?? [] as $facilityId) {
            // Get facility details
            $facility = collect($facilities)->get($facilityId);

            // Check if facility exists and calculate price
            if ($facility !== null) {
                $facilityPrice = data_get($facility, 'price', 0);
                $facilityTitle = data_get($facility, 'title', '');
                $totalCost += $facilityPrice * $durationInUnits;
                $selectedFacilities[] = [
                    'title' => $facilityTitle,
                    'price' => $facilityPrice,
                ];
            }
        }

        // Get gateway
        $gateway = Gateway::where('id', $request->gateway)->first();

        // Get site currency
        $currency = setting('site_currency');

        // Billing details
        $billing_details = [
            'first_name' => $request->first_name,
            'last_name' => $request->last_name,
            'email' => $request->email,
            'phone' => $request->phone,
            'address' => $request->address,
        ];

        // Create transaction
        $transaction = Transaction::create([
            'user_id' => Auth::id(),
            'tnx' => 'TRX'.strtoupper(Str::random(10)),
            'description' => 'Space Booked',
            'type' => TxnType::Booking,
            'amount' => $totalCost,
            'pay_currency' => $currency,
            'charge' => 0,
            'final_amount' => $totalCost,
            'method' => $gateway?->name,
            'status' => TxnStatus::Pending,
        ]);

        // Create booking
        $booking = Booking::create([
            'booking_from' => $fromDateFormatted,
            'booking_to' => $toDateFormatted,
            'space_id' => $space->id,
            'stock' => $request->stock,
            'booking_id' => strtoupper(Str::random(5).time()),
            'user_id' => Auth::id(),
            'billing_details' => $billing_details,
            'facilities' => $request->facilities,
            'gateway_id' => $request->gateway,
            'transaction_id' => $transaction->id,
            'total_amount' => $totalCost,
            'is_paid' => false,
            'status' => TxnStatus::Pending,
        ]);

        // Update space stock
        $space->update([
            'stock' => $space->stock - $request->stock,
        ]);

        return to_route('user.booking.booked', $booking->booking_id);
    }

    public function booked($id)
    {
        $booking = Booking::where('user_id', Auth::id())->where('booking_id', $id)->firstOrFail();
        $gateways = PaymentMethod::where('status', 1)->get();

        return view('frontend::user.checkout.success', compact('booking', 'gateways'));
    }

    public function paymentNow(Request $request, $bookingId)
    {
        // Validate request data
        $request->validate([
            'gateway' => 'required|exists:payment_methods,id',
            'manual_data' => 'nullable|array',
        ]);

        // Get method
        $method = PaymentMethod::findOrFail($request->gateway);

        // Get booking by bookingId
        $booking = Booking::where('user_id', Auth::id())->where('booking_id', $bookingId)->where('is_paid', false)->firstOrFail();
        // Get gateway
        $gateway = $request->gateway;
        // Get booking transaction
        $transaction = $booking->transaction;

        // Update booking
        $booking->update([
            'gateway_id' => $method->id,
        ]);

        // Get manual data
        $manualData = $request->get('manual_data', []);

        // Upload manual data
        foreach ($manualData as $key => $value) {
            if (is_file($value)) {
                $manualData[$key] = $this->imageUploadTrait($request->file('manual_data.'.$key));
            }
        }

        // Calculate charge
        $charge = $method->charge_type == 'fixed' ? $method->charge : $method->charge * $booking->total_amount / 100;

        // Update transaction
        $transaction->update([
            'type' => $method->type == GatewayType::Automatic ? TxnType::Booking : TxnType::ManualPayment,
            'amount' => $booking->total_amount,
            'charge' => $charge,
            'final_amount' => $booking->total_amount + $charge,
            'method' => $method->name,
            'pay_amount' => $method->currency == setting('site_currency') ? $booking->total_amount + $charge : ($booking->total_amount + $charge) * $method->rate,
            'pay_currency' => $method->currency,
            'manual_field_data' => json_encode($manualData),
        ]);

        // Redirecting to gateway payment page
        return $this->bookingAutoGateway($method->gateway?->gateway_code, $transaction);
    }

    public function invoice($bookingId)
    {
        $booking = Booking::where('user_id', Auth::id())->where('booking_id', $bookingId)->firstOrFail();

        return view('frontend::user.bookings.invoice', [
            'booking' => $booking,
        ]);
    }

    public function gatewayDetails($id)
    {
        $gateway = PaymentMethod::findOrFail($id);

        if ($gateway->type == GatewayType::Manual) {
            $fieldOptions = $gateway->field_options;
            $paymentDetails = $gateway->payment_details;

            return response()->json([
                'html' => view('frontend::user.bookings.gateway_details', compact('fieldOptions', 'paymentDetails'))->render(),
                'gateway' => $gateway,
                'type' => 'manual',
            ]);
        }

        return response()->json([
            'gateway' => $gateway,
            'type' => 'automatic',
        ]);
    }
}
