import cmd_habit_tracker.db.db_operations as db
import cmd_habit_tracker.c_logging.logger as log
from cmd_habit_tracker.utils.aux import get_new_habit, set_test_mode, get_goal, get_question, get_date, get_choice, get_year_and_month
from cmd_habit_tracker.helper_functions import track_date, get_table_dict_of_records, tabulate
from cmd_habit_tracker.db.models import Habit
import cmd_habit_tracker.utils.data as data
import cmd_habit_tracker.exceptions.exceptions as exceptions
from cmd_habit_tracker.ai.ai_methods import generate_single_habit, answer_question_for_app_use
import os

def quick_test():
    # add()
    # print(db.get_habit_by_title('mama'))
    # generate_single_habit("I am suffering from bad sleeping, can you suggest me a habit to track so I can recover.")
    # reset()
    pass

################################ Main wrappers ################################

def welcome():
    print("Welcome to your personal habit tracker")

def initialize_logger():
    log.start_logger()
    log.set_level_debug()

def initialize_db():
    db.create_tables()

def close_app():
    exit(0)

def reset():
    """Removes database and initializes it again"""
    initialize()
    clear_storage()
    initialize()

def clear_storage():
    db.drop_db()

def refresh():
    db.refresh_tracker_table()

def initialize():
    try:
        # the following two lines are important in case the program was executed from a directory other than the one of the project
        dir_path = os.path.dirname(os.path.realpath(__file__))
        os.chdir(dir_path)
        initialize_logger()
        initialize_db()
    except Exception as e:
        print(e)
        close_app()

def initialize_for_testing():
    try:
        dir_path = os.path.dirname(os.path.realpath(__file__))
        os.chdir(dir_path)
        set_test_mode()
        initialize_db()
        clear_storage()
        initialize_logger()
        initialize_db()
    except Exception as e:
        print(e)
        close_app()

################################ Commands wrappers ################################
def add():
    """a function to add a new habit"""
    # ask the user to insert values
    new_habit = get_new_habit()
    try:
        db.add_habit(new_habit)
    except exceptions.DuplicateHabit as e:
        print(e)
    except Exception as e:
        print(e)

def help():
    """Prints all the possible commands with their usage"""
    print()
    for command_usage in data.Commands.get_commands().values():
        print(command_usage + "\n")


def progress():
    """Prints the progress of all habits for the specified month"""
    year, month = get_year_and_month()
    print()
    table_dict1, table_dict2 = get_table_dict_of_records(records=db.get_tracked_info_by_month(year=year, month=month), year=year, month=month)
    print(tabulate(table_dict1, headers = 'keys', tablefmt = 'rounded_grid' ) )
    print(tabulate(table_dict2, headers = 'keys', tablefmt = 'rounded_grid' ) )

def habits():
    [print(habit) for habit in db.get_all_habits()]


def generate():
    generate_new = 1
    while generate_new:
        goal = get_goal()
        suggested_habit_str = generate_single_habit(goal)
        suggested_habit = Habit()
        suggested_habit.set_habit_from_str(suggested_habit_str)
        print(suggested_habit)
        print()
        print("Do you want to add this habit?")
        answer = input()
        if answer.strip().lower() in ['yes', 'y']:
            try:
                db.add_habit(suggested_habit.get_dict_column_value())
            except Exception as e:
                print(e)
                return
            print("Habit was added. Run 'habits' to see it")
            generate_new = 0
        else:
            print("Habit was not added, do you want to generate a new habit?")
            answer = input()
            if answer.strip().lower() in ['yes', 'y']:
                generate_new = 1
            else:
                generate_new = 0

def delete():
    """Deletes a habit"""
    available_habits = db.get_all_habits()
    print("Kindly choose the habit you want to delete:")
    options = [habit.title for habit in available_habits]+["Cancel"]
    choice = get_choice(options)
    if choice == len(options):
        print("No habits were deleted.")
        return
    db.delete_habit(available_habits[choice-1].id)
    print("Habit deleted successfully!")

def docs():
    question  = get_question()
    print(answer_question_for_app_use(question))

def command_not_found():
    print("Command not found. You can run `help` for more information.")
    print("")
    print("Do you have a specific question?")
    answer = input("Your answer (yes/no): ")
    if answer.strip().lower() in data.YES_ANSWERS:
        question  = input("\nWhat are you looking for?\nType here: ")
        print(answer_question_for_app_use(question))


def automatic_track():
    """Runs upon starting the program - let's user track todays info"""
    date=data.Date.get_yesterday()
    habits_count = len(db.get_all_habits())
    if habits_count == 0:
        print("Add habits to be tracked!\n")
    elif len(db.get_all_track_info_of_date(date.string_format())) != habits_count :
        track_date(date)
    else:
        print("Well done! Yesterday's tracking info were provided.\n")


def track():
    print("Choose an option:")
    choice = get_choice([
        "Insert tracking info for yesterday",
        "Insert tracking info for a specific date"
    ])
    date = get_date() if choice == 2 else data.Date.get_yesterday()
    if date.in_future():
        print("Please enter a valid date (Not in the future)")
    else:
        try:
            track_date(date=date)
        except Exception as e:
            print(e)

def clear():
    os.system("clear")

################################ Command handlers ################################

def get_command() -> str:
    """must be one of predefined commands, otherwise ask again"""
    command = input(">>> ").strip()
    while len(command) == 0:
        command = input("\n>>> ")
    main_command = command.split()[0]
    while main_command not in data.Commands.get_commands().keys():
        command_not_found()
        command = input(">>> ").strip()
        while len(command) == 0:
            command = input("\n>>> ")
        main_command = command.split()[0]

    return main_command

def execute_command(command: str):
    """
    parameters:
        command: a string containing the whole command
    """

    if command == data.Commands.ADD.value:
        add()
    elif command == data.Commands.TRACK.value:
        track()
    elif command == data.Commands.ARCHIVE.value:
        pass
    elif command == data.Commands.DELETE.value:
        delete()
    elif command == data.Commands.HABITS.value:
        habits()
    elif command == data.Commands.HELP.value:
        help()
    elif command == data.Commands.PROGRESS.value:
        progress()
    elif command == data.Commands.UPDATE.value:
        pass
    elif command == data.Commands.EXIT.value:
        close_app()
    elif command == data.Commands.GENERATE.value:
        generate()
    elif command == data.Commands.DOCS.value:
        docs()
    elif command == data.Commands.CLEAR.value:
        clear()
    else:
        return
