import json

import httpx
import pytest
import respx

from horatio_data_provider import DataProviderClient

BASE = "http://test"


@pytest.fixture
def client():
    return DataProviderClient(BASE)


# --- AAVE ---

@respx.mock
@pytest.mark.asyncio
async def test_aave_deposit_event_routing(client, parquet_bytes):
    route = respx.post(f"{BASE}/aave/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.aave.deposits().network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["event"] == "deposit"


@respx.mock
@pytest.mark.asyncio
async def test_aave_borrow_event_routing(client, parquet_bytes):
    route = respx.post(f"{BASE}/aave/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.aave.borrows().network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["event"] == "borrow"


# --- Uniswap ---

@respx.mock
@pytest.mark.asyncio
async def test_uniswap_swaps_body(client, parquet_bytes):
    route = respx.post(f"{BASE}/uniswap/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.uniswap.swaps("WETH", "USDC", fee=500).network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["event"] == "swap"
    assert body["symbol0"] == "WETH"
    assert body["symbol1"] == "USDC"
    assert body["fee"] == 500


# --- Lido ---

@respx.mock
@pytest.mark.asyncio
async def test_lido_deposit_event_routing(client, parquet_bytes):
    route = respx.post(f"{BASE}/lido/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.lido.deposits().network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["event"] == "deposit"


@respx.mock
@pytest.mark.asyncio
async def test_lido_withdrawal_request_event_routing(client, parquet_bytes):
    route = respx.post(f"{BASE}/lido/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.lido.withdrawal_requests().network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["event"] == "withdrawal_request"


# --- Stader ---

@respx.mock
@pytest.mark.asyncio
async def test_stader_deposit_event_routing(client, parquet_bytes):
    route = respx.post(f"{BASE}/stader/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.stader.deposits().network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["event"] == "deposit"


# --- Threshold ---

@respx.mock
@pytest.mark.asyncio
async def test_threshold_deposit_request_event_routing(client, parquet_bytes):
    route = respx.post(f"{BASE}/threshold/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.threshold.deposit_requests().network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["event"] == "deposit_request"


# --- Native ---

@respx.mock
@pytest.mark.asyncio
async def test_native_transfers_standard_url(client, parquet_bytes):
    route = respx.post(f"{BASE}/native_transfers/read").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.native.transfers().network("ETH").time_range("2025-01-01", "2025-01-02").fetch()
    assert route.called


@respx.mock
@pytest.mark.asyncio
async def test_native_transfers_min_amount_url(client, parquet_bytes):
    route = respx.post(f"{BASE}/native_transfers/read/min").mock(
        return_value=httpx.Response(200, content=parquet_bytes, headers={"content-type": "application/octet-stream"})
    )
    await client.native.transfers().network("ETH").time_range("2025-01-01", "2025-01-02").min_amount(0.5).fetch()
    assert route.called
    body = json.loads(route.calls[0].request.content)
    assert body["min_amount"] == 0.5


# --- Cache ---

@respx.mock
@pytest.mark.asyncio
async def test_cache_flush(client):
    route = respx.post(f"{BASE}/cache/flush").mock(
        return_value=httpx.Response(200, content=b"{}", headers={"content-type": "application/json"})
    )
    await client.cache.flush()
    assert route.called
