from parallels.core.reports.subscription_report_provider import SubscriptionReportProvider


class PlainReport(SubscriptionReportProvider):
    """Utility wrapper around Report, allowing to add issues for a subscription or a customer
    without knowing their parents.
    """
    REPORT_OBJECT_RESELLER = u'Reseller'
    REPORT_OBJECT_CUSTOMER = u'Client'
    REPORT_OBJECT_SUBSCRIPTION = u'Subscription'
    REPORT_OBJECT_PLAN = u'Plan'
    REPORT_AUXILIARY_USER = u'Auxiliary user'
    REPORT_AUXILIARY_USER_ROLE = u'Auxiliary user role'

    def __init__(self, root_report, migration_list_data):
        """Class constructor

        :type root_report: (
            parallels.core.reports.model.report.Report | parallels.core.reports.report_writer.ReportWriter
        )
        :type migration_list_data: parallels.core.migration_list.entities.list_data.MigrationListData
        """
        self.root_report = root_report
        self._migration_list_data = migration_list_data

    def get_root_report(self):
        """Get non-plain report

        :rtype: parallels.core.reports.model.report.Report
        """
        return self.root_report

    def get_reseller_report(self, login):
        """Get report of reseller

        :type login: str | unicode
        :rtype: parallels.core.reports.model.report.Report
        """
        return self.root_report.subtarget(self.REPORT_OBJECT_RESELLER, login)

    def get_customer_report(self, login):
        """Get report of customer

        :type login: str | unicode
        :rtype: parallels.core.reports.model.report.Report
        """
        report = self.root_report
        reseller_login = self._get_customer_owner(login)
        if reseller_login is not None:
            report = self.get_reseller_report(reseller_login)
        report = report.subtarget(self.REPORT_OBJECT_CUSTOMER, login)
        return report

    def get_subscription_report(self, name):
        """Get report of subscription

        :type name: str | unicode
        :rtype: parallels.core.reports.model.report.Report
        """
        report = self.root_report
        reseller_login, customer_login = self._get_subscription_owners(name)
        if reseller_login is not None:
            report = report.subtarget(self.REPORT_OBJECT_RESELLER, reseller_login)
        if customer_login is not None:
            report = report.subtarget(self.REPORT_OBJECT_CUSTOMER, customer_login)
        report = report.subtarget(self.REPORT_OBJECT_SUBSCRIPTION, name)
        return report

    def get_plan_report(self, reseller_login, plan_name):
        """Get report of hosting plan

        :type reseller_login: str | unicode | None
        :type plan_name: str | unicode
        :rtype: parallels.core.reports.model.report.Report
        """
        report = self.root_report
        if reseller_login is not None:
            report = report.subtarget(self.REPORT_OBJECT_RESELLER, reseller_login)
        report = report.subtarget(self.REPORT_OBJECT_PLAN, plan_name)
        return report

    def get_auxiliary_user_report(self, owner_login, auxiliary_user_name):
        """Get report of auxiliary user

        :type owner_login: str | unicode | None
        :type auxiliary_user_name: str | unicode
        :rtype: parallels.core.reports.model.report.Report
        """
        report = self._get_owner_report(owner_login)
        report = report.subtarget(self.REPORT_AUXILIARY_USER, auxiliary_user_name)
        return report

    def get_auxiliary_user_role_report(self, owner_login, auxiliary_user_role_name):
        """Get report of auxiliary user role

        :type owner_login: str | unicode | None
        :type auxiliary_user_role_name: str | unicode
        :rtype: parallels.core.reports.model.report.Report
        """
        report = self._get_owner_report(owner_login)
        report = report.subtarget(self.REPORT_AUXILIARY_USER, auxiliary_user_role_name)
        return report

    def _get_owner_report(self, owner_login):
        """Get report of customer or reseller or administrator, by login

        :type owner_login: str | unicode | None
        :rtype: parallels.core.reports.model.report.Report
        """
        if self._migration_list_data is None:
            return None

        if owner_login is None:
            return self.get_root_report()
        elif owner_login in self._migration_list_data.resellers:
            return self.get_reseller_report(owner_login)
        else:
            return self.get_customer_report(owner_login)

    def _get_customer_owner(self, customer_login):
        if self._migration_list_data is None:
            return None

        return self._migration_list_data.customers_mapping.get(customer_login)

    def _get_subscription_owners(self, subscription_name):
        if self._migration_list_data is None:
            return None, None

        if subscription_name not in self._migration_list_data.subscriptions_mapping:
            return None, None

        subscription_mapping = self._migration_list_data.subscriptions_mapping[subscription_name]
        subscription_owner = subscription_mapping.owner

        if subscription_owner is None:
            # owner is administrator
            return None, None
        if subscription_owner in self._migration_list_data.resellers:
            # subscription is owned directly by reseller
            return subscription_owner, None
        else:
            # subscription is owner by customer, which is owned or is not owned by reseller
            return self._get_customer_owner(subscription_owner), subscription_owner
