from parallels.core.logging import get_logger
from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.core.utils.common_constants import PLESK_EXTENSION_HOOK_SUBSCRIPTION, \
    PLESK_EXTENSION_HOOK_SUBSCRIPTION_POST_BACKUP, PLESK_EXTENSION_BACKUP_TYPE_SUBSCRIPTION
from parallels.plesk.hosting_repository.model import PleskHostingRepositoryModel
from parallels.plesk.source.plesk import messages
from parallels.plesk.source.plesk.actions.utils import get_target_plesk_server, iter_extensions, \
    is_extensions_supported
from parallels.plesk.source.plesk.actions.deploy.extensions.utils import DeployMessages, ExtensionDeployer

logger = get_logger(__name__)


class DeployExtensionsSubscription(SubscriptionAction):
    def get_description(self):
        return messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION

    def get_failure_message(self, global_context, subscription):
        return messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_FAILED.format(subscription_name=subscription.name)

    def is_critical(self):
        return False

    def filter_subscription(self, global_context, subscription):
        return is_extensions_supported(global_context)

    def run(self, global_context, subscription):
        """Restore extension data for given subscription in target Plesk

        :type global_context: parallels.plesk.source.plesk.global_context.PleskGlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        target_subscription = global_context.hosting_repository.subscription.get_by_name(subscription.name)
        if target_subscription is None:
            logger.warning(messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_NOT_EXISTS.format(
                subscription_name=subscription.name
            ))
            # skip subscriptions that have not been created yet
            return

        target_plesk_server = get_target_plesk_server(global_context)
        for extension, source_plesk_server in iter_extensions(
            global_context,
            filter_hook=[PLESK_EXTENSION_HOOK_SUBSCRIPTION],
            filter_source_id=[subscription.model.source]
        ):
            deploy_messages = DeployMessages(
                backup_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_BACKUP,
                backup_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_BACKUP_FAILED,
                backup_failed_solution_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_BACKUP_FAILED_SOLUTION,
                copy_content_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_COPY_CONTENT,
                copy_content_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_COPY_CONTENT_FAILED,
                copy_content_failed_solution_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_COPY_CONTENT_FAILED_SOLUTION,
                clear_backup_temp_data_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_CLEAR_BACKUP_TEMP_DATA_FAILED,
                restore_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_RESTORE,
                restore_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_RESTORE_FAILED,
                restore_failed_solution_message=messages.ACTION_DEPLOY_EXTENSIONS_SUBSCRIPTION_RESTORE_FAILED_SOLUTION
            )
            source_hosting_repository = PleskHostingRepositoryModel(source_plesk_server)
            source_subscription = source_hosting_repository.subscription.get_by_name(subscription.name)
            for error_message, solution in ExtensionDeployer(
                global_context,
                global_context.cache_state_controllers.subscription,
                extension,
                PLESK_EXTENSION_BACKUP_TYPE_SUBSCRIPTION,
                entity_name=subscription.name
            ).deploy(
                deploy_messages,
                source_plesk_server,
                target_plesk_server,
                extension.is_hook_available(PLESK_EXTENSION_HOOK_SUBSCRIPTION_POST_BACKUP),
                source_entity_id=source_subscription.domain_id,
                target_entity_id=target_subscription.subscription_id,
            ):
                global_context.safe.fail_subscription(
                    name=subscription.name,
                    error_message=error_message,
                    solution=solution,
                    is_critical=False,
                    omit_logging=True
                )
