import datetime
import json

import pytest
import pytz
import responses
from six.moves.urllib_parse import urlparse, parse_qs
import trafaret

from datarobot import BacktestSpecification, DatetimePartitioning, \
    DatetimePartitioningSpecification, FeatureSettings, Project
from datarobot import partitioning_methods
from datarobot.errors import DataRobotDeprecationWarning
from tests.test_project import prep_successful_aim_responses


def test_future_proof(datetime_partition_server_data):
    future_response = dict(datetime_partition_server_data, future='newKey')
    DatetimePartitioning.from_server_data(future_response)


def test_construct_duration_string():
    duration = partitioning_methods.construct_duration_string(years=1, months=2, days=3,
                                                              hours=4, minutes=5, seconds=6)
    assert duration == 'P1Y2M3DT4H5M6S'


def test_construct_duration_string_empty():
    assert partitioning_methods.construct_duration_string() == 'P0Y0M0DT0H0M0S'


def test_collect_payload_fails_cleanly_on_type_error(datetime_partition_spec):
    datetime_partition_spec.holdout_start_date = str(datetime_partition_spec.holdout_start_date)
    with pytest.raises(ValueError) as exc_info:
        datetime_partition_spec.collect_payload()
    assert 'expected holdout_start_date to be a datetime.datetime' in str(exc_info.value)


def test_backtest_to_specification(datetime_partition):
    backtest = datetime_partition.backtests[0]
    backtest_spec = backtest.to_specification()
    assert backtest_spec.index == backtest.index
    assert backtest_spec.gap_duration == backtest.gap_duration
    assert backtest_spec.validation_start_date
    assert backtest_spec.validation_duration == backtest.validation_duration


def test_partition_to_specification(datetime_partition):
    part_spec = datetime_partition.to_specification()
    assert part_spec.datetime_partition_column == datetime_partition.datetime_partition_column
    assert (part_spec.autopilot_data_selection_method ==
            datetime_partition.autopilot_data_selection_method)
    assert part_spec.validation_duration == datetime_partition.validation_duration
    assert part_spec.holdout_start_date == datetime_partition.holdout_start_date
    assert part_spec.holdout_duration == datetime_partition.holdout_duration
    assert part_spec.gap_duration == datetime_partition.gap_duration
    assert part_spec.number_of_backtests == datetime_partition.number_of_backtests
    assert len(part_spec.backtests) == len(datetime_partition.backtests)
    for bt_spec in part_spec.backtests:
        assert isinstance(bt_spec, BacktestSpecification)
    assert part_spec.use_time_series == datetime_partition.use_time_series
    assert part_spec.default_to_known_in_advance == datetime_partition.default_to_known_in_advance
    assert (part_spec.feature_derivation_window_start ==
            datetime_partition.feature_derivation_window_start)
    assert (part_spec.feature_derivation_window_end ==
            datetime_partition.feature_derivation_window_end)
    assert part_spec.forecast_window_start == datetime_partition.forecast_window_start
    assert part_spec.forecast_window_end == datetime_partition.forecast_window_end


def test_partition_to_specification_with_time_series(datetime_partition):
    datetime_partition.multiseries_id_columns = ['series_id']
    datetime_partition.differencing_method = 'seasonal'
    datetime_partition.treat_as_exponential = 'never'
    datetime_partition.periodicities = []
    datetime_partition.use_time_series = True
    datetime_partition.feature_settings = [FeatureSettings('special', known_in_advance=True)]
    part_spec = datetime_partition.to_specification()

    assert part_spec.multiseries_id_columns == datetime_partition.multiseries_id_columns
    assert part_spec.differencing_method == datetime_partition.differencing_method
    assert part_spec.treat_as_exponential == datetime_partition.treat_as_exponential
    assert part_spec.periodicities == datetime_partition.periodicities
    assert part_spec.use_time_series == datetime_partition.use_time_series
    assert part_spec.feature_settings == datetime_partition.feature_settings


