from .vault import Vault
from getpass import getpass
import sys
import logging
import argparse
import os

from colorama import Fore, just_fix_windows_console

just_fix_windows_console()


def config(args):
    password = getpass("Vault Password: ")

    config_folder = os.path.join(
        os.path.expanduser("~"), ".config", "bw_secrets")
    if not os.path.exists(config_folder):
        logging.info(f"creating folder {config_folder}")
        os.makedirs(config_folder)

    password_file = os.path.join(config_folder, "pass.key")
    if os.path.exists(password_file):
        os.remove(password_file)
    with open(password_file, "w") as f:
        f.write(password)
    os.chmod(password_file, 0o400)


def run(args):
    folder = args.folder
    command = args.command

    default_password_file = os.path.join(
        os.path.expanduser("~"), ".config", "bw_secrets", "pass.key")
    if not (os.path.exists(default_password_file) and os.path.isfile(default_password_file)) and args.password_file is None:
        logging.error(
            f"{Fore.RED}password file not configured or passed. please pass a password file or create one with `bwsp config`{Fore.RESET}")
        sys.exit(1)

    logging.info("injecting secrets into environment")

    vault = Vault(args.password_file)

    # check status
    if not (status := vault.get_vault_status()):
        sys.exit(1)
    if status == "unauthenticated":
        logging.error(
            f"{Fore.RED}bw cli status is 'unauthenticated', please log in using the cli and then try again")
        sys.exit(1)

    if status == "locked":
        if vault.unlock_vault() != True:
            sys.exit(1)
        logging.debug("vault unlocked")

    if not args.no_sync:
        if vault.sync_vault() == False:
            if args.lock:
                vault.lock_vault()
            sys.exit(1)
        logging.debug("vault synced")

    if not (items := vault.get_item_list_from_folder(folder)):
        if args.lock:
            vault.lock_vault()
        sys.exit(1)

    if args.lock:
        if vault.lock_vault() != True:
            sys.exit(1)
        logging.debug("vault locked")

    logging.debug("injecting environmental variables")
    for key, val in items.items():
        os.environ[key] = val
    return_code = os.system(command) % 255
    logging.debug(f"command exited with code {return_code}")


def main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-d", "--debug", help="enable debug logging", action="store_true"
    )

    subparsers = parser.add_subparsers(help="command to run", dest="cmd")

    # config parser
    subparsers.add_parser(
        "config", help="first-time setup"
    )

    # run parser - needs folder id/name
    # and a command to run after injection
    run_parser = subparsers.add_parser(
        "run", help="run command with env variable injection"
    )

    run_parser.add_argument(
        "folder", help="folder for pulling secrets from. can either be folder-id or folder name")
    run_parser.add_argument(
        "command", help="command to run after injecting the enviromental variables"
    )
    run_parser.add_argument(
        "-l", "--lock", help="lock vault after running", action="store_true"
    )
    run_parser.add_argument(
        "-p", "--password-file", help="path to password file (default ~/.config/bw_secrets/pass.key)"
    )
    run_parser.add_argument(
        "-n", "--no-sync", help="do not sync the vault before running. useful for back to back runs", action="store_true"
    )

    args = parser.parse_args()
    if args.debug:
        logging.basicConfig(level=logging.DEBUG,
                            format="[%(levelname)s] %(message)s")
    else:
        logging.basicConfig(level=logging.INFO,
                            format="[%(levelname)s] %(message)s")

    # parse args and run the proper command
    try:
        {
            "run": run,
            "config": config,
        }[args.cmd](args)
    except KeyboardInterrupt:
        print()
        sys.exit(0)
    except EOFError:
        print()
        sys.exit(0)
