from maps.wikimap.stat.arm.objects_count.lib.eval_report import (
    make_job,
    make_testable_job
)
from nile.api.v1 import (
    clusters,
    datetime as nd,
    statface as ns,
    local as nl,
    Record,
)


def test_smoke():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_job(
        job,
        list(nd.date_range('2019-10-01', '2019-10-01', step=1, stringify=False)),
        ns.StatfaceBetaClient(),
        '2019-10-01',
    )
    job.local_run(
        sources={},
        sinks={},
    )


def test_versions_fielddate_1():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-11-25', '2019-11-28', step=1, stringify=False)),
        'not used date-string'
    )
    versions_input = [
        Record(
            modified_at=1574743355,  # Вт ноя 26 07:42:35 MSK 2019
            next_version_at=1574894555,  # Чт ноя 28 01:42:35 MSK 2019 == Ср ноя 27 22:42:35 UTC 2019
            start_at=1574743355,  # Вт ноя 26 07:42:35 MSK 2019
            end_at=1574894555,  # Чт ноя 28 01:42:35 MSK 2019 == Ср ноя 27 22:42:35 UTC 2019
            object_id=1,
            object_type='closure',
            version=0,
            geometry_len_meters=0,
        ),
    ]
    output = []
    job.local_run(
        sources={'versions': nl.StreamSource(versions_input)},
        sinks={'versions_ofd': nl.ListSink(output)},
    )
    correct = [
        Record(
            fielddate=fd,
            object_id=1,
            object_type='closure',
            length=0,
        ) for fd in ['2019-11-26', '2019-11-27']
    ]
    assert output == correct


