#!/usr/bin/python3
import os
import sys
import getpass
import argparse


def check_args(args):
    if not args.host and (not args.service or not args.ctype):
        print('Either host or (service and ctype) must be set', file=sys.stderr)
        return False

    if os.path.exists(args.destination_path):
        if not os.path.isdir(args.destination_path):
            print(f'"{args.destination_path}" must be a directory', file=sys.stderr)
            return False

    return True


def parse_args():
    user_name = getpass.getuser()

    parser = argparse.ArgumentParser(description='Clone instance of the saas service to the local machine')

    parser.add_argument('-d', '--destination-path',
                        required=False, type=str, default=f'/home/{user_name}/saas_service',
                        help='absolute path to the destination directory with cloned service')
    parser.add_argument('-i', '--download-index',
                        required=False, action='store_true', default=False,
                        help='download index or not, default=False')
    parser.add_argument('-t', '--host',
                        required=False, type=str,
                        help='if not set - will be used random host')
    parser.add_argument('-s', '--service',
                        required=False, type=str,
                        help='if not set - will be used defined host')
    parser.add_argument('-c', '--ctype',
                        required=False, type=str,
                        help='if not set - will be used defined host')
    parser.add_argument('-p', '--port',
                        required=False, type=int, default=29000,
                        help='base port for the service on the local machine')

    args = parser.parse_args()

    if not check_args(args):
        parser.print_help()
        return None

    return args


def get_random_host(service, ctype):
    # TODO: add real implementation
    return 'saas-yp-education-1.man.yp-c.yandex.net'


def patch_configs(config_dir):
    # TODO: add real implementation
    pass


def execute(cmd):
    print(f'Starting the execution of the command: "{cmd}"')
    os.system(cmd)


def write_script(path, line):
    with open(path, 'w') as script:
        script.writelines([line])
    execute(f'chmod +x {path}')


def main():
    args = parse_args()
    if not args:
        return

    execute(f'rm -rf {args.destination_path}')
    os.makedirs(args.destination_path)

    host = args.host
    if not host:
        host = get_random_host(args.service, args.ctype)

    execute(f'mkdir -p {args.destination_path}/logs')
    execute(f'mkdir -p {args.destination_path}/detach')
    execute(f'mkdir -p {args.destination_path}/index')
    execute(f'mkdir -p {args.destination_path}/state')

    execute(f'ssh {host} "ps ax -o command | grep BasePort=80 | grep -v grep" > {args.destination_path}/src_cmd')
    with open(f'{args.destination_path}/src_cmd', 'r') as file:
        command = file.read()

    replace_with = [
        ('BasePort=80', f'BasePort={args.port}'),
        ('BSCONFIG_IPORT=80', f'BSCONFIG_IPORT={args.port}'),
    ]

    key_to_payload = {
        'LOG_PATH': {
            'replacement': f'{args.destination_path}/logs'
        },
        'Server.ModulesConfig.Synchronizer.DetachPath': {
            'replacement': f'{args.destination_path}/detach'
        },
        'WorkDir': {
            'replacement': f'{args.destination_path}',
            'action': lambda x: execute(f'scp -r {host}:{x}/dict.dict {args.destination_path}/')
        },
        'CONFIG_PATH': {
            'replacement': f'{args.destination_path}',
            'action': lambda x: execute(f'scp -r {host}:{x}/configs {args.destination_path}/')
        },
        'INDEX_DIRECTORY': {
            'replacement': f'{args.destination_path}/index',
            'action': lambda x: execute(
                f"scp -r {host}:{x} {args.destination_path}/index") if args.download_index else None
        },
        'DaemonConfig.Controller.StateRoot': {
            'replacement': f'{args.destination_path}/state',
            'action': lambda x: execute(f'scp -r {host}:{x} {args.destination_path}/state')
        },
        'STATE_ROOT': {
            'replacement': f'{args.destination_path}/state'
        }
    }

    for token in command.split():
        parts = token.split('=')
        if len(parts) != 2 or parts[0] not in key_to_payload:
            continue
        key = parts[0]
        old_value = parts[1]
        payload = key_to_payload[key]
        replace_with.append((old_value, payload['replacement']))
        if 'action' in payload:
            payload['action'](old_value)

    new_command = f"{command.rstrip()} -V BSCONFIG_INAME={args.destination_path.split('/')[-1]}"
    for before, after in replace_with:
        new_command = new_command.replace(before, after)
    new_command = f'{args.destination_path}/rtyserver ' + ' '.join(new_command.split(' ')[1:])

    write_script(f'{args.destination_path}/run.sh',
                 '#!/bin/sh\n\n'
                 'ulimit -n 10240\n\n'
                 f'{new_command}\n')

    write_script(f'{args.destination_path}/debug.sh',
                 '#!/bin/sh\n\n'
                 'ulimit -n 10240\n\n'
                 f'ya tool gdb --ex=run --args {new_command}\n')

    write_script(f'{args.destination_path}/build.sh',
                 '#!/bin/sh\n\n'
                 f'ya make $ARCADIA/saas/rtyserver --checkout && '
                 f'mv -f "$(readlink -f $ARCADIA/saas/rtyserver/rtyserver)" {args.destination_path}\n')

    patch_configs(f'{args.destination_path}/config')

    print(f'\n{new_command}\n')
    print('Congratulations! '
          'Now you can set $ARCADIA environment variable '
          'and run "./build.sh && ./run.sh" or "/build.sh && ./debug.sh"')


if __name__ == '__main__':
    main()
