import matchy.util as util
from datetime import datetime
import pytest


def test_iterate_all_shifts():
    original = [1, 2, 3, 4]
    lists = [val for val in util.iterate_all_shifts(original)]
    assert lists == [
        [1, 2, 3, 4],
        [2, 3, 4, 1],
        [3, 4, 1, 2],
        [4, 1, 2, 3],
    ]


def test_get_nested_dict_value():
    d = {
        "x": {
            "y": {
                "z": {
                    "val": 42
                }
            }
        }
    }
    assert 42 == util.get_nested_value(d, "x", "y", "z", "val")
    assert 16 == util.get_nested_value(d, "x", "y", "z", "vol", default=16)


def test_set_nested_dict_value():
    d = {
        "x": {
            "y": {
                "z": {
                    "val": 42
                }
            }
        }
    }
    util.set_nested_value(d, "x", "y", "z", "val", value=52)
    assert 52 == util.get_nested_value(d, "x", "y", "z", "val")


def test_randomized():

    def string():
        return "foo"

    def list():
        return ["foo", "bar"]

    assert util.randomised(string)() == "foo"
    assert util.randomised(list)() in list()


@pytest.mark.parametrize(
    "weekday, hour, start, expected",
    [
        pytest.param(
            0, 0, datetime(2024, 9, 22),
            datetime(2024, 9, 23), id="tomorrow"
        ),
        pytest.param(
            4, 16, datetime(2024, 9, 22),
            datetime(2024, 9, 27, 16), id="complicated"
        ),
    ],
)
def test_get_next_datetime(weekday, hour, start, expected):
    value = util.get_next_datetime(weekday, hour, start)
    assert value == expected


@pytest.mark.parametrize(
    "weekday, hour, start, cadence, cadence_start, expected",
    [
        pytest.param(
            0, 0, datetime(2024, 9, 22),
            1, datetime(2024, 9, 22),
            datetime(2024, 9, 23), id="tomorrow"
        ),
        pytest.param(
            0, 0, datetime(2024, 9, 22),
            2, datetime(2024, 9, 22),
            datetime(2024, 9, 23), id="every-other"
        ),
        pytest.param(
            0, 0, datetime(2024, 9, 22),
            2, datetime(2024, 9, 14),
            datetime(2024, 9, 30), id="every-other-before"
        ),
        pytest.param(
            0, 0, datetime(2024, 9, 22),
            3, datetime(2024, 9, 14),
            datetime(2024, 10, 7), id="every-third"
        ),
    ],
)
def test_get_next_datetime_with_cadence(weekday, hour, start, expected, cadence, cadence_start):
    value = util.get_next_datetime_with_cadence(weekday, hour, start, cadence, cadence_start)
    assert value == expected
