import logging

from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.common.utils.plesk_api_utils import check_if_subscription_exists
from parallels.plesk_api import operator as plesk_ops
from parallels.utils import format_list

logger = logging.getLogger(__name__)


class VerifyHostingSettings(SubscriptionAction):
	def get_description(self):
		return "Verify that hosting settings were restored"

	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 filter_subscription(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		return True

	def get_failure_message(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		return "Failed to verify that hosting settings were restored for subscription '%s'" % subscription.name

	def run(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		safe = global_context.safe

		logger.debug(u"Check if subscription was restored: it should exist in target panel")
		if not check_if_subscription_exists(subscription.panel_target_server.plesk_api(), subscription.name):
			safe.fail_subscription(
				subscription.name,
				u"Subscription was not restored: it does not exist on target panel"
			)

		logger.debug(u"Check that each site of subscription was restored and exists in target panel")
		missing_sites = self._get_missing_sites(subscription)
		if len(missing_sites) > 0:
			safe.fail_subscription(
				subscription.name,
				u"The following sites of subscription were not restored - they do not exist on target panel: %s" % (
					format_list(missing_sites)
				)
			)

	@staticmethod
	def _get_missing_sites(subscription):
		"""
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		site_names = set(
			site.name for site in subscription.converted_backup.iter_sites()
		)
		missing_sites = set()
		for site_name in site_names:
			request = plesk_ops.SiteOperator.Get(
				filter=plesk_ops.SiteOperator.FilterByName([site_name]),
				dataset=[plesk_ops.SiteOperator.Dataset.GEN_INFO]
			)
			results = subscription.panel_target_server.plesk_api().send(request)
			site_missing = True
			for result in results:
				if not hasattr(result, 'code') or result.code != 1013:
					if result.data[1].gen_info.name == site_name:
						site_missing = False
			if site_missing:
				missing_sites.add(site_name)
		return missing_sites