<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\Api\ConfirmBookingPaymentRequest;
use App\Http\Requests\Api\LookupBookingUnitRequest;
use App\Http\Requests\Api\StoreBookingRequest;
use App\Http\Requests\Api\UpdateBookingRequest;
use App\Http\Resources\BookingResource;
use App\Models\Booking;
use App\Models\User;
use App\Services\BookingService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Http\Response;

class BookingController extends Controller
{
    public function __construct(private BookingService $bookings) {}

    public function index(): AnonymousResourceCollection
    {
        return BookingResource::collection(
            Booking::query()
                ->with(['customer.nominee.documents', 'agent', 'unit', 'subtype', 'floor', 'creator', 'documents'])
                ->latest('id')
                ->get(),
        );
    }

    public function lookup(LookupBookingUnitRequest $request): JsonResponse
    {
        return response()->json([
            'data' => $this->bookings->lookup(
                (int) $request->validated('unit_id'),
                (string) $request->validated('unit_number'),
            ),
        ]);
    }

    public function store(StoreBookingRequest $request): JsonResponse
    {
        $actor = $request->user();

        assert($actor instanceof User);

        $booking = $this->bookings->create($actor, $request->payload(), $request->proofs());

        return BookingResource::make($this->loadBooking($booking))
            ->response()
            ->setStatusCode(201);
    }

    public function show(Booking $booking): BookingResource
    {
        return BookingResource::make($this->loadBooking($booking));
    }

    public function update(UpdateBookingRequest $request, Booking $booking): BookingResource
    {
        $booking = $this->bookings->update($booking, $request->payload());

        return BookingResource::make($this->loadBooking($booking));
    }

    public function creditPayment(ConfirmBookingPaymentRequest $request, Booking $booking): BookingResource
    {
        $actor = $request->user();

        assert($actor instanceof User);

        $booking = $this->bookings->creditPayment(
            $actor,
            $booking,
            $request->payload(),
            $request->proofs(),
        );

        return BookingResource::make($this->loadBooking($booking));
    }

    public function destroy(Booking $booking): Response
    {
        $this->bookings->cancel($booking);

        return response()->noContent();
    }

    private function loadBooking(Booking $booking): Booking
    {
        return $booking->loadMissing([
            'customer.nominee.documents',
            'agent',
            'unit',
            'subtype',
            'floor',
            'creator',
            'documents',
        ]);
    }
}
