from parallels.core.migration_list.writer.base_writer import MigrationListWriterBase
from parallels.core.utils.json_utils import write_json


class MigrationListWriterJSON(MigrationListWriterBase):
    def write_initial(
        self, filename,
        target_subscriptions, target_service_plans, target_addon_service_plans,
        comment_existing_subscriptions=True
    ):
        data = {
            'subscriptions': self._get_subscriptions(target_subscriptions),
            'resellers': self._get_resellers(),
            'customers': self._get_customers(),
            'plans': self._get_plans(target_service_plans),
            'addon_plans': self._get_addon_plans(target_addon_service_plans)
        }

        write_json(filename, data, pretty_print=True)

    def _get_subscriptions(self, target_subscriptions):
        subscriptions = self._source_data.extract_subscriptions(
            subscription_filter=None, subscriptions_mapping=None
        )

        return {
            subscription.name: {
                'plan': subscription.plan,
                'addon_plans': list(subscription.addon_plans),
                'owner': subscription.customer or subscription.reseller,
                'exists_on_target': subscription.name in target_subscriptions
            }
            for subscription in subscriptions
        }

    def _get_customers(self):
        customers = {}

        customer_owners = self._source_data.get_customer_owners()
        customer_contacts = self._source_data.get_customer_contacts()

        for customer_login, customer_data in self._target_data.get_customers().items():
            customers[customer_login] = {
                'contact_name': customer_data['contact_name'],
                'exists_on_target': True,
                'exists_on_source': False,
                'owner': customer_data['owner']
            }

        for customer_login, owner_login in customer_owners.items():
            if customer_login in customers:
                customers[customer_login]['exists_on_source'] = True
                continue  # customer from target has priority
            customers[customer_login] = {
                'contact_name': customer_contacts.get(customer_login),
                'exists_on_target': False,
                'exists_on_source': True,
                'owner': owner_login,
            }

        return customers

    def _get_resellers(self):
        resellers = {}

        reseller_plans = self._source_data.get_reseller_plans()
        reseller_contacts = self._source_data.get_reseller_contacts()

        for reseller_login, reseller_data in self._target_data.get_resellers().items():
            resellers[reseller_login] = {
                'contact_name': reseller_data['contact_name'],
                'exists_on_target': True,
                'exists_on_source': False,
                'plan': None,
            }

        for reseller_login, reseller_plan in reseller_plans.items():
            if reseller_login in resellers:
                resellers[reseller_login]['exists_on_source'] = True
                continue  # reseller from target has priority
            resellers[reseller_login] = {
                'contact_name': reseller_contacts.get(reseller_login),
                'exists_on_target': False,
                'exists_on_source': True,
                'plan': reseller_plan,
            }

        return resellers

    def _get_plans(self, target_service_plans):
        plans = {}

        source_plans = self._source_data.get_plans(target_service_plans, addon_plans=False)

        for plan_data in self._target_data.get_plans():
            plans[(plan_data['name'], plan_data['owner'])] = {
                'name': plan_data['name'],
                'exists_on_target': True,
                'exists_on_source': False,
                'owner': plan_data['owner']
            }

        for plan_owner, owner_plans in source_plans.items():
            for plan_name, exists_on_target in owner_plans.items():
                if (plan_name, plan_owner) in plans:
                    plans[(plan_name, plan_owner)]['exists_on_source'] = True
                    continue  # plan from target has priority
                plans[(plan_name, plan_owner)] = {
                    'name': plan_name,
                    'exists_on_target': False,
                    'exists_on_source': True,
                    'owner': plan_owner
                }

        return list(plans.values())

    def _get_addon_plans(self, target_addon_service_plans):
        addon_plans = self._source_data.get_plans(target_addon_service_plans, addon_plans=True)

        return [
            {
                'name': plan_name,
                'owner': plan_owner,
                'exists_on_target': exists_on_target
            }
            for plan_owner, owner_plans, in addon_plans.items()
            for plan_name, exists_on_target in owner_plans.items()
        ]
