from datetime import datetime
from typing import List, Mapping, Union

from yt.yson import YsonUint64

from maps_adv.common.yt_utils import BaseYtExportTask, BaseYtImportDirWithYqlTask
from maps_adv.config_loader import Config

from ..data_manager import BaseDataManager, yqls
from ..enums import EventDataSource, EventType, Source

__all__ = ["LeadEventsYtImportTask", "LeadsYtExportTask"]


MAP_YT_TO_ENUM = {
    "event_type": {
        "review": EventType.REVIEW,
        "click_on_phone": EventType.CLICK_ON_PHONE,
        "open_site": EventType.OPEN_SITE,
        "make_route": EventType.MAKE_ROUTE,
        "view_working_hours": EventType.VIEW_WORKING_HOURS,
        "view_entrances": EventType.VIEW_ENTRANCES,
        "cta_button_click": EventType.CTA_BUTTON_CLICK,
        "favourite_click": EventType.FAVOURITE_CLICK,
        "location_sharing": EventType.LOCATION_SHARING,
        "booking_section_interaction": EventType.BOOKING_SECTION_INTERACTION,
        "showcase_product_click": EventType.SHOWCASE_PRODUCT_CLICK,
        "promo_to_site": EventType.PROMO_TO_SITE,
        "geoproduct_button_click": EventType.GEOPRODUCT_BUTTON_CLICK,
    },
    "event_source": {
        "sprav": EventDataSource.SPRAV,
        "mobile": EventDataSource.MOBILE,
        "desktop_maps": EventDataSource.DESKTOP_MAPS,
    },
    "source": {
        "external_advert": Source.EXTERNAL_ADVERT,
        "straight": Source.STRAIGHT,
        "discovery_advert": Source.DISCOVERY_ADVERT,
        "discovery_no_advert": Source.DISCOVERY_NO_ADVERT,
    },
}


class LeadEventsYtImportTask(BaseYtImportDirWithYqlTask):
    YQL = yqls.list_lead_events_template
    ITER_SIZE: int = 10000
    CHUNKED_WRITER_METHOD_NAME = "import_events_from_generator"

    def __init__(self, *args, config: Mapping, dm: BaseDataManager, **kwargs):
        super().__init__(
            cluster=config["YT_CLUSTER"],
            yt_token=config["YT_TOKEN"],
            yql_token=config["YQL_TOKEN"],
            yt_dir=config["EVENTS_DIR_YT_IMPORT_TABLE"],
            data_consumer=dm,
        )

    @classmethod
    def _yt_row_decode(cls, row: List[Union[str, YsonUint64]]) -> List[Union[str, int]]:
        return [
            int(row[0]),
            MAP_YT_TO_ENUM["event_type"][row[1]].name,
            datetime.strptime(row[2], "%Y-%m-%d %H:%M:%S"),
            MAP_YT_TO_ENUM["event_source"][row[3]].name,
            row[4],
            str(row[5]) if row[5] else None,
            str(row[6]) if row[6] else None,
            str(row[7]) if row[7] else None,
            str(row[8]) if row[8] else None,
            int(row[9]),
            MAP_YT_TO_ENUM["source"][row[10]].name,
        ]


class LeadsYtExportTask(BaseYtExportTask):
    TABLE_SCHEMA = [
        dict(name="biz_id", type="uint64", required=True),
        dict(name="promoter_id", type="uint64", required=True),
        dict(name="name", type="string", required=False),
        dict(name="passport_uid", type="string", required=False),
        dict(name="yandex_uid", type="string", required=False),
        dict(name="device_id", type="string", required=False),
        dict(name="segments", type_v3={"type_name": "list", "item": "string"}),
    ]

    ITER_SIZE: int = 500000
    CHUNKED_ITERATOR_METHOD_NAME: str = "iter_leads_for_export"
    TIMEOUT: int = 7000

    def __init__(self, *args, config: Config, dm: BaseDataManager, **kwargs):
        super().__init__(
            cluster=config["YT_CLUSTER"],
            token=config["YT_TOKEN"],
            table=config["LEADS_YT_EXPORT_TABLE"],
            data_producer=dm,
        )
