import argparse
import json
import subprocess
import sys
import yaml


def print_usage():
    print('Usage:')
    print('{} usage            Prints this help message and exits'.format(sys.argv[0]))
    print('{} check|info       Applies pgmigrate check to every known database in nmaps projects'.format(sys.argv[0]))
    print('{} upgrade|migrate  Applies pgmigrate update to every known database in nmaps projects'.format(sys.argv[0]))
    print()
    print('-t TARGET, --target TARGET   Stop after TARGET migrate version')
    print('-v, --verbose                Don\'t hide any output (useful for debugging)')


def parse_command_line_arguments():
    parser = argparse.ArgumentParser(description='Nmaps pgmigrate')
    parser.add_argument(
        'command', default='usage', nargs='?',
        choices=['usage', 'check', 'info', 'upgrade', 'migrate'])
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('-t', '--target', default='latest')
    return parser.parse_args()


def read_config(path: str):
    with open(path, 'r') as f:
        return yaml.safe_load(f.read())


def run(args: list[str], verbose: bool):
    p = subprocess.run(args, encoding='utf-8', capture_output=True)
    if verbose and p.stderr:
        print(p.stderr, file=sys.stderr)
    if p.returncode:
        raise Exception('Command {} failed, exit code {}'.format(' '.join(args), p.returncode))
    return p.stdout


def make_config_path():
    ya_env_type = ''
    with open('/etc/yandex/environment.type', 'r') as f:
        ya_env_type = f.read().replace('\n', '')
    return '/etc/yandex/maps/wiki/migrations/config.{}.yaml'.format(ya_env_type)


def pgmigrate(command: str, target: str, verbose: bool):
    config_path = make_config_path()
    migrations = '/usr/lib/migrations'
    pgmigrate_helper = '/usr/bin/pgmigrate_helper'
    config = read_config(config_path)
    base_args = [pgmigrate_helper, '-c', config_path, '-d', migrations]
    if verbose:
        base_args.append('--verbose')

    def get_version():
        result = run(base_args + ['version', '-e', env], verbose)
        return result.replace('\n', '')

    for env in config['environments']:
        print('Applying pgmigrate command {} to environment {} (current version: {})'
              .format(command, env, get_version()))

        if command == 'migrate':
            run(base_args + ['migrate', '-e', env, '-t', target], verbose)
            print('Applied pgmigrate command {} to database {} (new version: {})'
                  .format(command, env, get_version()))

        info = json.loads(run(base_args + ['info', '-e', env], verbose))
        last = info[str(max(int(key) for key in info.keys()))]
        print('Version {} installed on {}'.format(last['version'], last['installed_on']))


def main():
    args = parse_command_line_arguments()
    if args.command in ['check', 'info']:
        command = 'check'
    elif args.command in ['upgrade', 'migrate']:
        command = 'migrate'
    else:
        print_usage()
        return

    pgmigrate(command, args.target, args.verbose)
