from maps.wikimap.stat.assessment.report.lib import feedback

from maps.wikimap.stat.libs import nile_ut

from nile.api.v1 import Record
from yt.yson import to_yson_type

import pytest


def test_should_get_assessed_tasks():
    result = nile_ut.yt_run(
        feedback._get_assessed_tasks,
        feedback_table=nile_ut.Table([
            Record(id=1, position=b'position 1', source=b'source 1', type=b'type 1', resolution=b'fb resolution 1', test_column=1),
            Record(id=2, position=b'position 2', source=b'source 2', type=b'type 2', resolution=b'fb resolution 2', test_column=2),
            Record(id=3, position=b'position 3', source=b'source 3', type=b'type 3', resolution=b'fb resolution 3', test_column=3),
        ]),
        latest_grades=nile_ut.Table([
            Record(entity_id=b'1', action_by=1,  action=b'action 1',  graded_by=101, grade=b'grade 1'),
            Record(entity_id=b'2', action_by=21, action=b'action 21', graded_by=121, grade=b'grade 21'),
            Record(entity_id=b'2', action_by=22, action=b'action 22', graded_by=122, grade=b'grade 22'),
            Record(entity_id=b'4', action_by=4,  action=b'action 4',  graded_by=104, grade=b'grade 4'),
        ])
    )

    assert sorted([
        Record(position=b'position 1', source=b'source 1', type=b'type 1', action_by=1,  action=b'action 1',  graded_by=101, grade=b'grade 1'),
        Record(position=b'position 2', source=b'source 2', type=b'type 2', action_by=21, action=b'action 21', graded_by=121, grade=b'grade 21'),
        Record(position=b'position 2', source=b'source 2', type=b'type 2', action_by=22, action=b'action 22', graded_by=122, grade=b'grade 22'),
    ]) == sorted(result)


def test_should_get_paid_tasks_at_date():
    result = nile_ut.yt_run(
        feedback._get_paid_tasks_at_date,
        '2020-07-28',
        feedback_table=nile_ut.Table([
            Record(id=1, position=b'position 1', source=b'source 1', type=b'type 1', commit_ids=to_yson_type([]), history=to_yson_type(
                [
                    {b'operation': b'non-paid', b'modifiedBy': 11, b'modifiedAt': b'2020-07-28 01:01:01+01:01'},
                    {b'operation': b'accept',   b'modifiedBy': 12, b'modifiedAt': b'2020-07-28 01:01:01+01:01'},
                ]
            )),
            Record(id=2, position=b'position 2', source=b'source 2', type=b'type 2', commit_ids=to_yson_type([]), history=to_yson_type(
                [
                    {b'operation': b'reject', b'modifiedBy': 21, b'modifiedAt': b'2020-07-28 02:02:02+02:02'},
                ]
            )),
        ]),
        social_commit_event=nile_ut.Table([])
    )

    assert sorted([
        Record(position=b'position 1', source=b'source 1', type=b'type 1', action_by=12, action=b'accept'),
        Record(position=b'position 2', source=b'source 2', type=b'type 2', action_by=21, action=b'reject'),
    ]) == sorted(result)


def test_should_convert_source_type_to_task_id():
    result = nile_ut.yt_run(
        feedback._source_type_to_task_id,
        feedback_tasks=nile_ut.Table([
            Record(region_name_tree=b'region', source=b'source', type=b'type', action_by=1, action=b'accept', graded_by=11, grade=b'grade'),
        ])
    )

    assert sorted([
        Record(region_name_tree=b'region', task_id=b'feedback/accept/source/type', action_by=1, action=b'accept', graded_by=11, grade=b'grade'),
    ]) == sorted(result)


def test_should_convert_position_to_lat_lon():
    result = nile_ut.yt_run(
        feedback._position_to_lat_lon,
        nile_ut.Table([
            # first element is longitude, second element is latitude
            Record(test_column=1, position=to_yson_type([11, 12])),
            Record(test_column=2, position=None),
            Record(test_column=3),
        ])
    )

    assert sorted([
        Record(test_column=1, lat=12,   lon=11),
        Record(test_column=2, lat=None, lon=None),
        Record(test_column=3, lat=None, lon=None),
    ]) == sorted(result)


def test_should_not_convert_position_to_lat_lon_if_position_is_incorrect():
    from nile.drivers.common.progress import CommandFailedError

    # Too many coordinates
    with pytest.raises(CommandFailedError):
        nile_ut.yt_run(
            feedback._position_to_lat_lon,
            nile_ut.Table([Record(test_column=1, position=to_yson_type([1, 2, 3]))])
        )

    # Too few coordinates
    with pytest.raises(CommandFailedError):
        nile_ut.yt_run(
            feedback._position_to_lat_lon,
            nile_ut.Table([Record(test_column=1, position=to_yson_type([1]))])
        )

    # Wrong type
    with pytest.raises(CommandFailedError):
        nile_ut.yt_run(
            feedback._position_to_lat_lon,
            nile_ut.Table([Record(test_column=1, position=b'position')])
        )


def test_should_get_tasks():
    result = nile_ut.yt_run(
        feedback.get_tasks,
        nile_ut.Job(),
        '2020-07-28',
        latest_grades=nile_ut.Table([
            Record(entity_id=b'1', action_by=12, action=b'accept', graded_by=101, grade=b'grade 1'),
            Record(entity_id=b'1', action_by=12, action=b'accept', graded_by=102, grade=b'grade 2'),
        ]),
        feedback_table=nile_ut.Table([
            Record(id=1, position=to_yson_type([11, 12]), source=b'source 1', type=b'type 1', commit_ids=to_yson_type([]), history=to_yson_type(
                [
                    {b'operation': b'non-paid', b'modifiedBy': 11, b'modifiedAt': b'2020-07-28 01:01:01+01:01'},
                    {b'operation': b'accept',   b'modifiedBy': 12, b'modifiedAt': b'2020-07-28 01:01:01+01:01'},
                ]
            )),
            Record(id=2, position=to_yson_type([21, 22]), source=b'source 2', type=b'type 2', commit_ids=to_yson_type([]), history=to_yson_type(
                [
                    {b'operation': b'reject', b'modifiedBy': 21, b'modifiedAt': b'2020-07-28 02:02:02+02:02'},
                ]
            )),
        ]),
        social_commit_event=nile_ut.Table([])
    )

    assert sorted([
        # Assessed tasks
        Record(lat=12, lon=11, task_id=b'feedback/accept/source 1/type 1', action_by=12, action=b'accept', graded_by=101, grade=b'grade 1'),
        Record(lat=12, lon=11, task_id=b'feedback/accept/source 1/type 1', action_by=12, action=b'accept', graded_by=102, grade=b'grade 2'),
        # Paid tasks
        Record(lat=12, lon=11, task_id=b'feedback/accept/source 1/type 1', action_by=12, action=b'accept', graded_by=None, grade=None),
        Record(lat=22, lon=21, task_id=b'feedback/reject/source 2/type 2', action_by=21, action=b'reject', graded_by=None, grade=None),
    ]) == sorted(result)
