<?php

namespace App\Jobs;

use App\Models\Booking;
use App\Models\BookingStatus;
use App\Services\FcmService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\DB;

/**
 * A driver has 40 seconds to Accept or Reject a newly-assigned job (see
 * BookingController@accept/@reject) — dispatched with a matching delay the
 * moment a booking becomes Pending. If the driver still hasn't responded by
 * the time this runs, the assignment is stale: bounce the booking back to
 * Unassigned so it's available for reassignment. bookings:expire-pending
 * covers the same ground every minute as a backstop for whenever the queue
 * worker isn't running, so this job silently no-ops if it's already too
 * late to matter (status changed, or the booking is gone).
 */
class ExpireBookingAssignment implements ShouldQueue
{
    use Queueable;

    public function __construct(private readonly int $bookingId) {}

    public function handle(FcmService $fcm): void
    {
        $booking = Booking::find($this->bookingId);

        if (! $booking || $booking->status?->name !== 'Pending') {
            return;
        }

        $unassignedId = BookingStatus::where('name', 'Unassigned')->value('id');
        $driverUser = $booking->driver?->user;

        DB::transaction(function () use ($booking, $unassignedId) {
            $booking->update(['status_id' => $unassignedId, 'driver_id' => null]);
            $booking->statusHistory()->create([
                'status_id' => $unassignedId,
                'note' => 'Auto-expired: driver did not respond within 40 seconds.',
            ]);
        });

        if ($driverUser) {
            $fcm->sendToOwner($driverUser, 'Job expired', 'Booking '.$booking->booking_number.' was not accepted in time and has been reassigned.', [
                'type' => 'booking_assignment_expired', 'booking_id' => (string) $booking->id,
            ]);
        }
    }
}