@responses.activate
@pytest.mark.usefixtures('client')
def test_retrieve(project_id, project_url, datetime_partition_after_target_server_data):
    responses.add(responses.GET, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_after_target_server_data)

    partition = DatetimePartitioning.get(project_id)

    assert partition.primary_training_row_count == 100
    assert partition.available_training_row_count == 100
    assert partition.gap_row_count == 100
    assert partition.holdout_row_count == 100
    assert partition.total_row_count == 100

    backtest = partition.backtests[0]
    assert backtest.primary_training_row_count == 100
    assert backtest.available_training_row_count == 100
    assert backtest.gap_row_count == 100
    assert backtest.validation_row_count == 100
    assert backtest.total_row_count == 100


@responses.activate
@pytest.mark.usefixtures('client')
def test_retrieve_time_series(
    project_id, project_url, datetime_partition_time_series_server_data
):
    responses.add(responses.GET, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_time_series_server_data)

    partition = DatetimePartitioning.get(project_id)

    fdw_start = datetime_partition_time_series_server_data['featureDerivationWindowStart']
    fdw_end = datetime_partition_time_series_server_data['featureDerivationWindowEnd']
    fw_start = datetime_partition_time_series_server_data['forecastWindowStart']
    fw_end = datetime_partition_time_series_server_data['forecastWindowEnd']
    assert partition.use_time_series
    assert partition.default_to_known_in_advance
    assert partition.feature_derivation_window_start == fdw_start
    assert partition.feature_derivation_window_end == fdw_end
    assert partition.forecast_window_start == fw_start
    assert partition.forecast_window_end == fw_end


@responses.activate
@pytest.mark.usefixtures('client')
def test_generate(project_id, project_url, datetime_partition_server_data,
                  holdout_start_date, datetime_partition_spec):
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_server_data)

    partition = DatetimePartitioning.generate(project_id, datetime_partition_spec)

    # test that we send the right things
    actual_payload = json.loads(responses.calls[0].request.body)
    expected_backtests = [{
        'index': bt.index, 'gapDuration': bt.gap_duration,
        'validationStartDate': bt.validation_start_date.isoformat(),
        'validationDuration': bt.validation_duration
        } for bt in datetime_partition_spec.backtests]
    expected_payload = {
        'datetimePartitionColumn': datetime_partition_spec.datetime_partition_column,
        'autopilotDataSelectionMethod': datetime_partition_spec.autopilot_data_selection_method,
        'validationDuration': datetime_partition_spec.validation_duration,
        'holdoutStartDate': holdout_start_date.isoformat(),
        'holdoutDuration': datetime_partition_spec.holdout_duration,
        'gapDuration': datetime_partition_spec.gap_duration,
        'numberOfBacktests': datetime_partition_spec.number_of_backtests,
        'backtests': expected_backtests,
        'useTimeSeries': datetime_partition_spec.use_time_series,
        'defaultToKnownInAdvance': datetime_partition_spec.default_to_known_in_advance
    }
    assert actual_payload == expected_payload

    # test that we get the right thing back
    assert partition.project_id == project_id
    assert partition.multiseries_id_columns is None
    assert (partition.datetime_partition_column ==
            datetime_partition_server_data['datetimePartitionColumn'])
    assert partition.use_time_series == datetime_partition_server_data['useTimeSeries']
    assert (partition.default_to_known_in_advance ==
            datetime_partition_server_data['defaultToKnownInAdvance'])
    assert partition.date_format == datetime_partition_server_data['dateFormat']
    assert (partition.autopilot_data_selection_method ==
            datetime_partition_server_data['autopilotDataSelectionMethod'])
    assert partition.validation_duration == datetime_partition_server_data['validationDuration']

    assert isinstance(partition.available_training_start_date, datetime.datetime)
    assert (partition.available_training_duration ==
            datetime_partition_server_data['availableTrainingDuration'])
    assert isinstance(partition.available_training_end_date, datetime.datetime)

    assert isinstance(partition.primary_training_start_date, datetime.datetime)
    assert (partition.primary_training_duration ==
            datetime_partition_server_data['primaryTrainingDuration'])
    assert isinstance(partition.primary_training_end_date, datetime.datetime)

    assert isinstance(partition.gap_start_date, datetime.datetime)
    assert partition.gap_duration == datetime_partition_server_data['gapDuration']
    assert isinstance(partition.gap_end_date, datetime.datetime)

    assert partition.holdout_start_date == holdout_start_date
    assert partition.holdout_duration == datetime_partition_server_data['holdoutDuration']
    assert isinstance(partition.holdout_end_date, datetime.datetime)

    assert partition.number_of_backtests == datetime_partition_server_data['numberOfBacktests']
    [backtest] = partition.backtests
    [backtest_data] = datetime_partition_server_data['backtests']
    assert backtest.index == backtest_data['index']
    assert isinstance(backtest.available_training_start_date, datetime.datetime)
    assert backtest.available_training_duration == backtest_data['availableTrainingDuration']
    assert isinstance(backtest.available_training_end_date, datetime.datetime)
    assert isinstance(backtest.primary_training_start_date, datetime.datetime)
    assert backtest.primary_training_duration == backtest_data['primaryTrainingDuration']
    assert isinstance(backtest.primary_training_end_date, datetime.datetime)
    assert isinstance(backtest.gap_start_date, datetime.datetime)
    assert backtest.gap_duration == backtest_data['gapDuration']
    assert isinstance(backtest.gap_end_date, datetime.datetime)
    assert isinstance(backtest.validation_start_date, datetime.datetime)
    assert backtest.validation_duration == backtest_data['validationDuration']
    assert isinstance(backtest.validation_end_date, datetime.datetime)


