#!/usr/bin/env python3
import subprocess
import os
import argparse
from argparse import RawTextHelpFormatter
from logger_slg import init_logger
from colorama import Fore, Back, Style
import requests
import time
from inspect import currentframe, getframeinfo
from slg_dev_ops.digital_ocean_api import create_droplet, get_droplets_ip, add_domain_records, apply_firewall_to_droplet




def get_arguments():
    parser = argparse.ArgumentParser(description='''
        If you have initialization steps you want to take, make sure to name it "init.sh" and place it in the projects root
    ''', formatter_class=RawTextHelpFormatter)

    # argument groups can have their tickers combined (ie -su)
    bools = parser.add_argument_group()

    parser.add_argument('-p', '--project_name', help='Name of the project you are creating', required=True)

    parser.add_argument('-d', '--domain_name', help='Domain name of the site (with no www prepended, ie twitchclip.io)', required=True)

    parser.add_argument('-u', '--username', help='Username to be created on the remote machine', required=True)

    parser.add_argument('-g', '--github_username', help='Github username for pulling of project', required=True)

    # parser.add_argument('-r', '--remote_ip', help='IP address of the remote server', required=True)

    parser.add_argument('-e', '--email_address', help='Email address for LetsEncrypt', required=True)

    parser.add_argument('-to', '--token', help='Digital Ocean Access Token for auto creation', required=True)

    bools.add_argument('-t', '--testing', action='store_true',
                       help='If ticked, will use testing values for certain commands')

    args = parser.parse_args()

    return args

def run_remote_command(username, remote_ip, user_commands):
    return subprocess.check_output(
        f'ssh {username}@{remote_ip} "{user_commands}"', shell=True)
    # an example command with sudo access
    # user_commands = f'''
    #     echo {password} | sudo -S apt update &&
    #     echo {password} | sudo -S apt-get install -y python3-pip &&
    #     pip3 install slg-dev-ops &&
    #     echo {password} | sudo -S chown -R {args.username} ~/.ssh/ &&
    #     echo {password} | sudo -S chmod 700 ~/.ssh/ &&
    #     echo {password} | sudo -S chmod 600 ~/.ssh/*
    # '''.replace('\t', '').replace('\n', '')

def run_local_command(command):
    subprocess.run(command, shell=True)

def print_in_color_then_reset(print_string, color=Fore.YELLOW):
    print(color + print_string, flush=True)
    print(Style.RESET_ALL, flush=True)


