from typing import Dict, Hashable, List

from maps_adv.export.lib.core.client import OldGeoAdvClient
from maps_adv.export.lib.core.client.old_geoadv import OrgPlace
from maps_adv.export.lib.core.enum import ActionType, CampaignType, CreativeType


class OrganizationResolver:
    def __init__(self, client: OldGeoAdvClient):
        self._client = client

    async def __call__(self, campaigns: list, places: dict):
        permalinks = self._extract_permalinks(campaigns)
        organizations = await self._client(permalinks)
        places.update(self._resolve(campaigns, organizations))

    @staticmethod
    def _extract_permalinks(campaigns: list) -> List[int]:
        permalinks = set()
        for campaign in campaigns:
            creatives = campaign["creatives"]

            if campaign["placing"].get("organizations"):
                permalinks.update(campaign["placing"]["organizations"]["permalinks"])

            if CreativeType.PIN_SEARCH in creatives:
                for creative in creatives[CreativeType.PIN_SEARCH]:
                    permalinks.update(creative["organizations"])

            if CreativeType.ICON in creatives:
                creative = creatives[CreativeType.ICON]
                permalinks.update(creative["organizations"])

            for action in campaign["actions"]:
                if action["type"] == ActionType.SEARCH:
                    permalinks.update(action["organizations"])

        return list(permalinks)

    def _resolve(self, campaigns: list, organizations: Dict[int, OrgPlace]):
        places = {}
        for campaign in campaigns:
            creatives = campaign["creatives"]
            campaign_organizations = {}

            if campaign["placing"].get("organizations"):
                campaign_organizations = self._extract_subdict(
                    organizations, campaign["placing"]["organizations"]["permalinks"]
                )

                campaign_places = {}
                if campaign["campaign_type"] != CampaignType.CATEGORY:
                    campaign_places = {
                        f"altay:{id_}": info
                        for id_, info in campaign_organizations.items()
                    }

                places.update(campaign_places)
                campaign["places"].extend(campaign_places.keys())

            if "organizations" in campaign["placing"]:
                campaign["placing"]["organizations"] = campaign_organizations

            if CreativeType.PIN_SEARCH in creatives:
                for creative in creatives[CreativeType.PIN_SEARCH]:
                    creative["organizations"] = self._extract_subdict(
                        organizations, creative["organizations"]
                    )

            if CreativeType.ICON in creatives:
                creative = creatives[CreativeType.ICON]
                creative["organizations"] = self._extract_subdict(
                    organizations, creative["organizations"]
                )

            for action in campaign["actions"]:
                if action["type"] == ActionType.SEARCH:
                    action["organizations"] = self._extract_subdict(
                        organizations, action["organizations"]
                    )

        return places

    @staticmethod
    def _extract_subdict(data: dict, extracted_keys: List[Hashable]) -> dict:
        return {key: data[key] for key in extracted_keys if key in data}
