from parallels.core.logging import get_logger
from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.core.utils.common import is_empty_iterator
from parallels.core.utils.common_constants import PLESK_EXTENSION_HOOK_SITE, PLESK_EXTENSION_BACKUP_TYPE_SITE, \
    PLESK_EXTENSION_HOOK_SITE_POST_BACKUP
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 DeployExtensionsDomains(SubscriptionAction):
    def get_description(self):
        return messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS

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

    def is_critical(self):
        return False

    def filter_subscription(self, global_context, subscription):
        if not is_extensions_supported(global_context):
            return False
        return not is_empty_iterator(subscription.converted_dump.iter_addon_domains())

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

        :type global_context: parallels.plesk.source.plesk.global_context.PleskGlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        target_plesk_server = get_target_plesk_server(global_context)
        deploy_messages = DeployMessages(
            backup_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_BACKUP,
            backup_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_BACKUP_FAILED,
            backup_failed_solution_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_BACKUP_FAILED_SOLUTION,
            copy_content_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_COPY_CONTENT,
            copy_content_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_COPY_CONTENT_FAILED,
            copy_content_failed_solution_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_COPY_CONTENT_FAILED_SOLUTION,
            clear_backup_temp_data_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_CLEAR_BACKUP_TEMP_DATA_FAILED,
            restore_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_RESTORE,
            restore_failed_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_RESTORE_FAILED,
            restore_failed_solution_message=messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_RESTORE_FAILED_SOLUTION
        )
        for domain_dump in subscription.converted_dump.iter_addon_domains():
            target_domain = global_context.hosting_repository.domain.get_by_name(domain_dump.name)
            if target_domain is None:
                logger.warning(messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_DOMAIN_NOT_EXISTS.format(
                    domain_name=domain_dump.name
                ))
                # skip domain that have not been created yet
                continue
            try:
                for extension, source_plesk_server in iter_extensions(
                    global_context,
                    filter_hook=[PLESK_EXTENSION_HOOK_SITE],
                    filter_source_id=[subscription.model.source]
                ):
                    source_hosting_repository = PleskHostingRepositoryModel(source_plesk_server)
                    source_domain = source_hosting_repository.domain.get_by_name(domain_dump.name)
                    for error_message, solution in ExtensionDeployer(
                        global_context,
                        global_context.cache_state_controllers.domain,
                        extension,
                        PLESK_EXTENSION_BACKUP_TYPE_SITE,
                        entity_name=domain_dump.name
                    ).deploy(
                        deploy_messages,
                        source_plesk_server,
                        target_plesk_server,
                        extension.is_hook_available(PLESK_EXTENSION_HOOK_SITE_POST_BACKUP),
                        source_entity_id=source_domain.domain_id,
                        target_entity_id=target_domain.domain_id,
                    ):
                        global_context.safe.fail_subscription(
                            name=subscription.name,
                            error_message=error_message,
                            solution=solution,
                            is_critical=False,
                            omit_logging=True
                        )
            except Exception:
                logger.exception()
                # place error into report and proceed to next domain
                global_context.safe.fail_subscription(
                    subscription.name,
                    messages.ACTION_DEPLOY_EXTENSIONS_DOMAINS_DOMAIN_FAILED.format(
                        domain_name=domain_dump.name,
                        subscription_name=subscription.name
                    ),
                    is_critical=False
                )
                continue
