from parallels.core.registry import Registry
from parallels.core.utils.common import default, safe_string_repr
from parallels.plesk.hosting_repository.utils.cli.base import BaseCli
from parallels.plesk.hosting_repository.utils.cli.utils import add_password_env


class UserCreateCli(BaseCli):
    def __init__(self, runner, user, owner):
        """Construct command to create user in Plesk via CLI

        :type runner: parallels.core.utils.plesk_cli_runner.PleskCLIRunnerBase
        :type user: parallels.core.target_data_model.AuxiliaryUser
        :type owner: parallels.core.target_data_model.Client | parallels.core.target_data_model.Reseller
        """
        super(UserCreateCli, self).__init__(runner)
        self._user = user
        self._owner = owner

    @property
    def name(self):
        return 'user'

    def _get_args(self):
        args = [
            '--create', self._user.login,
            '-cname', self._user.name,
            '-role', list(self._user.roles)[0],
            '-passwd', '',
            '-company', self._user.personal_info.get('company', ''),
            '-phone', self._user.personal_info.get('phone', ''),
            '-fax', self._user.personal_info.get('fax', ''),
            '-address', self._user.personal_info.get('address', ''),
            '-city', self._user.personal_info.get('city', ''),
            '-state', self._user.personal_info.get('state', ''),
            '-zip', self._user.personal_info.get('zip', ''),
            '-country', self._user.personal_info.get('country', ''),
            '-im', self._user.personal_info.get('im', ''),
            '-im-type', self._user.personal_info.get('im-type', ''),
            '-comment', self._user.personal_info.get('comment', ''),
            '-status', 'enabled' if self._user.is_active else 'disabled',
            '-email', self._user.personal_info['email']
        ]

        if self._user.is_domain_admin:
            args.extend(['-domain-admin', 'true'])
        if self._owner.login is not None:
            args.extend(['-owner', self._owner.login])
        else:
            args.extend(['-owner', 'admin'])
        if self._user.subscription_name is not None:
            args.extend(['-subscription-name', self._user.subscription_name])
        #     should be uncommented after plesk 18.0.34 released
        #       with fixed PPP-51835
        # if self._user.external_email != '':
        #     args.extend(['-external-email', self._user.external_email])

        args.extend(['-notify', 'false'])

        return args

    def _get_env(self):
        env = dict(ALLOW_WEAK_PASSWORDS='1')
        env = add_password_env(env, self._user.password)
        return env

    def _process_exception(self, e):
        # yes, there are 2 spaces between "account" and "already", and checking message is
        # not good way to check if auxiliary user exists
        if 'user account  already exists' in safe_string_repr(e).lower():
            return
        raise

    def _is_need_to_create_mailbox(self):
        if self._user.subscription_name is None:
            return False

        subscription = Registry.get_instance().get_context().get_subscription(self._user.subscription_name)
        for mailbox in subscription.mail_raw_dump.iter_mailboxes():
            if mailbox.full_name.lower() == self._user.login.lower():
                return True

        return False


class UserUpdateInfoCli(BaseCli):
    def __init__(self, runner, username, personal_info, additional_info):
        """Construct command to update info of user with given username in Plesk via CLI

        :type runner: parallels.core.utils.plesk_cli_runner.PleskCLIRunnerBase
        :type username: str
        :type personal_info: parallels.core.target_data_model.PersonalInfo
        :type additional_info: str
        """
        super(UserUpdateInfoCli, self).__init__(runner)
        self._username = username
        self._personal_info = personal_info
        self._additional_info = additional_info

    @property
    def name(self):
        return 'user'

    def _get_args(self):
        return [
            '--update', self._username,
            '-im', default(self._personal_info.im, ''),
            '-im-type', default(self._personal_info.im_type, 'Other'),
            '-comment', default(self._personal_info.comment, '') + default(self._additional_info, ''),
        ]
