from itertools import chain

import numpy as np
import pandas as pd
import pytest

from featuretools.utils import convert_time_units, make_temporal_cutoffs


def test_make_temporal_cutoffs():
    instance_ids = pd.Series(range(10))
    cutoffs = pd.date_range(start="1/2/2015", periods=10, freq="1d")
    temporal_cutoffs_by_nwindows = make_temporal_cutoffs(
        instance_ids, cutoffs, window_size="1h", num_windows=2
    )

    assert temporal_cutoffs_by_nwindows.shape[0] == 20
    actual_instances = chain.from_iterable([[i, i] for i in range(10)])
    actual_times = [
        "1/1/2015 23:00:00",
        "1/2/2015 00:00:00",
        "1/2/2015 23:00:00",
        "1/3/2015 00:00:00",
        "1/3/2015 23:00:00",
        "1/4/2015 00:00:00",
        "1/4/2015 23:00:00",
        "1/5/2015 00:00:00",
        "1/5/2015 23:00:00",
        "1/6/2015 00:00:00",
        "1/6/2015 23:00:00",
        "1/7/2015 00:00:00",
        "1/7/2015 23:00:00",
        "1/8/2015 00:00:00",
        "1/8/2015 23:00:00",
        "1/9/2015 00:00:00",
        "1/9/2015 23:00:00",
        "1/10/2015 00:00:00",
        "1/10/2015 23:00:00",
        "1/11/2015 00:00:00",
        "1/11/2015 23:00:00",
    ]
    actual_times = [pd.Timestamp(c) for c in actual_times]

    for computed, actual in zip(
        temporal_cutoffs_by_nwindows["instance_id"], actual_instances
    ):
        assert computed == actual
    for computed, actual in zip(temporal_cutoffs_by_nwindows["time"], actual_times):
        assert computed == actual

    cutoffs = [pd.Timestamp("1/2/2015")] * 9 + [pd.Timestamp("1/3/2015")]
    starts = [pd.Timestamp("1/1/2015")] * 9 + [pd.Timestamp("1/2/2015")]
    actual_times = ["1/1/2015 00:00:00", "1/2/2015 00:00:00"] * 9
    actual_times += ["1/2/2015 00:00:00", "1/3/2015 00:00:00"]
    actual_times = [pd.Timestamp(c) for c in actual_times]
    temporal_cutoffs_by_wsz_start = make_temporal_cutoffs(
        instance_ids, cutoffs, window_size="1d", start=starts
    )

    for computed, actual in zip(
        temporal_cutoffs_by_wsz_start["instance_id"], actual_instances
    ):
        assert computed == actual
    for computed, actual in zip(temporal_cutoffs_by_wsz_start["time"], actual_times):
        assert computed == actual

    cutoffs = [pd.Timestamp("1/2/2015")] * 9 + [pd.Timestamp("1/3/2015")]
    starts = [pd.Timestamp("1/1/2015")] * 10
    actual_times = ["1/1/2015 00:00:00", "1/2/2015 00:00:00"] * 9
    actual_times += ["1/1/2015 00:00:00", "1/3/2015 00:00:00"]
    actual_times = [pd.Timestamp(c) for c in actual_times]
    temporal_cutoffs_by_nw_start = make_temporal_cutoffs(
        instance_ids, cutoffs, num_windows=2, start=starts
    )

    for computed, actual in zip(
        temporal_cutoffs_by_nw_start["instance_id"], actual_instances
    ):
        assert computed == actual
    for computed, actual in zip(temporal_cutoffs_by_nw_start["time"], actual_times):
        assert computed == actual


def test_convert_time_units():
    units = {
        "years": 31540000,
        "months": 2628000,
        "days": 86400,
        "hours": 3600,
        "minutes": 60,
        "seconds": 1,
        "milliseconds": 0.001,
        "nanoseconds": 0.000000001,
    }
    for each in units:
        assert convert_time_units(units[each] * 2, each) == 2
        assert np.isclose(convert_time_units(float(units[each] * 2), each), 2)

    error_text = "Invalid unit given, make sure it is plural"
    with pytest.raises(ValueError, match=error_text):
        convert_time_units("jnkwjgn", 10)
