import os
import sys
from functools import partial
import platform


class EmDBAccessLayerStub:

    def get_time_zones_codes_in_use_by_job(self):
        tz_list = ["HNL", "HAW", "ANC", "PST"]
        return tz_list

    def get_is_tz_managed(self):
        return False

    def set_is_TZ_managed_to_true(self):
        return True

    def get_em_compatibility_version(self):
        return '9.0.22.000'

    def get_is_TZMangedAlloweNonManagedServers(self):
        return False;

    def get_conneced_CTMs_versions(self):
        return ['922', '922']


def is_windows():
    return platform.system() == "Windows"


class MyDbParams:
    def __init__(self):
        self.em_home = os.environ["EM_HOME"]

    def get_db_type(self):
        db_type = self.read_dbu_params("DBTYPE")
        return db_type

    def get_dbu_params_address(self):
        if is_windows():
            return os.path.join(self.em_home, "bin", "DBUtils", "DBUData", "primary", "DBU_params.dat")
        else:
            return os.path.join(self.em_home, "bin", "DBUData", "primary", "DBU_params.dat")

    def read_dbu_params(self, key):

        file_name = self.get_dbu_params_address()
        if not os.path.exists(file_name):
            err_msg = "File does not exist: {}".format(file_name)
            raise OSError(err_msg)
        try:
            value = get_value_from_file(file_name, key)
            return value
        except Exception as e:
            err_msg = "An error occurred during reading file: {}\nError code: {}".format(file_name, e)
            raise OSError(err_msg)


def get_value_from_file(file_path, line_key):
    with open(file_path, 'r') as file:
        for line in file:
            if line.startswith(line_key + '='):
                # Split the line by '=' and return the second part (value), removing any trailing newline characters
                return line.split('=')[1].strip()
    return None  # Return None if the key is not found


class EmDBAccessLayer:
    PARAMS_PVALUE_FIELD = 'pvalue'
    PARAMS_PANME_FIELD = 'pname'
    PARAMS_COMPATIBILITY_VERSION = 'ServerCompatibilityVersion'
    PARAMS_TZ_MANAGED_ALLOW_NON_MANAGED_SERVERS = 'TZMangedAlloweNonManagedServers'
    COMM_CONTROL_M_VER_FIELD = 'control_m_ver'

    def __init__(self):
        em_home = os.environ["EM_HOME"]
        new_path = os.path.join(em_home, "bin", "python", "db_access", "em")
        old_path = os.path.join(em_home, "bin", "python", "config", "common", "utils", "db_access")

        if os.path.exists(new_path):
            sys.path.append(new_path)
            from em_db_commands import EmDbCommands
            from em_db_manager import EmDbManager
            self.db_cmds = EmDbCommands()
            self.db_manager = EmDbManager()
        else:
            sys.path.append(old_path)
            from db_commands import DbCommands as EmDbCommands
            from db_manager import DbManager as EmDbManager
            self.db_cmds = EmDbCommands('em')
            self.db_manager = EmDbManager('em')
            self.db_params = MyDbParams()
            self.db_cmds.get_distinctive_jobs_timezones = partial(self.get_distinctive_jobs_timezones_impl, self)

        
        params_table = self.db_cmds.get_params()
        self.param_raw_by_pname_dic = {item['pname']: item for item in params_table}

    @classmethod
    def get_distinctive_jobs_timezones_impl(cls,self):
        db_type = self.db_params.get_db_type()
        get_distinct_timezones = { 'PGSQL': 'SELECT DISTINCT (TIME_ZONE) FROM DEF_JOB WHERE TRIM(TIME_ZONE) <> \'\'',
                                   'ORACLE': 'SELECT DISTINCT (TIME_ZONE) FROM DEF_JOB WHERE TRIM(TIME_ZONE) IS NOT NULL',
                                   'MSSQL': 'SELECT DISTINCT (TIME_ZONE) FROM DEF_JOB WHERE LTRIM(RTRIM(TIME_ZONE)) <> \'\''}
        query = get_distinct_timezones[db_type]

        result = self.db_manager.get_db_access().send_query(query)
        distinct_timezones = [tz[0] for tz in result]  # from [('CST',), ('NHL',)] to ['CST', 'NHL']
        return distinct_timezones


    def has_mvs_server(self):
        query = "select 1 from COMM where PLATFORM = 'MVS'"
        result = self.db_manager.get_db_access().send_query(query)
        return len(result) > 0


    def get_time_zones_codes_in_use_by_job(self):
        return self.db_cmds.get_distinctive_jobs_timezones()

    def get_is_tz_managed(self):
        value = self.db_cmds.get_name_value('TZ_MANAGED')
        return (value == 'TRUE')

    def set_is_TZ_managed_to_true(self):
        value = self.db_cmds.get_name_value('TZ_MANAGED')
        if value is None:
            return self.db_cmds.insert_name_value('TZ_MANAGED', 'TRUE')
        elif value != 'TRUE':
            return self.db_cmds.update_name_value('TZ_MANAGED', 'TRUE')
        else:
            return True

    def _get_param_val(self, pname):
        if not pname in self.param_raw_by_pname_dic:
            return None
        param_raw = self.param_raw_by_pname_dic[pname]
        param_val = param_raw[EmDBAccessLayer.PARAMS_PVALUE_FIELD]
        return param_val

    def get_em_compatibility_version(self):
        return self._get_param_val(EmDBAccessLayer.PARAMS_COMPATIBILITY_VERSION)

    def get_is_TZMangedAlloweNonManagedServers(self):
        value = self._get_param_val(EmDBAccessLayer.PARAMS_TZ_MANAGED_ALLOW_NON_MANAGED_SERVERS)

        # if PARAMS_TZ_MANAGGED_ALLOW_NON_MANAGED_SERVERS not exist or value is not y/Y we return false
        if value is None or value.upper() != 'Y':
            return False
        return True

    def get_conneced_CTMs_versions(self):
        comm_table = self.db_cmds.get_comm()
        # collecting all values of all connected ctm servers to one list
        control_m_ver_list = [item['control_m_ver'] for item in comm_table]
        return control_m_ver_list
