"""
Hotel Check-In Logic Gate — a runnable companion to Chapter 1 (The Dream of
Thinking Machines).

This is the Boolean logic engine sketched in Figure 1.6: three true-or-false
facts about a guest combine into a check-in decision. Nothing here is
approximate or probabilistic — Boole's insight was that once a decision can
be reduced to true/false facts and a rule for combining them, a machine can
execute it exactly, every time, with no judgment call left to make.

Run it:   python3 hotel_checkin_logic.py
"""

from dataclasses import dataclass


@dataclass
class GuestState:
    guest_id: str
    paid: bool
    booking_exists: bool
    room_available: bool


def decide_checkin(state: GuestState) -> tuple:
    """Boolean rule: allow check-in only if every hard fact is true."""
    facts = {
        "paid": state.paid,
        "booking_exists": state.booking_exists,
        "room_available": state.room_available,
    }
    allow = all(facts.values())
    failing = [name for name, value in facts.items() if not value]
    return (allow, failing)


GUESTS = [
    GuestState("G-1", paid=True, booking_exists=True, room_available=True),
    GuestState("G-2", paid=False, booking_exists=True, room_available=True),
    GuestState("G-3", paid=True, booking_exists=True, room_available=False),
    GuestState("G-4", paid=True, booking_exists=False, room_available=True),
    GuestState("G-5", paid=False, booking_exists=False, room_available=False),
]


def main():
    print(f"{'GUEST':<8}{'DECISION':<20}{'FAILING FACTS'}")
    print("-" * 55)
    for guest in GUESTS:
        allow, failing = decide_checkin(guest)
        decision = "ALLOW CHECK-IN" if allow else "ESCALATE / DENY"
        reasons = ", ".join(failing) if failing else "none"
        print(f"{guest.guest_id:<8}{decision:<20}{reasons}")

    print("\nThe rule never changes. Only the facts do.")
    print("That is the entire idea behind Boolean logic as a computing substrate.")


if __name__ == "__main__":
    main()
