import msvcrt
import sys

items = []
diners = []

# ANSI color codes for terminal output
GREEN = "\033[1;92m"
RESET = "\033[0m"

def colored_input(prompt):
	print(prompt, end="", flush=True)
	print(GREEN, end="", flush=True)

	characters = []
	while True:
		char = msvcrt.getwch()

		if char == "\x03":
			print(RESET, end="", flush=True)
			raise KeyboardInterrupt

		if char in ("\r", "\n"):
			print(RESET)
			return "".join(characters)

		if char == "\x08":
			if characters:
				characters.pop()
				sys.stdout.write("\b \b")
				sys.stdout.flush()
			continue

		if char in ("\x00", "\xe0"):
			msvcrt.getwch()
			continue

		characters.append(char)
		sys.stdout.write(char)
		sys.stdout.flush()

def section(title):
	print("\n" + "=" * 60)
	print(title)
	print("=" * 60)


def choose_sharers(diners):
	# Choose one or more diners by number (e.g. 1 or 1,3).
	while True:
		print("Who is sharing this item?")
		for i, diner in enumerate(diners, start=1):
			print(f"{i}. {diner}")
		raw = colored_input("Choose diner number(s), comma-separated: ").strip()

		if raw == "":
			print("Please choose at least one diner.")
			continue

		parts = [part.strip() for part in raw.split(",") if part.strip() != ""]
		if not parts:
			print("Please choose at least one diner.")
			continue

		indexes = []
		valid = True
		for part in parts:
			if not part.isdigit():
				valid = False
				break
			index = int(part)
			if index < 1 or index > len(diners):
				valid = False
				break
			if index not in indexes:
				indexes.append(index)

		if not valid:
			print("Enter valid diner numbers from the list (example: 1,3).")
			continue

		return [diners[index - 1] for index in indexes]


section("DINER SETUP")
print("Enter diner names first.")
print("Press Enter on a blank name when done.")

while True:
	name = colored_input("Diner name: ").strip()
	if name == "":
		break
	if name.lower() in (d.lower() for d in diners):
		print("That diner is already on the list.")
		continue
	diners.append(name)
	print(f"Added diner: {name}")

if not diners:
	print("No diners entered.")
	raise SystemExit

section("ITEM ENTRY")
print("Enter each item name and price.")
print("Press Enter on a blank item name when done.")

item_number = 1
while True:
	print(f"\nItem #{item_number}")
	print("-" * 20)
	item_name = colored_input("Item name: ").strip()
	if item_name == "":
		break

	while True:
		is_appetizer = colored_input("Is this an appetizer for the whole table? (y/n): ").strip().lower()
		if is_appetizer in ("y", "yes", "n", "no"):
			break
		print("Please enter y or n.")

	if is_appetizer in ("y", "yes"):
		sharers = list(diners)
		category = "Appetizer"
	else:
		sharers = choose_sharers(diners)
		if len(sharers) > 1:
			category = "Shared"
		else:
			category = "Individual"

	while True:
		entry = colored_input(f"Price for {item_name}: ").strip()
		try:
			price = float(entry)
			if price < 0:
				print("Price cannot be negative.")
				continue
			items.append({"name": item_name, "price": price, "sharers": sharers, "category": category})
			if category == "Appetizer":
				print(f"Added: {item_name} (${price:.2f}) as table appetizer")
			else:
				print(f"Added: {item_name} (${price:.2f}) shared by {', '.join(sharers)}")
			item_number += 1
			break
		except ValueError:
			print("Please enter a valid number.")

if not items:
	print("No items entered.")
else:
	section("TIP")
	subtotal = sum(item["price"] for item in items)
	print(f"Current subtotal: ${subtotal:.2f}")

	while True:
		tip_input = colored_input("What percent tip would you like to leave? ").strip().replace("%", "")
		try:
			tip_percent = float(tip_input)
			if tip_percent < 0:
				print("Tip percent cannot be negative.")
				continue
			break
		except ValueError:
			print("Please enter a valid tip percentage.")

	tip_amount = round(subtotal * (tip_percent / 100))
	total_bill = subtotal + tip_amount

	section("ITEMIZED BILL")
	for item in items:
		shared_by = ", ".join(item["sharers"])
		if item["category"] == "Appetizer":
			print(f"- {item['name']}: ${item['price']:.2f} (Appetizer, split across table)")
		else:
			print(f"- {item['name']}: ${item['price']:.2f} (Shared by: {shared_by})")

	# Calculate per-person subtotals
	person_subtotals = {person: 0 for person in diners}
	for item in items:
		share_cost = item["price"] / len(item["sharers"])
		for person in item["sharers"]:
			person_subtotals[person] += share_cost

	# Calculate per-person tip share (proportional)
	person_tips = {}
	for person, person_subtotal in person_subtotals.items():
		if subtotal > 0:
			person_tips[person] = tip_amount * (person_subtotal / subtotal)
		else:
			person_tips[person] = 0

	section("PER-PERSON TOTALS")
	for person in person_subtotals:
		owed = person_subtotals[person] + person_tips[person]
		print(f"{person}: ${owed:.2f} (Subtotal: ${person_subtotals[person]:.2f}, Tip: ${person_tips[person]:.2f})")

	section("FINAL TOTAL")
	print(f"Check subtotal: ${subtotal:.2f}")
	print(f"Tip ({tip_percent:.1f}%): ${tip_amount:.2f}")
	print(f"Final bill: ${total_bill:.2f}")
