import logging
import threading

from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.common.actions.utils.multithreading_properties import MultithreadingProperties
from parallels.common.utils import poa_api_helper
from parallels.utils import if_not_none, group_by_id
from parallels.common.utils.common_constants import ADMIN_ID

logger = logging.getLogger(__name__)


class ImportSubscriptions(SubscriptionAction):
	def __init__(self):
		self._lock = threading.Lock()

	def get_description(self):
		return "Create subscription in target panel"

	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 create subscription '%s' in target panel"
		) % (subscription.name,)

	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_multithreading_properties(self):
		return MultithreadingProperties(
			can_use_threads=True, use_threads_by_default=True
		)

	def run(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		webspaces_by_name = group_by_id(
			global_context.target_existing_objects.webspaces, lambda ws: ws.name
		)

		reseller = subscription.model_reseller
		client = subscription.model_client

		if subscription.name in webspaces_by_name:
			# subscription already exists, just enable virtual hosting if it is not enabled
			existing_hosting_type = webspaces_by_name[subscription.name].htype
			if subscription.raw_backup.is_virtual_hosting and existing_hosting_type == 'none':
				logger.info("Subscription already exists, but has no hosting. Enable virtual hosting.")
				global_context.import_api.enable_subscription_virtual_hosting(
					subscription.model, subscription.model_client,
				)
			return

		reseller_login = if_not_none(reseller, lambda r: r.login)

		if reseller is None:
			reseller_id = ADMIN_ID
		else:
			reseller_id = global_context.target_existing_objects.resellers[reseller.login].id

		if subscription.model.plan_name is not None:
			plan_id = poa_api_helper.get_service_template_by_owner_and_name(
				global_context.target_existing_objects.service_templates,
				reseller_id,
				subscription.model.plan_name
			).st_id
		else:
			# custom subscription - subscription that is not
			# assigned to any service template (service plan)
			plan_id = None

		if client.login != reseller_login:
			owner_id = global_context.target_existing_objects.customers[client.login].id
		else:
			owner_id = reseller_id

		target_plesk_server = global_context.conn.target.plesk_server

		# Workaround for Plesk for Linux <= 12.0
		# parallel creation of subscription may fail (bugs PPPM-2705, PPPM-2734)
		parallel_create_could_fail = (
			target_plesk_server.plesk_version < (12, 1)
			and
			not target_plesk_server.is_windows()
		)

		if parallel_create_could_fail:
			logger.debug("Parallel creation of subscriptions may fail, acquire lock")
			self._lock.acquire()

		try:
			global_context.import_api.create_hosting_subscription(
				owner_id,
				plan_id,
				subscription.model.addon_plan_ids,
				subscription.model,
				subscription.model_client,
				subscription.model_reseller
			)
		finally:
			if parallel_create_could_fail:
				logger.debug("Release lock for creation of subscriptions operation")
				self._lock.release()