@responses.activate
@pytest.mark.usefixtures('client')
def test_generate_with_multiseries(project_id, project_url, datetime_partition_spec,
                                   datetime_partition_server_data):
    datetime_partition_spec.multiseries_id_columns = ['series_id']
    datetime_partition_server_data['multiseriesIdColumns'] = ['series_id']
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_server_data)
    multi_prop_url = '{}features/{}/multiseriesProperties/'.format(
        project_url, datetime_partition_spec.datetime_partition_column)
    multi_prop_json = {
        'datetimePartitionColumn': datetime_partition_spec.datetime_partition_column,
        'detectedMultiseriesIdColumns': [
            {'multiseriesIdColumns': ['series_id'], 'timeStep': 1, 'timeUnit': 'DAY'}
        ]
    }
    date_feat_json = {
        'projectId': project_id, 'name': datetime_partition_spec.datetime_partition_column,
        'id': 2, 'timeSeriesEligible': False, 'featureType': 'date',
        'timeSeriesEligibilityReason': 'notUnique', 'lowInformation': False, 'uniqueCount': 500
    }
    responses.add(responses.GET,
                  '{}features/{}/'.format(project_url,
                                          datetime_partition_spec.datetime_partition_column),
                  json=date_feat_json)
    responses.add(responses.GET, multi_prop_url,
                  json=multi_prop_json)

    partition = DatetimePartitioning.generate(project_id, datetime_partition_spec)
    assert partition.multiseries_id_columns == ['series_id']


@responses.activate
@pytest.mark.usefixtures('client')
def test_generate_time_series(project_id, project_url, datetime_partition_time_series_server_data,
                              time_series_partition_spec, holdout_start_date):
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_time_series_server_data)

    partition = DatetimePartitioning.generate(project_id, time_series_partition_spec)

    # test that we send the right things
    actual_payload = json.loads(responses.calls[0].request.body)
    expected_backtests = [{
        'index': bt.index, 'gapDuration': bt.gap_duration,
        'validationStartDate': bt.validation_start_date.isoformat(),
        'validationDuration': bt.validation_duration
        } for bt in time_series_partition_spec.backtests]
    expected_payload = {
        'datetimePartitionColumn': time_series_partition_spec.datetime_partition_column,
        'autopilotDataSelectionMethod': time_series_partition_spec.autopilot_data_selection_method,
        'validationDuration': time_series_partition_spec.validation_duration,
        'holdoutStartDate': holdout_start_date.isoformat(),
        'holdoutDuration': time_series_partition_spec.holdout_duration,
        'gapDuration': time_series_partition_spec.gap_duration,
        'numberOfBacktests': time_series_partition_spec.number_of_backtests,
        'backtests': expected_backtests,
        'useTimeSeries': time_series_partition_spec.use_time_series,
        'defaultToKnownInAdvance': time_series_partition_spec.default_to_known_in_advance,
        'featureDerivationWindowStart': time_series_partition_spec.feature_derivation_window_start,
        'featureDerivationWindowEnd': time_series_partition_spec.feature_derivation_window_end,
        'forecastWindowStart': time_series_partition_spec.forecast_window_start,
        'forecastWindowEnd': time_series_partition_spec.forecast_window_end
    }
    assert actual_payload == expected_payload

    assert partition.use_time_series == time_series_partition_spec.use_time_series
    assert (partition.default_to_known_in_advance ==
            time_series_partition_spec.default_to_known_in_advance)
    assert (partition.feature_derivation_window_start ==
            time_series_partition_spec.feature_derivation_window_start)
    assert (partition.feature_derivation_window_end ==
            time_series_partition_spec.feature_derivation_window_end)
    assert partition.forecast_window_start == time_series_partition_spec.forecast_window_start
    assert partition.forecast_window_end == time_series_partition_spec.forecast_window_end


