select_unprocessed_start_and_end_of_packet = """
-- tag: select_unprocessed_start_and_end_of_packet
    SELECT
        toUnixTimestamp(  -- Start packet time
            multiIf(
                any(_timestamp) > 0, min(_timestamp),
                NULL
            )
        ),
        toUnixTimestamp(now())  -- End packet time
    FROM maps_adv_statistics_raw_metrika_log_distributed
    WHERE _timestamp > (
        SELECT max(receive_timestamp)
        FROM normalized_events_distributed
    )
    SETTINGS distributed_product_mode='global'
"""

normalize = """
-- tag: normalize
    INSERT INTO normalized_events_distributed (
         receive_timestamp,
         event_name,
         campaign_id,
         event_group_id,
         application,
         device_id,
         app_platform,
         app_version_name,
         app_build_number,
         user_latitude,
         user_longitude,
         place_id,
         _normalization_metadata
    )
    SELECT
        _timestamp,
        multiIf(
            EventName = 'geoadv.bb.pin.show', 'BILLBOARD_SHOW',
            EventName = 'geoadv.bb.pin.tap', 'BILLBOARD_TAP',
            EventName = 'geoadv.bb.action.makeRoute', 'ACTION_MAKE_ROUTE',
            EventName = 'geoadv.bb.action.call', 'ACTION_CALL',
            EventName = 'geoadv.bb.action.openSite', 'ACTION_OPEN_SITE',
            EventName = 'geoadv.bb.action.search', 'ACTION_SEARCH',
            EventName = 'geoadv.bb.action.saveOffer', 'ACTION_SAVE_OFFER',
            NULL
        ),
        CampaignID,
        EventGroupId,
        multiIf(
            APIKey = 2, 'METRO',
            APIKey = 4, 'MOBILE_MAPS',
            APIKey = 30488, 'NAVIGATOR',
            NULL
        ),
        DeviceID,
        multiIf(
            AppPlatform = 'iOS', 'IOS',
            AppPlatform = 'android', 'ANDROID',
            NULL
        ),
        AppVersionName,
        AppBuildNumber,
        Latitude,
        Longitude,
        NULL,
        %(metadata_datatube)s
    FROM maps_adv_statistics_raw_metrika_log_distributed
    WHERE
        APIKey IN (2, 4, 30488)
        AND _timestamp BETWEEN %(timestamp_start)s AND %(timestamp_end)s
        AND CampaignID != 0
"""

select_unprocessed_start_and_end_of_packet_for_mapkit_and_appmetric = """
-- tag: select_unprocessed_start_and_end_of_packet_for_mapkit_and_appmetric
SELECT min(start_packet_time), -- Start packet time
       toUnixTimestamp(now())  -- End packet time
FROM (
    SELECT
        toUnixTimestamp(
            multiIf(
                any(_timestamp) > 0, min(_timestamp),
                NULL
            )
        ) AS start_packet_time
    FROM maps_adv_statistics_raw_metrika_log_distributed
    WHERE _timestamp > (
        SELECT max(receive_timestamp) FROM normalized_events_distributed
    )

    UNION ALL
    SELECT
        toUnixTimestamp(
            multiIf(
                any(receive_time) > 0, min(receive_time),
                NULL
            )
        ) AS start_packet_time
    FROM mapkit_events_distributed
    WHERE receive_time > (
        SELECT max(receive_timestamp) FROM normalized_events_distributed
    )
    SETTINGS distributed_product_mode='global'
)
"""


