from parallels.core import messages
from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.core.logging import get_logger
from parallels.core.utils.common import format_list
from parallels.core.utils.migrator_utils import normalize_domain_name

logger = get_logger(__name__)


class VerifyHostingSettings(SubscriptionAction):
    def get_description(self):
        """Get short description of action as string

        :rtype: str | unicode
        """
        return messages.VERIFY_THAT_HOSTING_SETTINGS_WERE_RESTORED

    def get_failure_message(self, global_context, subscription):
        """Get message for situation when action failed

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        return messages.FAILED_VERIFY_THAT_HOSTING_SETTINGS_WERE % subscription.name

    def is_critical(self):
        """If action is critical or not

        If action is critical and it failed for a subscription, migration tool
        won't run the next operations for the subscription.

        :rtype: bool
        """
        # We explicitly completely fail subscriptions for which hosting settings were not restored.
        # For all other failures, consider them not critical.
        return False

    def run(self, global_context, subscription):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        logger.debug(messages.CHECK_IF_SUBSCRIPTION_WAS_CREATED)
        if not global_context.hosting_repository.subscription.is_exists(subscription.name):
            global_context.safe.fail_subscription(
                subscription.name,
                messages.SUBSCRIPTION_WAS_NOT_RESTORED_IT_DOES
            )

        logger.debug(messages.CHECK_THAT_SITES_WERE_CREATED)
        missing_sites = self._get_missing_sites(global_context, subscription)
        if len(missing_sites) > 0:
            global_context.safe.fail_subscription(
                subscription.name,
                messages.NOT_CREATED_SITES % (
                    format_list(missing_sites)
                )
            )

    @staticmethod
    def _get_missing_sites(global_context, subscription):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        expected_addon_domain_names = [
            normalize_domain_name(addon_domain.name) for addon_domain in subscription.converted_dump.iter_addon_domains()
        ]
        expected_subdomain_names = [
            normalize_domain_name(subdomain.name) for subdomain in subscription.converted_dump.iter_subdomains()
        ]

        existing_addon_domain_names = [
            normalize_domain_name(addon_domain.name) for addon_domain in
            global_context.hosting_repository.domain.get_list(subscription.name, expected_addon_domain_names)
        ]
        existing_subdomain_names = [
            normalize_domain_name(subdomain.name) for subdomain in
            global_context.hosting_repository.subdomain.get_list(subscription.name, expected_subdomain_names)
        ]

        return (
            (set(existing_addon_domain_names) - set(existing_addon_domain_names)) |
            (set(expected_subdomain_names) - set(existing_subdomain_names))
        )
