from parallels.core.logging import get_logger
from parallels.core import messages
from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.core.actions.post_migration_checks.utils import should_run_post_migration_checks
from parallels.core.actions.utils.logging_properties import LoggingProperties
from parallels.core.registry import Registry
from parallels.core.reports.printer import print_report
from parallels.core.utils.migration_progress import SubscriptionMigrationStatus
from parallels.core.utils.subscription_operations import SubscriptionOperation

logger = get_logger(__name__)


class PrintSubscriptionPostMigrationReportAction(SubscriptionAction):
    def get_description(self):
        """Get short description of action as string

        :rtype: str | unicode
        """
        return messages.PRINT_SUBSCRIPTION_POST_MIGRATION_REPORT_ACTION_DESCRIPTION

    def get_failure_message(self, global_context, subscription):
        """Get message for situation when action failed

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        return messages.PRINT_SUBSCRIPTION_POST_MIGRATION_REPORT_ACTION_FAILURE

    def get_logging_properties(self):
        """Get how action should be logged to migration tools end-user

        :rtype: parallels.core.actions.utils.logging_properties.LoggingProperties
        """
        return LoggingProperties(info_log=False)

    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 filter_subscription(self, global_context, subscription):
        """Check if we should run this action on given subscription or not

        The function returns true if it should be executed for the given
        subscription, and false if we should not run the action. For example,
        we should not work with .Security files for Linux subscriptions -
        filter them out in that function.

        Arguments:
        - global_context - registry with different objects that reused among different actions
        - subscription - object with information about single subscription

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        :rtype: bool
        """
        return should_run_post_migration_checks(global_context)

    def run(self, global_context, subscription):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        subscription_report = subscription.get_report(global_context.post_migration_check_report)
        print_report(
            subscription_report, show_no_issue_branches=True,
            log_message=messages.SUBSCRIPTION_POST_MIGRATION_REPORT_TITLE
        )

        global_status = global_context.progress.get_subscription(
            subscription.name
        )

        command_name = Registry.get_instance().get_command_name()

        is_post_migration_check_command = command_name in {
            'test-all', 'test-sites', 'test-mail', 'test-databases', 'test-dns', 'test-users'
        }

        if (
            is_post_migration_check_command or
            (command_name == 'transfer-accounts' and should_run_post_migration_checks(global_context))
        ):
            if global_context.subscriptions_status.is_stop(subscription.name):
                per_session_status = SubscriptionMigrationStatus.CANCELLED
                if is_post_migration_check_command:
                    global_status.status = SubscriptionMigrationStatus.CANCELLED
            elif not subscription_report.has_errors_or_warnings():
                per_session_status = SubscriptionMigrationStatus.FINISHED_OK
                if is_post_migration_check_command:
                    global_status.status = SubscriptionMigrationStatus.FINISHED_OK
            elif not subscription_report.has_errors():
                per_session_status = SubscriptionMigrationStatus.FINISHED_WARNINGS
                if is_post_migration_check_command:
                    global_status.status = SubscriptionMigrationStatus.FINISHED_WARNINGS
            else:
                per_session_status = SubscriptionMigrationStatus.FINISHED_ERRORS
                if is_post_migration_check_command:
                    global_status.status = SubscriptionMigrationStatus.FINISHED_ERRORS

            global_context.subscriptions_status.set_operation_status(
                subscription.name, SubscriptionOperation.OPERATION_POST_MIGRATION_CHECKS, per_session_status
            )
