import logging
import os

from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.common.utils.windows_utils import cmd_command
from parallels.common.utils.windows_utils import path_join as windows_path_join

logger = logging.getLogger(__name__)


class Transfer(SubscriptionAction):
	def get_description(self):
		return "Transfer WPB sites"

	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 transfer WPB sites of subscription '%s'" % (
			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 len(self._list_wpb_sites(global_context, subscription)) > 0

	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 run(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		logger.debug(u"Collecting information about Web Presense Builder sites")
		wpb_sites = self._list_wpb_sites(global_context, subscription)

		with subscription.panel_target_server.runner() as runner_target:
			source_server = subscription.web_source_server
			is_windows = source_server.is_windows()
			with source_server.runner() as runner_source:
				for domain_name, sitebuilder_site_id in wpb_sites:
					base_filename = u'wpb_%s.zip' % (domain_name)
					source_filename = source_server.get_session_file_path(base_filename)
					local_filename = global_context.migrator_server.get_session_file_path(base_filename)
					ppa_filename = subscription.panel_target_server.get_session_file_path(base_filename)

					logger.debug(u"Backup Web Presence Builder site on the source node")
					if is_windows:
						runner_source.sh(
							ur'cmd.exe /c "{php} -dauto_prepend_file="" {bru} backup --target=site --uuid={site_id} --file={filename}"',
							dict(
								php=ur"%s\admin\bin\php" % (source_server.plesk_dir,),
								bru=u"%s\\sb\\utils\\bru.php" % (source_server.plesk_dir,),
								source_plesk_dir=source_server.plesk_dir,
								site_id=sitebuilder_site_id, filename=source_filename
							)
						)
					else:
						runner_source.sh(
							u'{plesk_dir}/bin/sw-engine-pleskrun /usr/local/sb/utils/bru.php backup --target=site --uuid={site_id} --file={filename}',
							dict(
								plesk_dir=source_server.plesk_dir,
								site_id=sitebuilder_site_id,
								filename=source_filename
							)
						)

					logger.debug(u"Download backup file to local server")
					runner_source.get_file(source_filename, local_filename)
					runner_source.remove_file(source_filename)  # remove immediately as all WPB sites could take a lot of disk space
					logger.debug(u"Upload backup file to target panel management node")
					runner_target.upload_file(local_filename, ppa_filename)
					os.remove(local_filename)

					logger.debug(u"Restore Web Presense Builder site on target panel management node")
					target_plesk_dir = subscription.panel_target_server.plesk_dir
					if subscription.panel_target_server.is_windows():
						runner_target.sh(
							cmd_command('{php} -dauto_prepend_file="" {bru} restore --target=site --uuid={site_id} --file={filename} --use_defaults'),
							dict(
								php=ur"%s\admin\bin\php" % (target_plesk_dir,),
								bru=u"%s\\sb\\utils\\bru.php" % (target_plesk_dir,),
								source_plesk_dir=target_plesk_dir,
								site_id=sitebuilder_site_id, filename=ppa_filename
							)
						)
						runner_target.remove_file(ppa_filename)
						plesk_bin_domain=windows_path_join(target_plesk_dir, "bin/domain")
					else:
						runner_target.sh(
							u'{plesk_dir}/bin/sw-engine-pleskrun /usr/local/sb/utils/bru.php restore --target=site --uuid={site_id} --file={filename} --use_defaults',
							dict(
								plesk_dir=target_plesk_dir,
								site_id=sitebuilder_site_id,
								filename=ppa_filename
							)
						)
						runner_target.remove_file(ppa_filename)
						plesk_bin_domain = "%s/bin/domain" % target_plesk_dir

					logger.debug(u"Restore relation between Plesk domain and Web Presense Builder site")
					runner_target.sh(
						u'{plesk_bin_domain} --update {domain_name} -publish-sb-site true -sb-site-id {site_id}',
						dict(plesk_bin_domain=plesk_bin_domain, domain_name=domain_name, site_id=sitebuilder_site_id)
					)

	@staticmethod
	def _list_wpb_sites(global_context, subscription):
		""" Returns the following structure:
		wpb_sites = [
			(subscription_name, site_id),
			(subdomain1_name, site_id), (subdomain2_name, site_id), ...,
			(addondomain1_name, site_id), (addondomain2_name, site_id), ...
		]
		where site_id is an id of WPB site for subscription/addon domain/subdomain
		the function guarantees that site_id is not None
		"""

		safe = global_context.safe
		wpb_sites = []

		with safe.try_subscription(
			subscription.name,
			u"Failed to read information about Web Presense Builder sites.", is_critical=False
		):
			for site in subscription.converted_backup.iter_domains():
				if site.sitebuilder_site_id is not None:
					wpb_sites.append((site.name, site.sitebuilder_site_id))

		return wpb_sites