def normalize_app_metric_and_mapkit(
    normalized_events_table_name: str, recognised_apps: dict
):
    return f"""
-- tag: normalize_app_metric_and_mapkit
INSERT INTO normalized_events_distributed (
     receive_timestamp,
     event_name,
     campaign_id,
     event_group_id,
     application,
     device_id,
     app_platform,
     app_version_name,
     app_build_number,
     user_latitude,
     user_longitude,
     place_id,
     _normalization_metadata
)
    -- for app metric source
    SELECT
        _timestamp AS receive_timestamp,
        multiIf(
            EventName = 'geoadv.bb.pin.show', 'BILLBOARD_SHOW',
            EventName = 'geoadv.bb.pin.tap', 'BILLBOARD_TAP',
            EventName = 'geoadv.bb.action.makeRoute', 'ACTION_MAKE_ROUTE',
            EventName = 'geoadv.bb.action.call', 'ACTION_CALL',
            EventName = 'geoadv.bb.action.openSite', 'ACTION_OPEN_SITE',
            EventName = 'geoadv.bb.action.search', 'ACTION_SEARCH',
            EventName = 'geoadv.bb.action.saveOffer', 'ACTION_SAVE_OFFER',
            NULL
        ) AS event_name,
        CampaignID AS campaign_id,
        EventGroupId AS event_group_id,
        multiIf(
            APIKey = 2, 'METRO',
            APIKey = 4, 'MOBILE_MAPS',
            APIKey = 30488, 'NAVIGATOR',
            NULL
        ) AS application,
        DeviceID AS device_id,
        multiIf(
            AppPlatform = 'iOS', 'IOS',
            AppPlatform = 'android', 'ANDROID',
            NULL
        ) AS app_platform,
        AppVersionName AS app_version_name,
        AppBuildNumber AS app_build_number,
        Latitude AS user_latitude,
        Longitude AS user_longitude,
        NULL AS place_id,
        %(metadata_datatube)s AS _normalization_metadata
    FROM maps_adv_statistics_raw_metrika_log_distributed
    WHERE APIKey IN (2, 4, 30488)
      AND receive_timestamp BETWEEN %(timestamp_start)s AND %(timestamp_end)s
      AND campaign_id != 0
      AND ( -- Нужно для фильтрации логов, что они не пересекались из mapkit-а и appmetric-и
                 (application = 'NAVIGATOR'   AND app_platform = 'IOS'     AND app_build_number < %(ios_navi_build)d)
              OR (application = 'NAVIGATOR'   AND app_platform = 'ANDROID' AND app_build_number < %(android_navi_build)d)
              OR (application = 'MOBILE_MAPS' AND app_platform = 'IOS'     AND app_build_number < %(ios_maps_build)d)
              OR (application = 'MOBILE_MAPS' AND app_platform = 'ANDROID' AND app_build_number < %(android_maps_build)d)
              OR (application = 'METRO'       AND app_platform = 'IOS'     AND app_build_number < %(ios_metro_build)d)
              OR (application = 'METRO'       AND app_platform = 'ANDROID' AND app_build_number < %(android_metro_build)d)
          )

    -- for mapkit source
    UNION ALL
    WITH
        36500 as CAMPAIGN_ID_AT_DEPLOY_START,
        toDateTime('2022-06-21', 'UTC') as DEPLOY_START_TIME,
        toUInt64(toDateTime(0) + INTERVAL 50 DAY) as DEPLOY_DURATION_SEC,
        event_name='BILLBOARD_SHOW' AND (
            campaign_id %% 5 = 0 OR
            campaign_id >= CAMPAIGN_ID_AT_DEPLOY_START OR
            sipHash64(event_group_id) %% DEPLOY_DURATION_SEC < receive_timestamp - DEPLOY_START_TIME
        ) AS need_filter,
        normalized_events_with_key AS (
            SELECT
                (rowNumberInBlock(),event_group_id) AS key,
                receive_time AS receive_timestamp,
                multiIf(
                    event = 'billboard.show', 'BILLBOARD_SHOW',
                    event = 'billboard.click', 'BILLBOARD_TAP',
                    event = 'billboard.navigation.via', 'ACTION_MAKE_ROUTE',
                    event = 'billboard.action.call', 'ACTION_CALL',
                    event = 'billboard.action.Call', 'ACTION_CALL',
                    event = 'billboard.action.open_site', 'ACTION_OPEN_SITE',
                    event = 'billboard.action.OpenSite', 'ACTION_OPEN_SITE',
                    event = 'billboard.action.open_app', 'ACTION_OPEN_APP',
                    event = 'billboard.action.save_offer', 'ACTION_SAVE_OFFER',
                    event = 'billboard.action.search', 'ACTION_SEARCH',
                    NULL
                ) AS event_name,
                toUInt64OrNull(JSONExtractString(log_id, 'campaignId')) AS campaign_id,
                event_group_id,
                multiIf(
                    {''.join("startsWith(user_agent, '{}/'), '{}',".format(k, v) for k, v in recognised_apps.items())}
                    NULL
                ) AS application,
                device_id,
                multiIf(
                    positionCaseInsensitive(user_agent, 'iphoneos/') > 0, 'IOS',
                    positionCaseInsensitive(user_agent, 'android/') > 0, 'ANDROID',
                    NULL
                ) AS app_platform,
                replaceRegexpOne(
                    splitByChar('/', splitByChar(' ', user_agent)[1])[2],
                    '^(.+)\\\\.[0-9]+$',
                    '\\\\1'
                ) AS app_version_name,
                toUInt32OrNull(
                    replaceRegexpOne(
                        splitByChar('/', splitByChar(' ', user_agent)[1])[2],
                        '^.+\\\\.([0-9]+)$',
                         '\\\\1'
                    )
                ) AS app_build_number,
                user_lat AS user_latitude,
                user_lon AS user_longitude,
                if(place_id = '', NULL, place_id) AS place_id
            FROM mapkit_events_distributed
            WHERE receive_timestamp BETWEEN %(timestamp_start)s AND %(timestamp_end)s
              AND campaign_id IS NOT NULL
              AND event_name IS NOT NULL
              AND app_platform IS NOT NULL
              AND application IS NOT NULL
              AND app_build_number IS NOT NULL
              AND ( -- Нужно для фильтрации событий, что они не пересекались из mapkit-а и appmetric-и
                         (application = 'NAVIGATOR'   AND app_platform = 'IOS'     AND app_build_number >= %(ios_navi_build)d)
                      OR (application = 'NAVIGATOR'   AND app_platform = 'ANDROID' AND app_build_number >= %(android_navi_build)d)
                      OR (application = 'MOBILE_MAPS' AND app_platform = 'IOS'     AND app_build_number >= %(ios_maps_build)d)
                      OR (application = 'MOBILE_MAPS' AND app_platform = 'ANDROID' AND app_build_number >= %(android_maps_build)d)
                      OR (application = 'METRO'       AND app_platform = 'IOS'     AND app_build_number >= %(ios_metro_build)d)
                      OR (application = 'METRO'       AND app_platform = 'ANDROID' AND app_build_number >= %(android_metro_build)d)
                  )
        ),
        recently_normalized_event_group_ids AS (
            SELECT
                event_group_id
            FROM normalized_events_distributed
            WHERE need_filter AND receive_timestamp BETWEEN %(deduplication_window_start)s AND %(deduplication_window_end)s
        ),
        selected_keys AS (
            SELECT
                min(key)
            FROM normalized_events_with_key
            WHERE need_filter AND event_group_id NOT IN recently_normalized_event_group_ids
            GROUP BY event_group_id
        )
    SELECT
        receive_timestamp,
        event_name,
        campaign_id,
        event_group_id,
        application,
        device_id,
        app_platform,
        app_version_name,
        app_build_number,
        user_latitude,
        user_longitude,
        place_id,
        %(metadata_mapkit)s AS _normalization_metadata
    FROM normalized_events_with_key
    WHERE NOT need_filter OR key IN selected_keys
"""  # noqa: E501


__all__ = ["normalize", "select_unprocessed_start_and_end_of_packet"]
