from maps.wikimap.stat.libs.geobase_regions import (
    FILES as GEOBASE_FILES,
    GEOBASE_JOB_MEMORY_LIMIT_MB,
    mercator_geom_to_region_id,
)
from nile.api.v1 import (
    datetime as nd,
    extractors as ne,
)
from qb2.api.v1 import (
    filters as qf,
    typing,
)

_MODERATION_DELAY_DAYS = 14


def _subtract_moderation_delay(date):
    return nd.next_day(date, offset=-_MODERATION_DELAY_DAYS).decode()


def get_edits_events(commit_event_table, min_action_date):
    '''
    commit_event_table:
    | event_id | type | bounds_geom | primary_object_category_id | created_at | ... |
    |----------+------+-------------+----------------------------+------------+-----|
    | ...      | ...  | ...         | ...                        | ...        | ... |

    result:
    | entity_id | geom        | category_id                |
    |-----------+-------------+----------------------------|
    | commit_id | bounds_geom | primary_object_category_id |
    '''
    return commit_event_table.filter(
        qf.yql_custom('CAST(Yson::ConvertToString(Yson::Parse($p0)) AS Utf8) = \'edit\'', 'type'),
        qf.compare('created_at', '>=', min_action_date),
    ).project(
        entity_id='commit_id',
        geom='bounds_geom',
        category_id='primary_object_category_id',
    )


def get_moderation_tasks(social_task_table, commit_event_table, min_action_date):
    '''
    social_task_table:
    | event_id | primary_object_category_id | resolved_at | closed_at | ... |
    |----------+----------------------------+-------------+-----------+-----|
    | ...      | ...                        | ..          | ...       | ... |

    commit_event_table:
    | event_id | bounds_geom | created_at | ... |
    |----------+-------------+------------+-----|
    | ...      | ...         | ...        | ... |

    result:
    | entity_id | geom        | category_id                |
    |-----------+-------------+----------------------------|
    | event_id  | bounds_geom | primary_object_category_id |
    '''
    tasks = social_task_table.filter(
        qf.or_(
            qf.compare('resolved_at', '>=', min_action_date, default=False),
            qf.compare('closed_at', '>=', min_action_date, default=False),
        )
    ).project(
        entity_id='event_id',
        category_id='primary_object_category_id',
    )

    commit_geom = commit_event_table.filter(
        qf.compare('created_at', '>=', _subtract_moderation_delay(min_action_date))
    ).project(
        entity_id='event_id',
        geom='bounds_geom',
    )

    return tasks.join(
        commit_geom,
        by='entity_id',
        assume_unique_left=True,
        assume_unique_right=True,
    )


def _get_task_id(entity_domain, action, category_id):
    if category_id is None:
        category_id = 'common'
    if entity_domain == 'moderation':
        action = action + 'd'
    return '/'.join((entity_domain, action, category_id))


def add_task_id_region_id(graded_units, geom_and_category):
    '''
    WRN: Should be called for each commit-related entity_domain separately.

    graded_units:
    | entity_id | entity_domain | action | ... |
    |-----------+---------------+--------+-----|
    | ...       | ...           | ...    | ... |

    geom_and_category:
    | entity_id | geom             | category_id |
    |-----------+------------------+-------------|
    | ...       | hex_encoded_ewkb | ...         |

    result:
    | entity_id | action | region_id                        | task_id | ... |
    |-----------+--------+----------------------------------+---------+-----|
    | ...       | ...    | mercator_geom_to_region_id(geom) | ...     | ... |
    '''
    return graded_units.project(
        ne.all(exclude='entity_id'),
        entity_id=ne.custom(int, 'entity_id').with_type(typing.Int64),
    ).join(
        geom_and_category,
        by='entity_id',
        type='left',
        assume_small_left=True,
        assume_unique_left=True,
        assume_unique_right=True,
    ).project(
        ne.all(exclude=('category_id', 'geom', 'entity_id')),
        entity_id=ne.custom(str, 'entity_id').with_type(typing.Unicode),
        region_id=ne.custom(mercator_geom_to_region_id, 'geom').with_type(typing.Int64),
        task_id=ne.custom(_get_task_id, 'entity_domain', 'action', 'category_id').with_type(typing.Unicode),
        memory_limit=GEOBASE_JOB_MEMORY_LIMIT_MB,
        files=GEOBASE_FILES,
    )
