from parallels.core.logging import get_logger
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.reports.model.issue import Issue
from parallels.core.utils.common import group_by_id
from parallels.core.utils.common_constants import PLESK_EXTENSION_HOOK_SERVER, PLESK_EXTENSION_HOOK_RESELLER, \
    PLESK_EXTENSION_HOOK_CUSTOMER, PLESK_EXTENSION_HOOK_SUBSCRIPTION, PLESK_EXTENSION_HOOK_SITE
from parallels.plesk.source.plesk import messages
from parallels.plesk.source.plesk.actions.utils import is_extensions_supported, iter_extensions

logger = get_logger(__name__)


class CheckExtensionsAction(CommonAction):
    def get_description(self):
        return messages.ACTION_CHECK_EXTENSIONS

    def get_failure_message(self, global_context):
        return messages.ACTION_CHECK_EXTENSIONS_FAILED

    def is_critical(self):
        return False

    def filter_action(self, global_context):
        return is_extensions_supported(global_context)

    def run(self, global_context):
        """Check ability to migrate data of Plesk extensions

        :type global_context: parallels.plesk.source.plesk.global_context.PleskGlobalMigrationContext
        """
        target_extensions = global_context.hosting_repository.extension.get_list()
        target_extensions_by_name = group_by_id(target_extensions, lambda e: e.name)
        for source_extension, _ in iter_extensions(global_context, is_skip_missed=False):
            target_extension = target_extensions_by_name.get(source_extension.name)
            if target_extension is None:
                # there are no such extension on target
                global_context.pre_check_report.add_issue(
                    'extension_%s' % source_extension.name,
                    Issue.SEVERITY_WARNING,
                    messages.ACTION_CHECK_EXTENSIONS_EXTENSION_MISSED.format(
                        extension_name=source_extension.name
                    ),
                    messages.ACTION_CHECK_EXTENSIONS_EXTENSION_MISSED_SOLUTION.format(
                        extension_name=source_extension.name
                    )
                )
                continue
            for hook in source_extension.hooks.keys():
                if source_extension.is_hook_available(hook) and not target_extension.is_hook_available(hook):
                    # target version of Plesk extension does not support hook supported on source
                    missed_hook_message = self._get_missed_hook_message(hook)
                    if missed_hook_message is None:
                        # nothing to say about this hook, it does not matter for general migration purposes
                        continue
                    global_context.pre_check_report.add_issue(
                        'extension_%s_%s' % (source_extension.name, hook),
                        Issue.SEVERITY_WARNING,
                        missed_hook_message.format(extension_name=source_extension.name),
                        messages.ACTION_CHECK_EXTENSIONS_EXTENSION_HOOK_MISSED_SOLUTION.format(
                            extension_name=source_extension.name
                        )
                    )

    @staticmethod
    def _get_missed_hook_message(hook):
        if hook == PLESK_EXTENSION_HOOK_SERVER:
            return messages.ACTION_CHECK_EXTENSIONS_EXTENSION_HOOK_MISSED_SERVER
        elif hook == PLESK_EXTENSION_HOOK_RESELLER:
            return messages.ACTION_CHECK_EXTENSIONS_EXTENSION_HOOK_MISSED_RESELLER
        elif hook == PLESK_EXTENSION_HOOK_CUSTOMER:
            return messages.ACTION_CHECK_EXTENSIONS_EXTENSION_HOOK_MISSED_CUSTOMER
        elif hook == PLESK_EXTENSION_HOOK_SUBSCRIPTION:
            return messages.ACTION_CHECK_EXTENSIONS_EXTENSION_HOOK_MISSED_SUBSCRIPTION
        elif hook == PLESK_EXTENSION_HOOK_SITE:
            return messages.ACTION_CHECK_EXTENSIONS_EXTENSION_HOOK_MISSED_SITE
        return None
