#!/usr/bin/python3
# pylint: disable=consider-using-f-string
# pylint: disable=fixme
# TODO: legacy (classic) has "Sites" instead of "Site" (angi) and "Hosts" (classic/legacy) instead of "Host" (angi) --> could we set that via json files?
"""
 cs_ssh
 Author:       Fabian Herschel, Mar 2023
 License:      GNU General Public License (GPL)
 Copyright:    (c) 2023 SUSE LLC
"""

import time
#import subprocess
import re
import sys
import json
import argparse
# import random

from paramiko import SSHClient

class SshMultiNode:

    def message(self, msg, **kwargs):
        """
        message with formatted timestamp
        """
        stdout = True
        if 'stdout' in kwargs:
            stdout = kwargs['stdout']
        # TODO: specify, if message should be written to stdout, stderr and/or log file
        date_time = time.strftime("%Y-%m-%d %H:%M:%S")
        r_id = ""
        msg_arr = msg.split(" ")
        if stdout: 
            print("{}{} {:<9s} {}".format(date_time, r_id, msg_arr[0], " ".join(msg_arr[1:])))


    def __init__(self, **kwargs):
        """
        constructor
        """
        # if 'cmdparse' in kwargs:
        #    cmdparse = kwargs['cmdparse']
        self.config = { 
                        'command': None,
                        'hosts': [],
                        'quiet': False,
                        'report_hostname': False,
                        'user': 'root'
                      }


    def do_ssh(self, host, user, cmd):
        """
        ssh remote cmd exectution
        returns a tuple ( stdout-string, stderr, string, rc )
        """
        if host:
            try:
                ssh_client = SSHClient()
                ssh_client.load_system_host_keys()
                ssh_client.connect(host, username=user)
                (cmd_stdout, cmd_stderr) = ssh_client.exec_command(cmd)[1:]
                result_stdout = cmd_stdout.read().decode("utf8")
                result_stderr = cmd_stderr.read().decode("utf8")
                result_rc = cmd_stdout.channel.recv_exit_status()
                check_result = (result_stdout, result_stderr, result_rc)
                ssh_client.close()
            except Exception as ssh_muell:
                if test01.config['quiet'] is not True:
                    self.message(f"ssh connection to {host} did not work ...")
                    self.message(f"{type(ssh_muell)}")
                check_result=("", "", 2)
        else:
            check_result=("", "", 2)
        return check_result


test01 = SshMultiNode()

parser = argparse.ArgumentParser()
parser.add_argument("--hosts", nargs="*", help="hosts to connect to (stops after first successful command)")
parser.add_argument("--command", help="command to be called on the hosts")
parser.add_argument("--user", help="linux user to be used for ssh connection (default is root)")
parser.add_argument("--quiet", help="linux user to be used for ssh connection (default is root)", action="store_true")
parser.add_argument("--report_hostname", help="report hostname of succesful ssh connection", action="store_true")
args = parser.parse_args()
if args.hosts:
    test01.config['hosts'] = args.hosts
if args.command:
    test01.config['command'] = args.command
if args.user:
    test01.config['user'] = args.user
if args.quiet:
    test01.config['quiet'] = args.quiet
if args.report_hostname:
    test01.config['report_hostname'] = args.report_hostname

for host in test01.config['hosts']:
    result = test01.do_ssh(host, test01.config['user'], test01.config['command'])
    if result[2] > 0:
        if test01.config['quiet'] is not True:
            test01.message(f"INFO: Connection to {host} failed rc={result[2]}") 
    else:
        if test01.config['quiet'] is not True:
            test01.message(f"INFO: Connection to {host} successful")
        if test01.config['report_hostname'] is True:
            print(f"Output from {host}:")
        print(result[0])
        break # only take the first host which answers with rc == 0
