from __future__ import annotations

import threading
import time
from datetime import datetime, timedelta, timezone

import pytest

from price.cache import PriceCache


def test_set_and_get():
    cache = PriceCache()
    cache.set("BTCUSDT", 65000.5)
    assert cache.get("BTCUSDT") == 65000.5


def test_get_unknown_symbol_returns_none():
    cache = PriceCache()
    assert cache.get("UNKNOWN") is None


def test_get_all_returns_copy():
    cache = PriceCache()
    cache.set("BTCUSDT", 65000.5)
    cache.set("ETHUSDT", 3200.0)
    result = cache.get_all()
    assert result == {"BTCUSDT": 65000.5, "ETHUSDT": 3200.0}
    # التأكد أنها نسخة وليس المرجع الأصلي
    result["BTCUSDT"] = 0
    assert cache.get("BTCUSDT") == 65000.5


def test_is_stale_for_fresh_price():
    cache = PriceCache()
    cache.set("BTCUSDT", 65000.5)
    assert not cache.is_stale("BTCUSDT", max_age_seconds=10)


def test_is_stale_for_old_price():
    cache = PriceCache()
    cache.set("BTCUSDT", 65000.5)
    # تزوير الطابع الزمني ليكون قديماً
    old_time = datetime.now(timezone.utc) - timedelta(seconds=30)
    with cache._lock:
        cache._last_updated["BTCUSDT"] = old_time
    assert cache.is_stale("BTCUSDT", max_age_seconds=10)


def test_is_stale_for_unknown_symbol():
    cache = PriceCache()
    assert cache.is_stale("UNKNOWN")


def test_thread_safety():
    """كتابة متعددة الخيوط — لا تلف في البيانات."""
    cache = PriceCache()
    errors: list[str] = []

    def writer(symbol: str, price: float) -> None:
        for _ in range(100):
            try:
                cache.set(symbol, price)
            except Exception as e:
                errors.append(str(e))

    threads = [
        threading.Thread(target=writer, args=("BTCUSDT", 65000.0)),
        threading.Thread(target=writer, args=("ETHUSDT", 3200.0)),
        threading.Thread(target=writer, args=("BTCUSDT", 66000.0)),
    ]
    for t in threads:
        t.start()
    for t in threads:
        t.join()

    assert not errors
    assert cache.get("ETHUSDT") == 3200.0
