#!/usr/bin/env python3
#-*- coding: utf-8 -*-
import subprocess
import os
import getpass
import argparse
import logging
import signal
import subprocess
import sys

CUR_FILE_DIR = os.path.dirname(os.path.realpath(__file__))
DEFAULT_CLICKHOUSE_ROOT = os.path.abspath(os.path.join(CUR_FILE_DIR, "../../"))
CURRENT_WORK_DIR = os.getcwd()
CONTAINER_NAME = "clickhouse_testflows_tests"

DIND_TESTFLOWS_TESTS_IMAGE_NAME = "clickhouse/testflows-runner"

def check_args_and_update_paths(args):
    if not os.path.isabs(args.binary):
        args.binary = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.binary))

    if not args.bridge_binary:
        args.bridge_binary = os.path.join(os.path.dirname(args.binary), 'clickhouse-odbc-bridge')
    elif not os.path.isabs(args.bridge_binary):
        args.bridge_binary = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.bridge_binary))

    if not os.path.isabs(args.configs_dir):
        args.configs_dir = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.configs_dir))

    if not os.path.isabs(args.clickhouse_root):
        args.clickhouse_root = os.path.abspath(os.path.join(CURRENT_WORK_DIR, args.clickhouse_root))

    for path in [args.binary, args.configs_dir, args.clickhouse_root]:
        if not os.path.exists(path):
            raise Exception("Path {} doesn't exists".format(path))

def docker_kill_handler_handler(signum, frame):
    subprocess.check_call('docker kill $(docker ps -a -q --filter name={name} --format="{{{{.ID}}}}")'.format(name=CONTAINER_NAME), shell=True)
    raise KeyboardInterrupt("Killed by Ctrl+C")

signal.signal(signal.SIGINT, docker_kill_handler_handler)

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
    parser = argparse.ArgumentParser(description="ClickHouse testflows runner")

    parser.add_argument(
        "--binary",
        default=os.environ.get("CLICKHOUSE_TESTS_SERVER_BIN_PATH", os.environ.get("CLICKHOUSE_TESTS_CLIENT_BIN_PATH", "/usr/bin/clickhouse")),
        help="Path to clickhouse binary")

    parser.add_argument(
        "--bridge-binary",
        default=os.environ.get("CLICKHOUSE_TESTS_ODBC_BRIDGE_BIN_PATH", ""),
        help="Path to clickhouse-odbc-bridge binary. Defaults to clickhouse-odbc-bridge in the same dir as clickhouse.")

    parser.add_argument(
        "--configs-dir",
        default=os.environ.get("CLICKHOUSE_TESTS_BASE_CONFIG_DIR", os.path.join(DEFAULT_CLICKHOUSE_ROOT, "programs/server")),
        help="Path to clickhouse configs directory")

    parser.add_argument(
        "--clickhouse-root",
        default=DEFAULT_CLICKHOUSE_ROOT,
        help="Path to repository root folder")

    parser.add_argument(
        "--command",
        default='',
        help="Set it to run some other command in container (for example bash)")

    parser.add_argument(
        "--disable-net-host",
        action='store_true',
        default=False,
        help="Don't use net host in parent docker container")

    parser.add_argument(
        "--docker-image-version",
        default="latest",
        help="Version of docker image which runner will use to run tests")


    parser.add_argument('testflows_args', nargs='*', help="args for testflows command")

    args = parser.parse_args()

    check_args_and_update_paths(args)

    net = ""
    if not args.disable_net_host:
        net = "--net=host"

    # create named volume which will be used inside to store images and other docker related files,
    # to avoid redownloading it every time
    #
    # should be removed manually when not needed
    subprocess.check_call('docker volume create {name}_volume'.format(name=CONTAINER_NAME), shell=True)

    # enable tty mode & interactive for docker if we have real tty
    tty = ""
    if sys.stdout.isatty() and sys.stdin.isatty():
        tty = "-it"

    cmd = "docker run {net} {tty} --rm --name {name} --privileged --volume={bridge_bin}:/clickhouse-odbc-bridge --volume={bin}:/clickhouse \
        --volume={cfg}:/clickhouse-config --volume={pth}:/ClickHouse --volume={name}_volume:/var/lib/docker -e TESTFLOWS_OPTS='{opts}' {img} {command}".format(
        net=net,
        tty=tty,
        bin=args.binary,
        bridge_bin=args.bridge_binary,
        cfg=args.configs_dir,
        pth=args.clickhouse_root,
        opts=' '.join(args.testflows_args),
        img=DIND_TESTFLOWS_TESTS_IMAGE_NAME + ":" + args.docker_image_version,
        name=CONTAINER_NAME,
        command=args.command
    )

    print(("Running testflows container as: '" + cmd + "'."))
    # testflows return non zero error code on failed tests
    subprocess.call(cmd, shell=True)

    result_path = os.environ.get("CLICKHOUSE_TESTS_RESULT_PATH", None)
    if result_path is not None:
        move_from = os.path.join(args.clickhouse_root, 'tests/testflows')
        status = os.path.join(move_from, 'check_status.tsv')
        results = os.path.join(move_from, 'test_results.tsv')
        clickhouse_logs = os.path.join(move_from, 'clickhouse_logs.tar.gz')
        subprocess.call("mv {} {}".format(status, result_path), shell=True)
        subprocess.call("mv {} {}".format(results, result_path), shell=True)
        subprocess.call("mv {} {}".format(clickhouse_logs, result_path), shell=True)
