import pytest
import re
from maps.wikimap.stat.tasks_payment.tasks_logging.outsource.lib.outsource_log import make_job
from nile.drivers.common.progress import CommandFailedError
from nile.api.v1 import (
    local,
    clusters,
    Record
)


@pytest.fixture
def geometry():
    return b'POLYGON (('\
        b'2.3255418688678313 48.8198807556526404,'\
        b'2.3143946082019293 48.8223674617638679,'\
        b'2.3128711134814659 48.8214464739695089,'\
        b'2.3255418688678313 48.8198807556526404'\
        b'))'


@pytest.fixture
def bbox():
    return {
        'lon_min': 2.3128711134814659,
        'lon_max': 2.3255418688678313,
        'lat_min': 48.8198807556526404,
        'lat_max': 48.8223674617638679
    }


@pytest.fixture
def geom():
    return b'0103000020e61000000100000004000000e22002b2b59a0240ed1244daf1684840cf200252e18302'\
        b'4001c9445643694840c5200292c2800240898e762825694840e22002b2b59a0240ed1244daf1684840'


@pytest.fixture
def undefined_bbox():
    return {
        'lon_min': None,
        'lon_max': None,
        'lat_min': None,
        'lat_max': None
    }


def run_job(outsource_payments, outsource_dump, users_dump):
    cluster = clusters.MockCluster()
    job = make_job(cluster.job(), '2020-02-02', 'logs_path', 'results_path')

    result = []
    job.local_run(
        sources={
            'nmaps-outsource-regions-payments-log': local.StreamSource(outsource_payments),
            'nmaps-outsource-regions-dump-log': local.StreamSource(outsource_dump),
            'nmaps-users-dump-log': local.StreamSource(users_dump)
        },
        sinks={
            'result': local.ListSink(result)
        }
    )

    return result


@pytest.mark.parametrize(
    'complexity_rate,task_id_suffix',
    [
        (b'1.000000', b'1'),
        (b'1.500000', b'1.5'),
        (b'2.000000', b'2'),
        (b'3.000000', b'3'),
    ]
)
def test_regular_records(geometry, geom, bbox, complexity_rate, task_id_suffix):
    result = run_job(
        outsource_payments=[
            Record(
                region_id=b'111',
                task_type=b'bld_drawing',
                work_amount=b'1.0',
                complexity_rate=complexity_rate,
                iso_eventtime=b'2020-02-02 10:36:09',
                outsourcer_login=b'ivan'
            )
        ],
        outsource_dump=[
            Record(object_id=b'111', geometry=geometry)
        ],
        users_dump=[
            Record(puid=b'123', um_login=b'ivan')
        ]
    )

    assert result == [
        Record(
            iso_datetime=b'2020-02-02T10:36:09+03:00',
            puid=123,
            task_id=b'outsource/bld_drawing/' + task_id_suffix,
            quantity=1.0,
            **bbox,
            geom=geom
        )
    ]


@pytest.mark.parametrize(
    'complexity_rate',
    [
        # unexpected values
        b'0.500000',
        b'0.999999',
        b'1.000001',
        b'2.500000',
        b'3.500000',
        b'4.000000',

        # unexpected format
        b'1.00000',
        b'1.0000000'
    ]
)
def test_fail_on_unexpected_complexity_rate(geometry, complexity_rate):
    re_errmsg = 'Unexpected complexity_rate value: ' + re.escape(complexity_rate.decode('utf8'))
    with pytest.raises(CommandFailedError, match=re_errmsg):
        result = run_job(
            outsource_payments=[
                Record(
                    region_id=b'111',
                    task_type=b'bld_drawing',
                    work_amount=b'1.0',
                    complexity_rate=complexity_rate,
                    iso_eventtime=b'2020-02-02 10:36:09',
                    outsourcer_login=b'ivan'
                )
            ],
            outsource_dump=[
                Record(object_id=b'111', geometry=geometry)
            ],
            users_dump=[
                Record(puid=b'123', um_login=b'ivan')
            ]
        )
        print(result)


def test_ignore_records_with_empty_outsourcer_login(geometry):
    result = run_job(
        outsource_payments=[
            Record(
                region_id=b'111',
                task_type=b'bld_drawing',
                work_amount=b'1.0',
                complexity_rate=b'1.500000',
                iso_eventtime=b'2020-02-02 10:36:09',
                outsourcer_login=b''
            )
        ],
        outsource_dump=[
            Record(object_id=b'111', geometry=geometry)
        ],
        users_dump=[
            Record(puid=b'123', um_login=b'')
        ]
    )

    assert [] == result


def test_no_puid_for_unknown_user(geometry, geom, bbox):
    # Actually, causes job to fail as puid column is not optional in CARTOGRAPHIC_TASKS_LOG_SCHEMA
    result = run_job(
        outsource_payments=[
            Record(
                region_id=b'111',
                task_type=b'bld_drawing',
                work_amount=b'1.0',
                complexity_rate=b'1.500000',
                iso_eventtime=b'2020-02-02 10:36:09',
                outsourcer_login=b'ivan'
            )
        ],
        outsource_dump=[
            Record(object_id=b'111', geometry=geometry)
        ],
        users_dump=[
            Record(puid=b'123', um_login=b'petr')
        ]
    )

    assert [
        Record(
            iso_datetime=b'2020-02-02T10:36:09+03:00',
            puid=None,
            task_id=b'outsource/bld_drawing/1.5',
            quantity=1.0,
            **bbox,
            geom=geom
        )
    ] == result


def test_maps_outsource_region_with_no_geometry_to_undefined_bbox(undefined_bbox):
    result = run_job(
        outsource_payments=[
            Record(
                region_id=b'111',
                task_type=b'bld_drawing',
                work_amount=b'1.0',
                complexity_rate=b'1.500000',
                iso_eventtime=b'2020-02-02 10:36:09',
                outsourcer_login=b'ivan',
            )
        ],
        outsource_dump=[
            Record(object_id=b'111', geometry=None)
        ],
        users_dump=[
            Record(puid=123, um_login=b'ivan')
        ]
    )

    assert [
        Record(
            iso_datetime=b'2020-02-02T10:36:09+03:00',
            puid=123,
            task_id=b'outsource/bld_drawing/1.5',
            quantity=1.0,
            **undefined_bbox,
            geom=None
        )
    ] == result
