import random
# The random module is used to simulate randomness in customers
# (what they want to buy and how much money they have)


# =========================
# Customer class
# =========================
class Customer:
    def __init__(self, item_list):
        """
        Each customer:
        - randomly chooses one item they want to buy
        - has a random budget
        """

        # Choose exactly one random item from the available inventory items
        self.wish = random.sample(list(item_list), 1)[0]

        # Give the customer a random budget between 0.5 and 5 currency units
        self.budget = random.uniform(0.5, 5)


# =========================
# Inventory class
# =========================
class Inventory:
    def __init__(self):
        """
        The inventory stores:
        - how many items are available
        - how much each item costs
        """
        self.itemlist = {"coffee": 0, "milk": 5}
        self.pricelist = {"coffee": 1.99, "milk": 0.99}

    def check_item_availability(self, item, q):
        """
        Check if at least q units of an item are available
        """
        return self.itemlist[item] >= q

    def add_items(self, item, q):
        """
        Add q units of an item to the inventory
        """
        try:
            self.itemlist[item] = self.itemlist[item] + q
        except:
            print("Item not found in inventory")

    def remove_items(self, item, q):
        """
        Remove q units of an item from the inventory
        """
        self.itemlist[item] = self.itemlist[item] - q

    def print_inventory(self):
        """
        Print the current inventory in a readable format
        """
        print("The inventory is:")
        for key, value in self.itemlist.items():
            print("\t", key.title(), value)

    def check_buying_price(self, item, q):
        """
        Calculate how much the shop has to pay to buy q units of an item
        """
        bp = round(self.pricelist[item] * q, 2)
        return bp


# =========================
# CoffeeShop class
# =========================
class CoffeeShop:
    def __init__(self):
        """
        This class controls the whole game logic
        """
        self.funds = 30
        self.inventory = Inventory()
        self.manager_level = 1
        self.open = False
        self.day = 1

        # Daily statistics
        self.items_sold = {}
        self.cash_earned = 0

    def open_shop(self):
        """
        Open the shop for the day
        """
        self.open = True

    def close_shop(self):
        """
        Close the shop
        """
        self.open = False

    def shop_open_closed(self):
        """
        Return a string describing whether the shop is open
        """
        if self.open == False:
            return "Closed"
        else:
            return "Open"

    def earn_funds(self, amount):
        """
        Add money to the shop funds
        """
        self.funds = self.funds + amount

    def spend_funds(self, amount):
        """
        Subtract money from the shop funds
        """
        self.funds = self.funds - amount

    def print_funds(self):
        """
        Print current shop funds
        """
        print("The current funds of the shop are:", self.funds)

    def calculate_selling_price(self, item, q):
        """
        Calculate the selling price for an item.
        The manager level increases the price by 10% per level.
        """
        sp = round(
            self.inventory.pricelist[item] * (1 + self.manager_level * 0.1) * q,
            2
        )
        return sp

    def status(self):
        """
        Print the current status of the shop
        """
        print("----------------------------------")
        print("This is day:", self.day)
        print("The shop is:", self.shop_open_closed())
        self.print_funds()
        self.inventory.print_inventory()
        print("----------------------------------")

    def buy_inventory(self):
        """
        Allow the player to buy items for the shop inventory
        """
        query_item = input("What would you like to buy for the shop inventory:")

        # Check if the item exists
        if query_item in self.inventory.itemlist.keys():
            query_amount = int(
                input(
                    "How many " + query_item +
                    " would you like to buy for the shop inventory:"
                )
            )
        else:
            print("Item not found.")
            return

        # Only continue if an amount was entered
        if query_amount:
            bp = self.inventory.check_buying_price(query_item, query_amount)

            # Check if the shop has enough money
            if bp <= self.funds:
                self.spend_funds(bp)
                self.inventory.add_items(query_item, query_amount)
                print("Bought", query_amount, "units of", query_item, "for", bp)
            else:
                print("Funds not enough.")

    def menu(self):
        """
        Main menu shown to the player
        """
        print("\n")
        print("====================================")
        print("1. View Shop Status")
        print("2. Buy items for inventory")
        print("3. Open Shop and complete day")
        print("4. ...")
        print("5. Quit Game")
        print("====================================")

        s = input("Enter your selection:")

        if s == "1":
            my_shop.status()
        elif s == "2":
            my_shop.buy_inventory()
        elif s == "3":
            my_shop.interact_with_all_customers()
            my_shop.progress_day()
            my_shop.daily_summary()
        elif s == "5":
            quit()

    def progress_day(self):
        """
        Move to the next day
        """
        self.day = self.day + 1

    def daily_summary(self):
        """
        Print a summary of what happened during the day
        """
        print("+++++++++ DAY FINISHED")
        print("The shop income today was", self.cash_earned, ".")
        print("The shop sold the following items:")
        for key, value in self.items_sold.items():
            print("\t", key.title(), value)
        print("+++++++++")

    def customer_count(self):
        """
        Determine how many customers visit today.
        The number increases with the day.
        """
        return self.day + random.randint(1, 5)

    def generate_customers_for_day(self):
        """
        Create all customers for the current day
        """
        customers = []
        count = self.customer_count()

        for x in range(0, count):
            customers.append(Customer(self.inventory.itemlist.keys()))

        return customers

    def interact_with_all_customers(self):
        """
        Simulate all customers visiting the shop for one day
        """
        self.items_sold = {}
        self.cash_earned = 0

        # Generate today's customers
        customers = self.generate_customers_for_day()

        for customer in customers:

            # Check if the desired item is available
            if self.inventory.check_item_availability(customer.wish, 1):

                price = self.calculate_selling_price(customer.wish, 1)

                # Check if the customer can afford the item
                if price <= customer.budget:
                    self.earn_funds(price)
                    self.cash_earned = round(self.cash_earned + price, 2)
                    self.inventory.remove_items(customer.wish, 1)

                    # Track sold items
                    if customer.wish in self.items_sold:
                        self.items_sold[customer.wish] += 1
                    else:
                        self.items_sold[customer.wish] = 1

                    print("Sold", 1, customer.wish, "to customer for", price)
                else:
                    print("The customer could not afford the", customer.wish, ".")
            else:
                print("The wish for", customer.wish, "could not be fulfilled.")


# =========================
# Game start
# =========================
my_shop = CoffeeShop()

# Main game loop
while True:
    my_shop.menu()