def test_versions_fielddate_2():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2020-01-23', '2020-01-23', step=1, stringify=False)),
        'not used date-string'
    )
    NOON = 1579780800  # Чт янв 23 12:00:00 UTC 2020
    HOUR = 3600
    DAY = HOUR*24
    versions_input = [
        # object 1
        Record(
            modified_at=NOON-DAY,
            next_version_at=NOON,
            start_at=NOON-DAY+HOUR,
            end_at=NOON-DAY+2*HOUR,
            object_id=1,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
        # object 2
        Record(
            modified_at=NOON,
            next_version_at=None,
            start_at=NOON+DAY,
            end_at=NOON+DAY+HOUR,
            object_id=2,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
        # object 3
        Record(
            modified_at=NOON-5*HOUR,
            next_version_at=NOON,
            start_at=NOON-4*HOUR,
            end_at=NOON-3*HOUR,
            object_id=3,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
        Record(
            modified_at=NOON,
            next_version_at=NOON+5*HOUR,
            start_at=NOON+HOUR,
            end_at=NOON+2*HOUR,
            object_id=3,
            version=1,
            object_type='closure',
            geometry_len_meters=0,
        ),
        # object 4
        Record(
            modified_at=NOON-DAY,
            next_version_at=NOON,
            start_at=NOON+HOUR,
            end_at=None,
            object_id=4,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
        # object 5
        Record(
            modified_at=NOON,
            next_version_at=None,
            start_at=NOON+HOUR,
            end_at=NOON+DAY,
            object_id=5,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
    ]
    output = []
    job.local_run(
        sources={'versions': nl.StreamSource(versions_input)},
        sinks={'versions_ofd': nl.ListSink(output)},
    )

    correct = [
        Record(
            fielddate='2020-01-23',
            object_id=3,
            object_type='closure',
            length=0,
        ),
        Record(
            fielddate='2020-01-23',
            object_id=5,
            object_type='closure',
            length=0,
        ),
    ]
    assert output == correct


def test_versions_fielddate_3():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2020-01-23', '2020-01-24', step=1, stringify=False)),
        'not used date-string'
    )
    NOON = 1579780800  # Чт янв 23 12:00:00 UTC 2020
    HOUR = 3600
    DAY = HOUR*24
    versions_input = [
        # object 1
        Record(
            modified_at=NOON-DAY,
            next_version_at=NOON,
            start_at=NOON-DAY+HOUR,
            end_at=NOON+2*DAY,
            object_id=1,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
        Record(
            modified_at=NOON,
            next_version_at=NOON+DAY,
            start_at=NOON-DAY+HOUR,
            end_at=NOON+2*DAY,
            object_id=1,
            version=1,
            object_type='closure',
            geometry_len_meters=0,
        ),
        Record(
            modified_at=NOON+DAY,
            next_version_at=None,
            start_at=NOON-DAY+HOUR,
            end_at=NOON+2*DAY,
            object_id=1,
            version=2,
            object_type='closure',
            geometry_len_meters=0,
        ),
        # object 2
        Record(
            modified_at=NOON-DAY,
            next_version_at=NOON,
            start_at=NOON-DAY+HOUR,
            end_at=NOON-HOUR,
            object_id=2,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
        Record(
            modified_at=NOON,
            next_version_at=None,
            start_at=NOON+HOUR,
            end_at=NOON+DAY,
            object_id=2,
            version=1,
            object_type='closure',
            geometry_len_meters=0,
        ),
        # object 3
        Record(
            modified_at=NOON-DAY,
            next_version_at=NOON,
            start_at=NOON-DAY+HOUR,
            end_at=NOON-HOUR,
            object_id=3,
            version=0,
            object_type='closure',
            geometry_len_meters=0,
        ),
        Record(
            modified_at=NOON,
            next_version_at=None,
            start_at=NOON+DAY-HOUR,
            end_at=NOON+DAY,
            object_id=3,
            version=1,
            object_type='closure',
            geometry_len_meters=0,
        ),
    ]
    output = []
    job.local_run(
        sources={'versions': nl.StreamSource(versions_input)},
        sinks={'versions_ofd': nl.ListSink(output)},
    )

    correct = [
        Record(
            fielddate='2020-01-23',
            object_id=obj_id,
            object_type='closure',
            length=0,
        ) for obj_id in [1, 2, 3]
    ] + [
        Record(
            fielddate='2020-01-24',
            object_id=obj_id,
            object_type='closure',
            length=0,
        ) for obj_id in [1, 2, 3]
    ]
    assert output == correct


def test_add_fiedldate_1():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-11-25', '2019-11-28', step=1, stringify=False)),
        'not used date-string'
    )
    objects_input = [Record(
        created_at=1574743355,  # Вт ноя 26 07:42:35 MSK 2019
        deleted_at=1574894555,  # Чт ноя 28 01:42:35 MSK 2019 == Ср ноя 27 22:42:35 UTC 2019
        object_id=16105,
        object_type='closure-template'.encode('utf-8'),
        region_id='103544',
        template_id=None,
        category='no-transit'.encode('utf-8'),
        fake=False,
        geometry_len_meters=0,
    )]
    output = []
    job.local_run(
        sources={'objects': nl.StreamSource(objects_input)},
        sinks={'objects_ofd': nl.ListSink(output)},
    )
    correct = [
        Record(
            fielddate=fd,
            object_id=16105,
            object_type=obj_type,
            region_id='103544',
            length=0,
        ) for obj_type in ['\t_total_\t', '\t_total_\ttemplate\t'] for fd in ['2019-11-26', '2019-11-27']
    ]
    assert output == correct


def test_add_fiedldate_2():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-10-28', '2019-10-28', step=1, stringify=False)),
        'not used date-string'
    )
    objects_input = [
        Record(
            created_at=1571267355,  # Чт окт 17 02:09:15 MSK 2019
            deleted_at=None,
            object_id=16100,
            object_type='closure'.encode('utf-8'),
            region_id='103544',
            template_id=None,
            category='no-transit'.encode('utf-8'),
            fake=False,
            geometry_len_meters=1.2,
        ),
        Record(
            created_at=1572367355,  # Вт окт 29 19:42:35 MSK 2019
            deleted_at=1574959355,  # Чт ноя 28 19:42:35 MSK 2019
            object_id=16105,
            object_type='closure'.encode('utf-8'),
            region_id='103544',
            template_id=None,
            category='no-transit'.encode('utf-8'),
            fake=False,
            geometry_len_meters=0.7,
        ),
    ]
    output = []
    job.local_run(
        sources={'objects': nl.StreamSource(objects_input)},
        sinks={'objects_ofd': nl.ListSink(output)},
    )
    correct = [
        Record(
            fielddate='2019-10-28',
            object_id=16100,
            object_type=obj_type,
            region_id='103544',
            length=1.2,
        ) for obj_type in ['\t_total_\t', '\t_total_\tclosure\t', '\t_total_\tclosure\tno-transit\t']
    ]
    assert output == correct


def test_join_regions():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-10-28', '2019-10-28', step=1, stringify=False)),
        'not used date-string'
    )
    objects_input = [Record(
        fielddate='2019-10-28',
        object_id=16100,
        object_type='\t_total_\tclosure\t',
        region_id='103544',
        length=0,
    )]
    regions = [Record(
        region_tree='\t10\t5\t',
        region_id='103544',
    )]
    output = []
    job.local_run(
        sources={
            'objects_ofd': nl.StreamSource(objects_input),
            'regions': nl.StreamSource(regions),
        },
        sinks={'objects_measured': nl.ListSink(output)},
    )
    correct = [Record(
        fielddate='2019-10-28',
        object_id=16100,
        object_type='\t_total_\tclosure\t',
        region='\t10\t5\t',
        length=0,
    )]
    assert output == correct


def test_versions_join_regions():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-10-28', '2019-10-28', step=1, stringify=False)),
        'not used date-string'
    )
    versions_input = [Record(
        fielddate='2019-10-28',
        object_id=16100,
        object_type='closure_template'.encode('utf-8'),
        length=0,
    )]
    objects_input = [Record(
        object_id=16100,
        object_type='closure_template'.encode('utf-8'),
        template_id=None,
        category='no-transit'.encode('utf-8'),
        fake=False,
        region_id='103544',
    )]
    regions = [Record(
        region_tree='\t10\t5\t',
        region_id='103544',
    )]
    output = []
    job.local_run(
        sources={
            'versions_ofd': nl.StreamSource(versions_input),
            'objects': nl.StreamSource(objects_input),
            'regions': nl.StreamSource(regions),
        },
        sinks={'versions_measured': nl.ListSink(output)},
    )
    correct = [Record(
        fielddate='2019-10-28',
        object_id=16100,
        object_type=object_type,
        region='\t10\t5\t',
        length=0,
    ) for object_type in ['\t_total_\t', '\t_total_\ttemplate\t']]
    assert output == correct


def test_unknown_regions():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-10-28', '2019-10-28', step=1, stringify=False)),
        'not used date-string'
    )
    objects_input = [Record(
        fielddate='2019-10-28',
        object_id=16100,
        object_type='\t_total_\tclosure\t',
        region_id='---',
        length=0,
    )]
    regions = [Record(
        region_tree='\t10\t5\t',
        region_id='103544',
    )]
    output = []
    job.local_run(
        sources={
            'objects_ofd': nl.StreamSource(objects_input),
            'regions': nl.StreamSource(regions),
        },
        sinks={'objects_measured': nl.ListSink(output)},
    )
    correct = [
        Record(
            fielddate='2019-10-28',
            object_id=16100,
            object_type='\t_total_\tclosure\t',
            region=region_str,
            length=0,
        ) for region_str in ['\t10000\t', '\t10000\t_unknown_\t']
    ]
    assert output == correct


def test_count():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-10-28', '2019-10-28', step=1, stringify=False)),
        'not used date-string'
    )
    objects_input = [
        Record(
            fielddate='2019-10-28',
            object_id=16100,
            object_type='\t_total_\tclosure\t',
            region='\t10\t5\t',
            length=1.2,
        ),
        Record(
            fielddate='2019-10-28',
            object_id=7100,
            object_type='\t_total_\tclosure\t',
            region='\t10\t5\t',
            length=0.7,
        ),
    ]
    output = []
    job.local_run(
        sources={'objects_measured': nl.StreamSource(objects_input)},
        sinks={'objects_count': nl.ListSink(output)},
    )
    correct = [Record(
        fielddate='2019-10-28',
        object_type='\t_total_\tclosure\t',
        region='\t10\t5\t',
        count=2,
        length=1.9,
    )]
    assert output == correct


