namespace Baya.Domain.Entities.Booking;

/// <summary>
/// The allowed status machine for <see cref="Booking"/>. Every transition is validated here so an illegal
/// edge is a clean conflict (never a silent overwrite) and terminal states have no outgoing edge. A CHECK
/// constraint backs the terminal states in the DB; this table is the authoritative guard consulted by
/// <c>TransitionBookingStatusCommand</c> and the internal capture/check-in/check-out flows. No transition
/// may contradict EVV — that extra invariant is enforced by the handlers, not encodable here.
/// </summary>
public static class BookingTransitions
{
    private static readonly IReadOnlyDictionary<string, IReadOnlyCollection<string>> Allowed =
        new Dictionary<string, IReadOnlyCollection<string>>
        {
            [BookingStatus.PendingPayment] = [BookingStatus.Confirmed, BookingStatus.Cancelled],
            [BookingStatus.Confirmed] = [BookingStatus.InProgress, BookingStatus.Cancelled],
            [BookingStatus.InProgress] = [BookingStatus.Completed, BookingStatus.Cancelled],
            [BookingStatus.Completed] = [BookingStatus.Disputed, BookingStatus.Closed],
            [BookingStatus.Disputed] = [BookingStatus.Closed],
            // Terminal states — no outgoing edges.
            [BookingStatus.Closed] = [],
            [BookingStatus.Cancelled] = []
        };

    public static bool CanTransition(string from, string to)
        => Allowed.TryGetValue(from, out var targets) && targets.Contains(to);
}