@responses.activate
@pytest.mark.usefixtures('client')
def test_generate_feature_settings(
        project_id, project_url, datetime_partition_server_data_feature_settings,
        holdout_start_date, datetime_partition_spec_feature_settings
):
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_server_data_feature_settings)

    partition = DatetimePartitioning.generate(project_id, datetime_partition_spec_feature_settings)

    # test that we send the right things
    actual_payload = json.loads(responses.calls[0].request.body)
    expected_backtests = [{
        'index': bt.index, 'gapDuration': bt.gap_duration,
        'validationStartDate': bt.validation_start_date.isoformat(),
        'validationDuration': bt.validation_duration
    } for bt in datetime_partition_spec_feature_settings.backtests]
    expected_feature_settings = [{
        'featureName': fs.feature_name,
        'knownInAdvance': fs.known_in_advance
    } for fs in datetime_partition_spec_feature_settings.feature_settings]
    expected_payload = {
        'datetimePartitionColumn':
            datetime_partition_spec_feature_settings.datetime_partition_column,
        'autopilotDataSelectionMethod':
            datetime_partition_spec_feature_settings.autopilot_data_selection_method,
        'validationDuration': datetime_partition_spec_feature_settings.validation_duration,
        'holdoutStartDate': holdout_start_date.isoformat(),
        'holdoutDuration': datetime_partition_spec_feature_settings.holdout_duration,
        'gapDuration': datetime_partition_spec_feature_settings.gap_duration,
        'numberOfBacktests': datetime_partition_spec_feature_settings.number_of_backtests,
        'backtests': expected_backtests,
        'useTimeSeries': datetime_partition_spec_feature_settings.use_time_series,
        'defaultToKnownInAdvance':
            datetime_partition_spec_feature_settings.default_to_known_in_advance,
        'featureSettings': expected_feature_settings
    }
    assert actual_payload == expected_payload
    assert partition.feature_settings == datetime_partition_spec_feature_settings.feature_settings


@pytest.mark.parametrize('known_in_advance', [None, 'True', 1, {'true': True}, [True]])
def test_create_feature_settings_bad_known_in_advance(known_in_advance):
    with pytest.raises(trafaret.DataError):
        FeatureSettings('feature_name', known_in_advance=known_in_advance)


@pytest.mark.parametrize('feature_name', [None, False, 1, {'true': True}, [True]])
def test_create_feature_settings_bad_feature_name(feature_name):
    with pytest.raises(trafaret.DataError):
        FeatureSettings(feature_name, 'known_in_advance')


@responses.activate
@pytest.mark.usefixtures('client')
def test_generate_keep_extra_time_series_controls_spec(
    project_id, project_url,
    datetime_partition_server_data_extra_time_series_controls,
    datetime_partition_spec_extra_time_series_controls
):
    server_data = datetime_partition_server_data_extra_time_series_controls
    spec_fixture = datetime_partition_spec_extra_time_series_controls
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=server_data)

    partitioning = DatetimePartitioning.generate(project_id, spec_fixture)
    partitioning_spec = partitioning.to_specification()

    assert partitioning_spec.periodicities == spec_fixture.periodicities
    assert partitioning_spec.treat_as_exponential == spec_fixture.treat_as_exponential
    assert partitioning_spec.differencing_method == spec_fixture.differencing_method


