import logging
from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.plesk_api import operator as plesk_ops

logger = logging.getLogger(__name__)


class RestoreCatchAllSmartermailAssimilate(SubscriptionAction):
	"""This is a HACK: when webspace is created we do not pass disable provisioning flag,
	even if working in SmarterMail assimilate mode.
	Actually it is quite difficult to pass it when creating webspace.
	So, provisioning happens, and SmarterMail APS resets catch-all configuration.
	"""

	def get_description(self):
		return "Restore catch-all settings for SmarterMail assimilation mode"

	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 restore catch-all settings for SmarterMail "
			"assimilation mode for subscription '%s'" % 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
		"""
		return False

	def filter_subscription(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		has_mail = subscription.converted_backup.mailsystem is not None
		return has_mail and subscription.is_mail_assimilate

	def run(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		catch_all_value = subscription.converted_backup.mailsystem.get_catch_all()
		if catch_all_value is not None and '@' in catch_all_value:
			subscription_info = global_context.conn.target.plesk_api().send(
				plesk_ops.SubscriptionOperator.Get(
					filter=plesk_ops.SubscriptionOperator.FilterByName([subscription.name]),
					dataset=[plesk_ops.SubscriptionOperator.Dataset.GEN_INFO]
				)
			)
			if len(subscription_info) != 1:
				raise Exception("Expected exactly one subscription, got %s", len(subscription_info))
			subscription_id, _ = subscription_info[0].data

			for nonexistent_user in [
				# first disable catch-all, so when enabling catch-all APSMail
				# won't decide that there is nothing to change
				plesk_ops.MailOperator.SetPrefs.NonexistentUserReject(),
				plesk_ops.MailOperator.SetPrefs.NonexistentUserForward(catch_all_value),
			]:
				results = global_context.conn.target.plesk_api().send(plesk_ops.MailOperator.SetPrefs(
					filter=plesk_ops.MailOperator.FilterBySiteId([subscription_id]),
					nonexistent_user=nonexistent_user
				))
				for result in results:
					result.check()