from parallels.core.logging import get_logger
from parallels.core import messages
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.actions.utils.logging_properties import LoggingProperties
from parallels.core.utils.restore_hosting_utils import get_restore_hosting_utils
from parallels.core.utils.imported_backups import ImportedBackups
from parallels.core.utils.common import unused

logger = get_logger(__name__)


class ImportBackups(CommonAction):
    def get_description(self):
        return messages.IMPORT_BACKUP_DUMPS_TARGET_PANELS_REPOSITORY

    def get_failure_message(self, global_context):
        return messages.FAILED_IMPORT_BACKUP_DUMPS_TARGET_PANELS

    def get_logging_properties(self):
        """Get how action should be logged to migration tools end-user

        :rtype: parallels.core.actions.utils.logging_properties.LoggingProperties
        """
        return LoggingProperties(compound=False)

    def run(self, global_context):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        """
        backups = set([])
        for subscription in global_context.iter_all_subscriptions():
            if not self._should_import_for_subscription(subscription):
                continue

            for backup in [subscription.server_converted_dump, subscription.mail_server_converted_dump]:
                if backup is not None:
                    backups.add((backup, subscription.panel_target_server))

        for backup, panel_target_server in backups:
            self._import_backup(global_context, backup, panel_target_server)

    @staticmethod
    def _import_backup(global_context, backup, panel_target_server):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        """
        # STEP #1: create utility objects
        target_backup_path = panel_target_server.get_session_file_path('plesk.backup')
        source_backup_path = backup.container.filename
        restore_hosting_utils = get_restore_hosting_utils(panel_target_server)

        # STEP #2: remove backup from target panel's repository if it already exists
        # If backup with such name already exists in target panel's repository
        # (for example, if migrator was interrupted before it cleans up backup file)
        # PMM will refuse to import it again
        # and we could get outdated backup, so remove backup file from target Plesk before import
        restore_hosting_utils.remove_backup(backup.backup_info_file)

        # STEP #3: upload backup
        with logger.debug_level_context(messages.UPLOAD_BACKUP_DUMP_S_TARGET_NODE % source_backup_path):
            with panel_target_server.runner() as runner:
                runner.upload_file(source_backup_path, target_backup_path)

        # STEP #4: import backup to target panel's repository
        with logger.debug_level_context(messages.IMPORT_BACKUP_DUMP_TARGET_PANELS_REPOSITORY):
            backup_prefix, backup_id = restore_hosting_utils.import_backup(
                target_backup_path,
                additional_env_vars=global_context.target_panel_obj.get_import_dump_additional_env_vars(global_context),
                backup_info_file=backup.backup_info_file
            )

        # If pmmcli has not reported backup ID and backup prefix (for example in case of invalid dump), then
        # try to detect them ourselves, by looking inside backup archive
        if backup_id is None:
            backup_id = backup.container.backup_id
        if backup_prefix is None:
            backup_prefix = backup.container.backup_prefix

        # STEP #5: index imported XML domain backup files
        # Index backup files after backup is imported: create dict with key -
        # domain name and value - backup XML file name.
        with logger.debug_level_context(messages.CREATE_MAPPING_DOMAIN_NAME_BACKUP_XML):
            domain_to_backup_file = restore_hosting_utils.index_imported_domain_backup_files(backup_prefix, backup_id)
            logger.debug(messages.DEBUG_MAPPING_XML_FILES, domain_to_backup_file)

        # STEP #6: Put imported backup information to imported backup registry
        ImportedBackups.get_instance().add(backup, domain_to_backup_file)

    @staticmethod
    def _should_import_for_subscription(subscription):
        """Whether we should import backup for that subscription

        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        :rtype: bool
        """
        unused(subscription)
        return True
