import Arithmetic
import Exponents
import Trig
from dotenv import load_dotenv
import sys
import os
import curses
import Utilities

def get_number(prompt):
    while True:
        try:
            return float(input(prompt))
        except ValueError:
            print("Please enter a valid number.")

def main_menu(stdscr):
    curses.curs_set(0)
    current = 0
    offset = 0

    while True:
        stdscr.clear()
        height, width = stdscr.getmaxyx()

        stdscr.addstr(0, 0, "Pick a Function", curses.A_BOLD)
        stdscr.addstr(1, 0, "—" * 30)

        visible_height = height - 4
        visible_options = main_options[offset:offset + visible_height]

        for i, opt in enumerate(visible_options):
            y = i + 4
            index = i + offset

            text = f"> {opt} <" if index == current else f"  {opt}"
            stdscr.addstr(
                y, 0,
                text[:width-1],
                curses.A_REVERSE if index == current else 0
            )

        key = stdscr.getch()

        if key == curses.KEY_UP:
            current = (current - 1) % len(main_options)
        elif key == curses.KEY_DOWN:
            current = (current + 1) % len(main_options)
        elif key in (10, 13):
            return main_options[current]

        if current < offset:
            offset = current
        elif current >= offset + visible_height:
            offset = current - visible_height + 1

def env_menu(stdscr):
    curses.curs_set(0)
    current = 0
    offset = 0

    while True:
        stdscr.clear()
        height, width = stdscr.getmaxyx()

        stdscr.addstr(0, 0, "Import Numbers from env file?", curses.A_BOLD)
        stdscr.addstr(1, 0, "—" * 30)

        visible_height = height - 4
        visible_options = env_options[offset:offset + visible_height]

        for i, opt in enumerate(visible_options):
            y = i + 4
            index = i + offset

            text = f"> {opt} <" if index == current else f"  {opt}"
            stdscr.addstr(
                y, 0,
                text[:width-1],
                curses.A_REVERSE if index == current else 0
            )

        key = stdscr.getch()

        if key == curses.KEY_UP:
            current = (current - 1) % len(env_options)
        elif key == curses.KEY_DOWN:
            current = (current + 1) % len(env_options)
        elif key in (10, 13):
            return env_options[current]

        if current < offset:
            offset = current
        elif current >= offset + visible_height:
            offset = current - visible_height + 1
env_options = ["Y", "N"]
env = curses.wrapper(env_menu)
if env == "Y":
    load_dotenv()
    raw_A = os.getenv("A")
    raw_B = os.getenv("B")

    if raw_A is None or raw_B is None:
        print("❌ Missing A or B in ENV")
        sys.exit(1)

    A = float(raw_A)
    B = float(raw_B)

else:
    A = get_number("Type the 1st number ")
    B = get_number("Type the 2nd number ")

operations = {
    "+": {"func": Arithmetic.add, "args": 2},
    "-": {"func": Arithmetic.sub, "args": 2},
    "x": {"func": Arithmetic.multiply, "args": 2},
    "÷": {"func": Arithmetic.divide, "args": 2},
    "^": {"func": Exponents.power, "args":2},
    "root": {"func": Exponents.root, "args":2},
    "Fac(!)": {"func": Exponents.factorial, "args": 1},
    "sin": {"func": Trig.sin, "args": 1},
    "cos": {"func": Trig.cos, "args": 1},
    "tan": {"func": Trig.tan, "args": 1},
    "csc": {"func": Trig.csc, "args": 1},
    "sec": {"func": Trig.sec, "args": 1},
    "cot": {"func": Trig.cot, "args": 1},
    "arcsin": {"func": Trig.arcsin, "args": 1},
    "arccos": {"func": Trig.arccos, "args": 1},
    "arctan": {"func": Trig.arctan, "args": 1},
    "arccsc": {"func": Trig.arccsc, "args": 1},
    "arcsec": {"func": Trig.arcsec, "args": 1},
    "arccot": {"func": Trig.arccot, "args": 1},
    "sinh": {"func": Trig.sinh, "args": 1},
    "cosh": {"func": Trig.cosh, "args": 1},
    "tanh": {"func": Trig.tanh, "args": 1},
    "csch": {"func": Trig.csch, "args": 1},
    "sech": {"func": Trig.sech, "args": 1},
    "coth": {"func": Trig.coth, "args": 1},
    "arcsinh": {"func": Trig.arcsinh, "args": 1},
    "arccosh": {"func": Trig.arccosh, "args": 1},
    "arctanh": {"func": Trig.arctanh, "args": 1},
}
main_options = list(operations.keys())
inp = curses.wrapper(main_menu)
op = operations[inp]
func = op["func"]
arg_count = op["args"]

if arg_count == 2:
    try:
        result = func(A, B)
        print(result)
    except ZeroDivisionError as e:
        print(e)
    except Exception as e:
        print(f"Unexpected error: {e}")
else:
    try:
        result = func(A)
        print(result)
    except Exception as e:
        print(f"Unexpected error: {e}")