import logging
from parallels.common import MigrationError

from parallels.common.actions.base.common_action import CommonAction
from parallels.common.converter.business_objects.plans import PlansConverter
from parallels.common.utils import plesk_api_utils
from parallels.target_panel_plesk.converter.hosting_plan import BackupToTargetPleskModelPlanConverter
from parallels.utils import format_list, format_multiline_list

logger = logging.getLogger(__name__)


class CreateHostingPlans(CommonAction):
	def get_description(self):
		"""
		:rtype: basestring
		"""
		return "Create hosting plans"

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:rtype: basestring
		"""
		return "Failed to create hosting plans"

	def run(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:rtype: None
		"""
		# 1) read migration list data
		plan_migration_list = global_context.migrator._read_migration_list_plans(global_context.options)

		# 2) convert plans to target model
		target_plesk_api = global_context.conn.target.plesk_server.plesk_api()

		allowed_limits = plesk_api_utils.get_service_template_allowed_limits(target_plesk_api)
		logger.debug("Allowed service template limits: %s", format_list(allowed_limits))
		allowed_permissions = plesk_api_utils.get_service_template_allowed_permissions(target_plesk_api)
		logger.debug("Allowed service template permissions: %s", format_list(allowed_permissions))
		allowed_hosting_settings = plesk_api_utils.get_service_template_allowed_hosting_settings(target_plesk_api)
		logger.debug("Allowed service template hosting settings: %s", format_list(allowed_hosting_settings))

		converted_plans = PlansConverter().convert_plans(
			global_context.source_server_infos, global_context.import_api, plan_migration_list,
			BackupToTargetPleskModelPlanConverter(
				allowed_limits, allowed_permissions, allowed_hosting_settings,
				global_context.conn.target.plesk_server.is_windows()
			)
		)
		# 3) import plans to the target panel
		self._import_plans(global_context, converted_plans)

	def _import_plans(self, global_context, plans):
		"""Import converted service service plans to target panel

		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type plans: dict[(basestring | None, basestring, bool), parallels.common.target_data_model.Plan]
		"""
		failed_plans = []

		for (owner, name, is_addon), plan in plans.iteritems():
			owner_title = 'admin' if owner is None else "'%s' reseller" % owner
			plan_type_title = 'hosting plan' if not is_addon else 'hosting addon plan'
			if plan.source != 'target':
				logger.info("Create %s '%s' owned by %s", plan_type_title, name, owner_title)
				logger.debug("Plan settings: %s", plan.settings)
				try:
					if not plan.is_addon:
						global_context.import_api.create_service_template(owner, name, plan.settings)
					else:
						global_context.import_api.create_addon_service_template(owner, name, plan.settings)
				except Exception as e:
					logger.error(
						"Failed to create %s '%s' of %s: %s", plan_type_title, name, owner_title, e
					)
					failed_plans.append((name, plan_type_title, owner_title))
			else:
				logger.info(
					"%s '%s' owned by %s already exists on the target panel, no need to create",
					plan_type_title.capitalize(), name, owner_title
				)

		self._check_failed_plans(failed_plans)

	@staticmethod
	def _check_failed_plans(failed_plans):
		"""Check if there are failed plans and raise nice exception in case there are som

		:param list[(basestring, basestring, basestring)] failed_plans: list of failed plans
		:rtype: None
		"""
		if len(failed_plans) > 0:
			raise MigrationError(
				"Failed to create the following plans on target panel:\n%s\n\n"
				"Migration will be stopped. Check the log above and debug.log for more details. \n"
				"To continue migration, create these plans manually on target panel, \n"
				"or assign subscriptions to another plans with the help of migration list" % format_multiline_list([
					"%s '%s' owned by %s" % (plan_type_title, plan_name, owner)
					for plan_name, plan_type_title, owner in failed_plans
				])
			)