import logging

from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.core.checking import Problem
from parallels.core.import_api.import_api import SubscriptionCannotBeSyncedWithPlan
from parallels.core.migrator_config import is_transfer_resource_limits_enabled
from parallels.plesk import messages
from parallels.core.utils.restore_hosting_utils import restore_hosting_settings_lock


logger = logging.getLogger(__name__)


class SyncSubscriptionPlan(SubscriptionAction):
	"""Synchronize subscriptions with service plans

	We have 2 ways controlled by 'transfer-resource-limits' option in config.ini:
	1) Transfer limits and permissions.
	2) Use limits and permissions from service plan.

	In the 2nd case we should keep subscriptions synced with service plans.
	But Plesk restore resets sync status of subscription when restoring
	backup without plan reference (which is removed for other reasons
	at _remove_subscriptions_to_plans_relation function), making each
	restored subscription locked. So we have to call sync in explicit way.
	(actually there is another way to resolve the problem
	- fill Plesk backup with correct plan information, but that way is
	a bit more complex)

	In the 1st case there is no sense to keep synced status, as limits
	and permissions of each subscription are taken from the source panel,
	not from new Plesk service template.
	"""

	def get_description(self):
		return messages.SYNC_SUBSCRIPTION_WITH_PLAN

	def get_failure_message(self, global_context, subscription):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		"""
		return messages.FAILED_TO_SYNC_SUBSCRIPTION_WITH_PLAN

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

	def filter_subscription(self, global_context, subscription):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		"""
		return True

	def run(self, global_context, subscription):
		"""Run action on given subscription

		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		:rtype: None
		"""
		transfer_resource_limits = is_transfer_resource_limits_enabled(
			global_context.config,
			global_context.target_panel_obj
		)

		is_custom = subscription.model.plan_name is None
		is_locked = subscription.raw_dump.locked
		if not is_custom and (not is_locked or not transfer_resource_limits):
			try:
				with restore_hosting_settings_lock:
					global_context.target_panel_obj.get_import_api(global_context).sync_subscription(
						subscription.name
					)
			except SubscriptionCannotBeSyncedWithPlan as e:
				logger.debug(messages.LOG_EXCEPTION, exc_info=True)
				global_context.safe.fail_subscription(
					subscription.name, unicode(e), is_critical=False, omit_logging=True,
					severity=Problem.WARNING
				)