@responses.activate
@pytest.mark.usefixtures('client')
def test_generate_no_peridiocities_on_server_spec(
    project_id, project_url,
    datetime_partition_server_data_extra_time_series_controls,
    datetime_partition_spec_extra_time_series_controls
):
    server_data = datetime_partition_server_data_extra_time_series_controls
    spec_fixture = datetime_partition_spec_extra_time_series_controls
    server_data['periodicities'] = None
    spec_fixture.periodicities = None
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=server_data)

    partitioning = DatetimePartitioning.generate(project_id, spec_fixture)
    partitioning_spec = partitioning.to_specification()

    assert partitioning_spec.periodicities == spec_fixture.periodicities
    assert partitioning_spec.treat_as_exponential == spec_fixture.treat_as_exponential
    assert partitioning_spec.differencing_method == spec_fixture.differencing_method


@responses.activate
@pytest.mark.usefixtures('client')
def test_create_project_with_periodicity(
    datetime_partition_server_data_extra_time_series_controls,
    datetime_partition_spec_extra_time_series_controls
):
    server_data = datetime_partition_server_data_extra_time_series_controls
    spec_fixture = datetime_partition_spec_extra_time_series_controls
    prep_successful_aim_responses()
    Project('p-id').set_target(
        'SalePrice',
        metric='RMSE',
        partitioning_method=spec_fixture)

    request_message = json.loads(responses.calls[0].request.body)
    assert request_message['periodicities'] == server_data['periodicities']


@responses.activate
@pytest.mark.usefixtures('client')
def test_create_project_with_treat_as_exponential(
    datetime_partition_spec_extra_time_series_controls
):
    spec_fixture = datetime_partition_spec_extra_time_series_controls
    prep_successful_aim_responses()
    Project('p-id').set_target(
        'SalePrice',
        metric='RMSE',
        partitioning_method=spec_fixture)

    request_message = json.loads(responses.calls[0].request.body)
    assert request_message['treatAsExponential'] == spec_fixture.treat_as_exponential


@responses.activate
@pytest.mark.usefixtures('client')
def test_create_project_with_differencing_method(
        datetime_partition_spec_extra_time_series_controls
):
    spec_fixture = datetime_partition_spec_extra_time_series_controls
    prep_successful_aim_responses()
    Project('p-id').set_target(
        'SalePrice',
        metric='RMSE',
        partitioning_method=spec_fixture)

    request_message = json.loads(responses.calls[0].request.body)
    assert request_message['differencingMethod'] == spec_fixture.differencing_method


@responses.activate
@pytest.mark.usefixtures('client')
def test_retrieve_otp_without_holdout(project_id, project_url,
                                      datetime_partition_without_holdout_server_data):
    responses.add(responses.GET, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_without_holdout_server_data)

    partition = DatetimePartitioning.get(project_id)

    assert partition.primary_training_start_date is None
    assert partition.primary_training_end_date is None
    assert partition.primary_training_row_count == 0
    assert partition.primary_training_duration == 'P0Y0M0D'

    assert partition.available_training_start_date == datetime.datetime(2013, 11, 20, 22, 38, 47,
                                                                        tzinfo=pytz.UTC)
    assert partition.available_training_end_date == datetime.datetime(2014, 1, 12, 22, 44, 23,
                                                                      tzinfo=pytz.UTC)
    assert partition.available_training_duration == 'P0Y0M53DT0H5M36S'
    assert partition.available_training_row_count == 4276

    assert partition.gap_start_date is None
    assert partition.gap_end_date is None
    assert partition.gap_row_count == 0
    assert partition.gap_duration == 'P0Y0M0D'

    assert partition.holdout_start_date is None
    assert partition.holdout_end_date is None
    assert partition.holdout_row_count == 0
    assert partition.holdout_duration == 'P0Y0M0D'

    assert partition.total_row_count == 4276

    backtest = partition.backtests[0]
    assert backtest.primary_training_row_count == 4168
    assert backtest.available_training_row_count == 4168
    assert backtest.gap_row_count == 0
    assert backtest.validation_row_count == 108
    assert backtest.total_row_count == 4276


@responses.activate
@pytest.mark.usefixtures('client')
def test_retrieve_feature_settings(
        project_id, project_url, datetime_partition_after_target_server_data_feature_settings):

    responses.add(responses.GET, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_after_target_server_data_feature_settings)

    partition = DatetimePartitioning.get(project_id)

    fs_list = datetime_partition_after_target_server_data_feature_settings['featureSettings']
    assert partition.feature_settings == [
        FeatureSettings(fs['featureName'], fs['knownInAdvance']) for fs in fs_list]


