# Throw your own errors
# raise — when you decide something is wrong

# ─────────────────────────────────────────────
# Your first raise
# ─────────────────────────────────────────────

def get_age(age):
    if age < 0:
        raise ValueError("Age cannot be negative.")
    return age

try:
    print(get_age(-5))
except ValueError as e:
    print(e)    # Age cannot be negative.

# raise stops the function immediately
# as e gives you access to the error message

# ─────────────────────────────────────────────
# Validating input in a function
# ─────────────────────────────────────────────

def calculate_bmi(weight, height):
    if weight <= 0:
        raise ValueError("Weight must be greater than zero.")
    if height <= 0:
        raise ValueError("Height must be greater than zero.")
    return weight / height ** 2

try:
    bmi = calculate_bmi(70, 0)
except ValueError as e:
    print(e)    # Height must be greater than zero.

# bad input never reaches the formula

# ─────────────────────────────────────────────
# raise inside a loop
# ─────────────────────────────────────────────

def get_positive_number():
    while True:
        try:
            number = int(input("Enter a positive number: "))
            if number <= 0:
                raise ValueError("Must be positive.")
            return number
        except ValueError as e:
            print(e)

result = get_positive_number()
print(f"Got: {result}")

# loop keeps asking
# bad type or negative — both caught and reported
# only valid positive number gets through

# ─────────────────────────────────────────────
# Quick reference
# ─────────────────────────────────────────────

# raise ValueError("message")   — throw an error deliberately
# raise TypeError("message")    — wrong type
# except ValueError as e:       — catch and access the message
# print(e)                      — print the error message
#
# raise stops the function immediately
# always pair raise with try / except — or program crashes
