#!/usr/bin/env python

import argparse
import sys
import textwrap

from smartgpt import Mode, Settings, SmartGPT, Verbosity
from smartgpt.user_profile import SETTINGS_PATH
from smartgpt.util import color_text


def main(args: argparse.Namespace) -> None:
    if args.print_settings_file:
        print_settings_file_and_exit()

    settings = override_settings_with_CLI_args(Settings.load(SETTINGS_PATH), args)

    print_settings(settings)

    app = SmartGPT.create(settings)
    app.repl()


def print_settings_file_and_exit() -> None:
    print(f"The contents of {SETTINGS_PATH}:\n")
    print(color_text(open(SETTINGS_PATH).read(), color="cyan"))
    sys.exit()


def print_settings(settings: Settings) -> None:
    print(settings)


def override_settings_with_CLI_args(
    settings: Settings, args: argparse.Namespace
) -> Settings:
    """Overwrites settings attributes with those specified in CLI"""
    if args.mode is not None:
        settings.mode = args.mode
    if args.verbosity:
        settings.verbosity = args.verbosity
    if args.model:
        settings.model = args.model

    return settings


class CustomHelpFormatter(argparse.RawTextHelpFormatter):
    def _split_lines(self, text, width):
        lines = text.splitlines()
        wrapped_lines = [textwrap.wrap(line, 60) if line else [""] for line in lines]
        # flatten list of lists
        return [item for sublist in wrapped_lines for item in sublist]


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        formatter_class=CustomHelpFormatter,
        description=(
            "  ____                       _    ____ ____ _____ \n"
            " / ___| _ __ ___   __ _ _ __| |_ / ___|  _ \_   _|\n"
            " \___ \| '_ ` _ \ / _` | '__| __| |  _| |_) || |  \n"
            "  ___) | | | | | | (_| | |  | |_| |_| |  __/ | |  \n"
            " |____/|_| |_| |_|\__,_|_|   \__|\____|_|    |_|  \n"
            "\n"
            "YouTube: https://www.youtube.com/watch?v=wVzuvf9D9BU\n"
            "Github: https://github.com/ekiefl/smartgpt\n"
            "\n"
            f"NOTE: The settings file for SmartGPT can be found at {SETTINGS_PATH}.\n"
            "All arguments passed through this CLI override the values found in the "
            "settings file."
        ),
    )
    parser.add_argument(
        "--mode",
        required=False,
        choices=[mode.value for mode in Mode],
        help=(
            "This sets the mode of operation for interactive sessions with the AI. The "
            "interaction modes determine how the AI processes user's prompts and generates "
            "responses.\n"
            "\n"
            "Here are the available modes:\n"
            "\n"
            '1. `resolver`: This is the "SmartGPT" mode. Multiple agents, known as '
            "generators, create potential responses to the user's prompt. Then, an agent "
            "called the researcher scrutinizes these generated responses, pointing out "
            "strengths and weaknesses. Finally, the resolver agent considers the researcher's "
            "analysis, selects the best response, and then tries to improve it based on the "
            "researcher's analysis.\n"
            "\n"
            "2. `step_by_step`: In this mode, the user's prompts are flavored with some "
            "additional chain-of-thought prompting to encourage a more detailed and "
            "step-by-step response. If your prompt is {prompt}, step_by_step modifies your "
            "prompt to become, \"Question: {prompt}. Answer: Let's work this out in a step by "
            'step way to be sure we have the right answer."\n'
            "\n"
            "3. `zero_shot`: In this mode, user's prompts are sent directly to the AI model. The "
            "model then generates and returns a response to the prompt without any additional "
            "intervention.\n"
            "\n"
        ),
    )
    parser.add_argument(
        "--verbosity",
        required=False,
        choices=[verbosity.value for verbosity in Verbosity],
        help=(
            "Sets the amount that shows up on your screen.\n"
            "\n"
            "1. `none`: Only the final response shows.\n"
            "\n"
            "2. `some`: Status updates are provided so you know where in the response "
            "creation SmartGPT is at.\n"
            "\n"
            "3. `all`: Status updates are provided and all intermediary responses are shown. "
            "Additionally, you see which response the resolver agent liked most and why (this "
            "is suppressed with `some`).\n"
        ),
    )
    parser.add_argument(
        "--model",
        required=False,
        help=("The name of the model you want (e.g. gpt-4, gpt-3.5-turbo)"),
    )
    parser.add_argument(
        "--print-settings-file",
        action="store_true",
        help=(
            "Prints the settings file and location. Modify this file to change the "
            "default behavior."
        ),
    )
    args = parser.parse_args()

    main(args)