@responses.activate
@pytest.mark.usefixtures('client')
def test_from_minimum_specification(project_id, project_url, datetime_partition_server_data):
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_server_data)

    datetime_column = datetime_partition_server_data['datetimePartitionColumn']
    min_spec = DatetimePartitioningSpecification(datetime_column)
    DatetimePartitioning.generate(project_id, min_spec)

    expected_payload = {'datetimePartitionColumn': datetime_column,
                        'useTimeSeries': False, 'defaultToKnownInAdvance': False}
    actual_payload = json.loads(responses.calls[0].request.body)
    assert actual_payload == expected_payload


def test_to_dataframe(datetime_partition):
    df = datetime_partition.to_dataframe()
    expected_shape = (4*(1+datetime_partition.number_of_backtests), 3)
    assert df.shape == expected_shape


@responses.activate
@pytest.mark.usefixtures('client')
def test_disabled_holdout(project_id, project_url, datetime_partition_without_holdout_server_data):
    responses.add(responses.POST, '{}datetimePartitioning/'.format(project_url),
                  json=datetime_partition_without_holdout_server_data)

    datetime_column = datetime_partition_without_holdout_server_data['datetimePartitionColumn']
    spec = DatetimePartitioningSpecification(datetime_column, disable_holdout=True)
    DatetimePartitioning.generate(project_id, spec)

    expected_payload = {
        'datetimePartitionColumn': datetime_column,
        'disableHoldout': True,
        'useTimeSeries': False,
        'defaultToKnownInAdvance': False
    }
    actual_payload = json.loads(responses.calls[0].request.body)
    assert actual_payload == expected_payload


# APriori backward compatibility
@responses.activate
@pytest.mark.usefixtures('client', 'known_warning')
def test_a_priori_backward_compatibility_supported(
        project_id, project_url, datetime_partition_after_target_server_data_feature_settings):

    resp = datetime_partition_after_target_server_data_feature_settings
    resp['defaultToAPriori'] = resp.pop('defaultToKnownInAdvance')
    resp['featureSettings'] = [
        {'aPriori': r['knownInAdvance'], 'featureName': r['featureName']}
        for r in resp['featureSettings']
    ]
    responses.add(responses.GET, '{}datetimePartitioning/'.format(project_url), json=resp)

    partition = DatetimePartitioning.get(project_id)

    fs_list = datetime_partition_after_target_server_data_feature_settings['featureSettings']
    # Test response with aPriori works
    assert partition.feature_settings == [
        FeatureSettings(fs['featureName'], fs['aPriori']) for fs in fs_list]
    # Test a_priori works
    assert partition.feature_settings[0].a_priori
    # Test default_to_a_priori works
    assert partition.default_to_a_priori == resp['defaultToAPriori']


@pytest.mark.parametrize('a_priori', ['True', 1, {'true': True}, [True]])
def test_create_feature_settings_bad_a_priori(a_priori):
    with pytest.raises(DataRobotDeprecationWarning):
        FeatureSettings('feature_name', a_priori=a_priori)


@responses.activate
@pytest.mark.usefixtures('client')
def test_time_series_feature_log(project_id, project_url):
    expected_resp = {
        'count': 0,
        'previous': None,
        'totalLogLines': 78,
        'featureLog': '',
        'next': None
    }
    responses.add(responses.GET, '{}timeSeriesFeatureLog/'.format(project_url), json=expected_resp)
    resp = DatetimePartitioning.feature_log_list(project_id, limit=10, offset=20)
    assert resp == expected_resp

    req_url = responses.calls[0].request.url
    assert {'limit': ['10'], 'offset': ['20']} == parse_qs(urlparse(req_url).query)


@responses.activate
@pytest.mark.usefixtures('client')
def test_time_series_feature_log_retrieve(project_id, project_url):
    log_data = 'useful info'
    responses.add(responses.GET, '{}timeSeriesFeatureLog/file/'.format(project_url), body=log_data)
    retrieved_data = DatetimePartitioning.feature_log_retrieve(project_id)
    assert retrieved_data == log_data
