import os
import json
import pwd
import sys

from cfg_checker.common.const import ENV_TYPE_GLOB, ENV_TYPE_SALT
from cfg_checker.common.const import ENV_TYPE_KUBE, ENV_TYPE_LINUX, ENV_LOCAL
from cfg_checker.common.const import supported_envs

from cfg_checker.common.exception import ConfigException
from cfg_checker.common.log import logger_cli

from cfg_checker.common.other import utils, shell
from cfg_checker.common.ssh_utils import ssh_shell_p

from cfg_checker.clients import get_kube_remote

pkg_dir = os.path.dirname(__file__)
pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir)
pkg_dir = os.path.normpath(pkg_dir)
pkg_dir = os.path.abspath(pkg_dir)

_default_work_folder = os.path.normpath(pkg_dir)


def _extract_salt_return(_raw):
    if not isinstance(_raw, str):
        _json = _raw
        logger_cli.debug("...ambigious return detected")
    else:
        try:
            _json = json.loads(_raw)
        except ValueError:
            _json = _raw
            logger_cli.debug(
                "...return value is not a json: '{}'".format(_raw)
            )

    return _json


class CheckerConfiguration(object):
    @staticmethod
    def load_nodes_list():
        _file = os.environ.get('SALT_NODE_LIST_FILE', None)
        if _file:
            _v, _ = utils.get_nodes_list(
                os.path.join(pkg_dir, _file),
                env_sting=os.environ.get('CFG_ALL_NODES', None)
            )
            return _v
        else:
            return None

    def _detect(self, _type):
        logger_cli.debug("...detecting '{}'".format(_type))
        if _type is None:
            raise ConfigException("# Unexpected supported env type")
        elif _type == ENV_TYPE_SALT:
            # Detect salt env
            _detect_cmd = ["curl", "-s"]
            _detect_cmd.append(
                "http://" + self.mcp_host + ':' + self.salt_port
            )
            # Try to call salt API on target host
            _r = None
            logger_cli.debug("...trying to detect env type '{}'".format(_type))
            if self.env_name == ENV_LOCAL:
                _r = shell(" ".join(_detect_cmd))
            else:
                _r = ssh_shell_p(
                    " ".join(_detect_cmd),
                    self.ssh_host,
                    username=self.ssh_user,
                    keypath=self.ssh_key,
                    piped=False,
                    use_sudo=self.ssh_uses_sudo,
                    silent=True
                )
            # Parse return
            _r = _extract_salt_return(_r)

            if len(_r) < 1:
                return False
            elif _r["return"] == "Welcome":
                return True
            else:
                return False
        elif _type == ENV_TYPE_KUBE:
            _kube = get_kube_remote(self)
            if not _kube.initialized:
                logger_cli.debug(
                    "... failed to load config from '{}'".format(
                        _kube.kConfigPath
                    )
                )
                return False
            else:
                logger_cli.debug(
                    "... config loaded from '{}'".format(
                        _kube.kConfigPath
                    )
                )
            try:
                _vApi = _kube.get_versions_api()
                _v = _vApi.get_code()
                if hasattr(_v, "platform") and \
                        hasattr(_v, "major") and \
                        hasattr(_v, "minor"):
                    _host = "localhost" if _kube.is_local else _kube.kConf.host
                    logger_cli.info(
                        "# Kube server found: {}:{} on '{}'".format(
                            _v.major,
                            _v.minor,
                            _host
                        )
                    )
                    return True
                else:
                    return False
            except Exception as e:
                logger_cli.debug(
                    "... kube env error: '{}' ".format(
                        str(e)
                    )
                )
                return False
        elif _type == ENV_TYPE_LINUX:
            # Detect Linux env
            from platform import system, release
            _s = system()
            _r = release()
            logger_cli.debug("...running on {} {}".format(_s, _r))
            if _s in ['Linux', 'Darwin']:
                return True
            else:
                return False
        else:
            raise ConfigException(
                "# Env type of '{}' is not supported".format(
                    _type
                )
            )

    def _detect_types(self):
        """Try to detect env type based on the name
        """
        self.detected_envs = []
        logger_cli.info('# Detecting env types')
        for _env in supported_envs:
            if self._detect(_env):
                logger_cli.info("# '{}' found".format(_env))
                self.detected_envs.append(_env)
            else:
                logger_cli.info("# '{}' not found".format(_env))

        return

    def _init_mcp_values(self):
        """Load values from environment variables or put default ones
        """
        # filter vars and preload if needed
        self.salt_vars = []
        self.kube_vars = []
        for _key, _value in self.vars:
            if _key.startswith(ENV_TYPE_GLOB):
                os.environ[_key] = _value
            elif _key.startswith(ENV_TYPE_SALT):
                self.salt_vars.append([_key, _value])
            elif _key.startswith(ENV_TYPE_KUBE):
                self.kube_vars.append([_key, _value])
            else:
                logger_cli.warn(
                    "Unsupported config variable: '{}={}'".format(
                        _key,
                        _value
                    )
                )
        self.name = "CheckerConfig"
        self.working_folder = os.environ.get(
            'CFG_TESTS_WORK_DIR',
            _default_work_folder
        )
        self.date_format = "%Y-%m-%d %H:%M:%S.%f%z"
        self.default_tz = "UTC"

        self.pkg_versions_map = 'versions_map.csv'

        # self.ssh_uses_sudo = False
        self.ssh_key = os.environ.get('MCP_SSH_KEY', None)
        self.ssh_user = os.environ.get('MCP_SSH_USER', None)
        self.ssh_host = os.environ.get('MCP_SSH_HOST', None)

        self.mcp_host = os.environ.get('MCP_ENV_HOST', None)
        self.salt_port = os.environ.get('MCP_SALT_PORT', '6969')
        self.threads = int(os.environ.get('MCP_THREADS', "5"))

        self.skip_nodes = utils.node_string_to_list(os.environ.get(
            'CFG_SKIP_NODES',
            None
        ))
        # prebuild user data and folder path
        self.pw_user = pwd.getpwuid(os.getuid())
        if self.env_name == "local":
            pass
        else:
            if not self.ssh_key and not self.force_no_key:
                raise ConfigException(
                    "Please, supply a key for the cluster's master node. "
                    "Use MCP_SSH_KEY, see 'etc/example.env'"
                )

    def _init_env_values(self):
        if ENV_TYPE_SALT in self.detected_envs:
            for _key, _value in self.salt_vars:
                os.environ[_key] = _value

            self.salt_user = os.environ.get('SALT_USER', 'salt')
            self.salt_timeout = os.environ.get('SALT_TIMEOUT', 30)
            self.salt_file_root = os.environ.get('SALT_FILE_ROOT', None)
            self.salt_scripts_folder = os.environ.get(
                'SALT_SCRIPTS_FOLDER',
                'cfg_checker_scripts'
            )
        elif ENV_TYPE_KUBE in self.detected_envs:
            for _key, _value in self.kube_vars:
                os.environ[_key] = _value

            self.kube_config_root = os.environ.get('KUBE_CONFIG_ROOT', None)
            self.kube_scripts_folder = os.environ.get(
                'KUBE_SCRIPTS_FOLDER',
                None
            )
            self.kube_node_user = os.environ.get(
                'KUBE_NODE_USER',
                'ubuntu'
            )
            self.kube_node_keypath = os.environ.get(
                'KUBE_NODE_KEYPATH',
                None
            )
            # Warn user only if Kube env is detected locally
            if self.env_name == ENV_LOCAL:
                if not os.path.exists(self.kube_config_path):
                    logger_cli.warn(
                        "Kube config path not found on local env: '{}'".format(
                            self.kube_config_path
                        )
                    )
                # On local envs, KUBE_NODE_KEYPATH is mandatory and is
                # provided to give cfg-checker access to kube nodes
                if not self.kube_node_keypath and not self.force_no_key:
                    raise ConfigException(
                        "Please, supply a key for the cluster nodes. "
                        "Use KUBE_NODE_KEYPATH, see 'etc/example.env'. "
                        "Consider checking KUBE_NODE_USER as well"
                    )
                self.kube_node_homepath = os.path.join(
                    '/home',
                    self.kube_node_user
                )
            else:
                # Init key for nodes
                # KUBE_NODE_KEYPATH is provided in case of node keys would be
                # different to master node key, which is supplied
                # using MCP_SSH_KEY (mandatory) and, for the most cases,
                # should be the same for remote envs
                if not self.kube_node_keypath and not self.force_no_key:
                    logger_cli.debug(
                        "... using MCP_SSH_KEY as node keys. "
                        "Supply KUBE_NODE_KEYPATH to update."
                    )
                    self.kube_node_keypath = self.ssh_key
                self.kube_node_homepath = self.homepath

    def _init_env(self, config_path, env_name=None):
        """Inits the environment vars from the env file
        Uses simple validation for the values and names

        Keyword Arguments:
            env_name {str} -- environment name to search configuration
                files in etc/<env_name>.env (default: {None})
            env_type {str} -- environment type to use: salt/kube

        Raises:
            ConfigException -- on IO error when loading env file
            ConfigException -- on env file failed validation
        """
        # load env file as init os.environment with its values
        if os.path.isfile(config_path):
            with open(config_path) as _f:
                _list = _f.read().splitlines()
            logger_cli.info(
                "# Loading env vars from '{}'".format(
                    config_path
                )
            )
        else:
            raise ConfigException(
                "# Failed to load enviroment vars from '{}'".format(
                    config_path
                )
            )
        self.vars = []
        for index in range(len(_list)):
            _line = _list[index]
            # skip comments
            if _line.strip().startswith('#'):
                continue
            # validate
            _errors = []
            if len(_line) < 1:
                _errors.append("Line {}: empty".format(index))
            elif _line.find('=') < 0 or _line.count('=') > 1:
                _errors.append("Line {}: {}".format(index, _line))
            else:
                # save values
                _t = _line.split('=')
                self.vars.append([_t[0], _t[1]])
        # if there was errors, report them
        if _errors:
            raise ConfigException(
                "# Environment file failed validation in lines: {}".format(
                    "\n".join(_errors)
                )
            )
        else:
            logger_cli.debug(
                "-> ...loaded total of '{}' vars".format(
                    len(_list)
                )
            )
            self.env_name = env_name

    def __init__(self, args):
        """Base configuration class. Only values that are common for all scripts
        """
        self.ssh_uses_sudo = args.sudo
        self.ssh_direct = args.ssh_direct
        self.kube_config_path = args.kube_config
        self.debug = args.debug
        self.insecure = args.insecure
        self.force_no_key = args.force_no_key
        # Make sure we running on Python 3
        if sys.version_info[0] < 3 and sys.version_info[1] < 5:
            logger_cli.error("# ERROR: Python 3.5+ is required")
            sys.exit(1)
        else:
            logger_cli.debug("### Python version is {}.{}".format(
                sys.version_info[0],
                sys.version_info[1]
            ))

        # if env name is default, check var too
        if args.env_name == ENV_LOCAL:
            _env = os.getenv('MCP_ENV', None)
            _env = _env if _env else args.env_name
            _env_config_path = os.path.join(pkg_dir, 'etc', _env + '.env')
        else:
            _env = args.env_name
            _env_config_path = args.env_config

        # Init environment variables from file, validate
        self._init_env(_env_config_path, env_name=_env)
        # Load Common vars for any type of the env
        self._init_mcp_values()
        # Detect env types present
        self._detect_types()
        # handle forced env type var
        _forced_type = os.getenv('MCP_TYPE_FORCE', None)
        if _forced_type in supported_envs:
            self.detected_envs.append(_forced_type)
        elif _forced_type is not None:
            logger_cli.warn(
                "Unsupported forced type of '{}'".format(
                    _forced_type
                )
            )
        # Check if any of the envs detected
        if len(self.detected_envs) < 1:
            if _env is None:
                raise ConfigException("No environment types detected locally")
            else:
                raise ConfigException(
                    "No environment types detected at '{}'".format(
                                self.mcp_host
                            )
                )
        # initialize path to folders
        if self.env_name == ENV_LOCAL:
            # names and folders
            self.user = self.pw_user.pw_name
            self.homepath = self.pw_user.pw_dir
        else:
            # names and folders in case of remote env
            self.user = self.ssh_user
            self.homepath = os.path.join('/home', self.ssh_user)

        # Init vars that is specific to detected envs only
        self._init_env_values()