def test_all_count():
    cluster = clusters.MockCluster()
    job = cluster.job()
    make_testable_job(
        job,
        list(nd.date_range('2019-10-28', '2019-10-28', step=1, stringify=False)),
        'not used date-string'
    )
    objects_input = [
        Record(
            fielddate='2019-10-28',
            object_id=16100,
            object_type='\t_total_\t',
            region='\t10\t5\t',
            length=31.2,
        ),
        Record(
            fielddate='2019-10-28',
            object_id=7100,
            object_type='\t_total_\tclosure\t',
            region='\t10\t5\t',
            length=30.7,
        ),
    ]
    versions_input = [
        Record(
            fielddate='2019-10-28',
            object_id=16100,
            object_type='\t_total_\tclosure\t',
            region='\t10\t5\t',
            length=1.2,
        ),
        Record(
            fielddate='2019-10-28',
            object_id=7100,
            object_type='\t_total_\tclosure\t',
            region='\t10\t5\t',
            length=0.7,
        ),
    ]
    output = []
    job.local_run(
        sources={
            'objects_measured': nl.StreamSource(objects_input),
            'versions_measured': nl.StreamSource(versions_input),
        },
        sinks={'all_count': nl.ListSink(output)},
    )
    correct = [
        Record(
            fielddate='2019-10-28',
            object_type='\t_total_\t',
            region='\t10\t5\t',
            count=1,
            length=31.2,
        ),
        Record(
            fielddate='2019-10-28',
            object_type='\t_total_\tclosure\t',
            region='\t10\t5\t',
            count=1,
            length=30.7,
            count_effective=2,
            length_effective=1.9,
        ),
    ]
    assert output == correct
