<?php

namespace Modules\Booking\Policies;

use App\Models\User;
use Modules\Booking\Enums\BookingStatus;
use Modules\Booking\Models\Booking;

class BookingPolicy
{
    /**
     * Listing is always scoped to the caller's own bookings at the query
     * level (BookingController::index) — any authenticated user may look at
     * their own list. Staff get the full, unscoped list via the Filament
     * BookingResource (T4.7), not this gate.
     */
    public function viewAny(User $user): bool
    {
        return true;
    }

    /**
     * A booking's owner may always view it; anyone else needs the
     * view_bookings permission (admin/support roles).
     */
    public function view(User $user, Booking $booking): bool
    {
        return $user->id === $booking->user_id || $user->can('view_bookings');
    }

    public function create(User $user): bool
    {
        return true;
    }

    /**
     * A booking's owner may cancel their own pending_payment booking; staff
     * can cancel any pending_payment booking via manage_bookings. Cancelling
     * a confirmed (paid) booking refunds it (CancelBookingAction, T5.12) —
     * that's the same authorization boundary as refund(), staff only
     * (domain.md §8: refund initiation is a staff-only operation).
     */
    public function cancel(User $user, Booking $booking): bool
    {
        if ($booking->status === BookingStatus::Confirmed) {
            return $user->can('process_refunds');
        }

        return $user->id === $booking->user_id || $user->can('manage_bookings');
    }

    public function refund(User $user, mixed $booking): bool
    {
        return $user->can('process_refunds');
    }

    /**
     * A booking's owner may pay for their own (still pending_payment only —
     * enforced by InitiatePaymentAction, not here); staff can initiate on
     * behalf of a customer via manage_bookings.
     */
    public function pay(User $user, Booking $booking): bool
    {
        return $user->id === $booking->user_id || $user->can('manage_bookings');
    }

    /**
     * Staff-only, and only once a booking is terminal (cancelled/expired) —
     * a pending_payment or confirmed (paid) booking must never be deleted
     * out from under an in-flight payment/refund flow. Soft delete only
     * (Booking uses SoftDeletes); Payment/Refund history stays intact.
     */
    public function delete(User $user, Booking $booking): bool
    {
        return in_array($booking->status, [BookingStatus::Cancelled, BookingStatus::Expired], true)
            && $user->can('manage_bookings');
    }

    /**
     * Staff-only. No status restriction beyond RestoreAction's own built-in
     * "only if trashed" visibility — a booking's status doesn't change on
     * delete, so whatever made it deletable still holds once restored.
     */
    public function restore(User $user, Booking $booking): bool
    {
        return $user->can('manage_bookings');
    }
}
