'''
Offline replay provider contract tests.

'''
from datetime import (
    UTC,
    datetime,
)
from pathlib import Path

import numpy as np
import pytest
import trio

from piker.brokers import DataUnavailable
from piker.brokers import replay


INPUTS: Path = (
    Path(__file__).parents[1]
    / '_inputs'
    / 'replay'
)


def test_versioned_scenario_normalizes_market_data() -> None:
    '''
    Reject fixture drift before a datad actor obscures its cause.

    Replay scenarios are durable test inputs rather than loose mock
    dictionaries. Decode the versioned basic scenario through the
    production loader and prove its market identity, Decimal fields,
    contiguous event IDs, and normalized tick records survive typed
    decoding. These assertions catch schema or symbology changes at
    the provider boundary without starting services or using network
    resources.

    '''
    scenario: replay.ReplayScenario = replay.load_scenario(
        INPUTS / 'basic-v1.json'
    )

    assert scenario.version == 1
    assert scenario.scenario_id == 'basic-v1'
    assert scenario.markets[0].fqme == 'btcusd.test.replay'
    assert str(scenario.markets[0].price_tick) == '0.01'
    assert [quote.sequence for quote in scenario.quotes] == [
        1,
        2,
        3,
        4,
    ]
    assert scenario.quotes[1].ticks[0].type == 'trade'


def test_history_queries_are_bounded_and_repeatable(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    '''
    Keep history replay finite, offline, and repeatable.

    A history fixture which mutates a cursor per request can make the
    two concurrent 1-second and 1-minute backfill tasks race,
    while an unbounded latest frame can make datad backfill
    forever. Select the same 1-minute frame twice, then request
    data ending at its first timestamp. Equal arrays prove calls
    are immutable and the explicit `DataUnavailable` proves
    reverse backfill terminates at the fixture boundary without
    a clock delay or external request.

    '''
    scenario_path: Path = INPUTS / 'basic-v1.json'
    monkeypatch.setenv(
        'PIKER_REPLAY_SCENARIO',
        str(scenario_path),
    )
    scenario: replay.ReplayScenario = replay.load_scenario(
        scenario_path
    )
    mkt = scenario.markets[0]

    async def main() -> None:
        async with replay.open_history_client(mkt) as (
            get_hist,
            config,
        ):
            first, start, end = await get_hist(60)
            second, second_start, second_end = await get_hist(60)
            np.testing.assert_array_equal(first, second)
            assert (start, end) == (second_start, second_end)
            assert config == {'erlangs': 1, 'rate': 1}

            boundary: datetime = datetime.fromtimestamp(
                int(first['time'][0]),
                tz=UTC,
            )
            with pytest.raises(DataUnavailable):
                await get_hist(60, end_dt=boundary)

    trio.run(main)