if __name__ == '__main__':
    logger = init_logger(
        name=__name__,
        log_path=f'/var/log/slg/{__file__.split("/")[-1]}.log'
    )

    args = get_arguments()
    print(args)

    test_flag = '-t' if args.testing else ''

    uname = args.username
    # ip = args.remote_ip

    input("""Set up your domain name's nameservers to point to digital ocean's nameservers to continue.

    They are:

        ns1.digitalocean.com
        ns2.digitalocean.com
        ns3.digitalocean.com

    Once finished with setting up digital ocean to have control of your domain, press enter to proceed.
    """)

    logger.info('Creating droplet')
    droplet_id = create_droplet(args.token, testing=args.testing)

    logger.info("Getting newly created droplet's IP")
    ip = get_droplets_ip(droplet_id, args.token)

    logger.info('Adding domain records for droplet')
    records = add_domain_records(ip, args.domain_name, args.token)

    logger.info('Adding firewall rules to droplet')
    firewall_resp = apply_firewall_to_droplet(droplet_id, args.token)

    if not (records == 'Successfully created records for @, www' and firewall_resp):
        logger.error(f'''Droplet was not created successfully:

            droplet_id: {droplet_id}
            ip: {ip}
            records: {records}
            firewall_resp: {firewall_resp}
        ''')
        exit(0)


    print("\n---- NOTE: this script will ask you for your password many times. This is for ease of development and shouldn't be cause for alarm ----\n")

    password = input('Please enter your password for sudo commands and the password of the user to be created: ')


    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_local_command(f'slg-digital-ocean-droplet-setup -r {ip} -u {uname} -dn')

    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'echo {password} | sudo -S mkdir -p /var/log/slg && echo {password} | sudo -S chown -R {uname}:{uname} /var/log/slg')

    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'PATH=/home/steven/.local/bin:$PATH; echo {password} | sudo -S -E env "PATH=$PATH" slg-install-nginx')
    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'PATH=/home/steven/.local/bin:$PATH; echo {password} | sudo -S -E env "PATH=$PATH" slg-install-firewall')
    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'PATH=/home/steven/.local/bin:$PATH; slg-init-remote-crontab -u {uname}')

    while True:
        try:
            resp = requests.get(f'http://{args.domain_name}')
            if resp.status_code == 200:
                break
            else:
                print("Domain name not ready. Make sure you've pointed the domain name to the new IP.", flush=True)
                print("Trying again in 5 seconds...", flush=True)
                time.sleep(5)
        except:
            print("Domain name not ready. Make sure you've pointed the domain name to the new IP.", flush=True)
            print("Trying again in 5 seconds...", flush=True)
            time.sleep(5)

    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'echo {password} | sudo -S -E env "PATH=$PATH" slg-setup-tls-ssl-nginx {args.domain_name} {args.project_name} -u {uname} -e {args.email_address} {test_flag}')
    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'echo {password} | sudo -S -E env "PATH=$PATH" slg-init-nginx-conf-gunicorn -f /etc/nginx/conf.d/{args.project_name}.conf -d {args.domain_name},www.{args.domain_name}')
    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'echo {password} | sudo -S mkdir -p /var/www/html/static')
    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'echo {password} | sudo -S npm install -g javascript-obfuscator')
    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'echo {password} | sudo -S docker run -p 27017:27017 -v /home/{uname}/{args.project_name}-mongo:/data/db -d mongo')

    print_in_color_then_reset(f'\n\n---- NOW STARTING LINE {getframeinfo(currentframe()).lineno} ----\n\n')
    run_remote_command(uname, ip, f'ssh-keygen -q -t rsa -N \'\' -f ~/.ssh/id_gh_read_only <<<y >/dev/null 2>&1')

    print_in_color_then_reset("\n\nCopy the below string and paste into a deploy key in your project's repository:\n\n")
    public_key = run_remote_command(uname, ip, f'cat ~/.ssh/id_gh_read_only.pub')
    print(public_key.decode('utf-8'), flush=True)

    input("\n\nWhen you've pasted in the above key press enter to continue. Or hit Ctrl-C if you don't wish to proceed in cloning your repo and performing initialization.")

    GIT_RSA_FINGERPRINT = 'SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8'
    fingerprint = run_remote_command(uname, ip, f"ssh-keyscan -t rsa github.com | tee ~/.ssh/github-key-temp | ssh-keygen -lf -")
    # extract the actual fingerprint
    fingerprint = fingerprint.split()[1].decode('utf-8')

    if GIT_RSA_FINGERPRINT != fingerprint:
        print_in_color_then_reset("\n\n-------- EXITING. GITHUB FINGERPRINT DOESN'T MATCH ---------\n\n", color=Fore.RED)
        print(GIT_RSA_FINGERPRINT, flush=True)
        print(fingerprint, flush=True)
        exit(0)
    else:
        # add key to known hosts
        run_remote_command(uname, ip, f"cat ~/.ssh/github-key-temp >> ~/.ssh/known_hosts")

    run_remote_command(uname, ip, f"git config --global core.sshCommand 'ssh -i ~/.ssh/id_gh_read_only -F /dev/null'")

    run_remote_command(uname, ip, f'git clone --recurse-submodules git@github.com:{args.github_username}/{args.project_name}.git')

    # run the initialization script in the repository
    run_remote_command(uname, ip, f'~/{args.project_name}/init.sh {password}')

    print(
        f"\n\nNow you can login as {args.username}: ssh {args.username}@{ip}!")