from __future__ import annotations

from datetime import datetime

import pandas as pd

from web_core import data as data_module


def _make_intraday_df(days: list[str]) -> pd.DataFrame:
    index_values: list[pd.Timestamp] = []
    for day in days:
        index_values.append(pd.Timestamp(f"{day} 14:30:00", tz="UTC"))
        index_values.append(pd.Timestamp(f"{day} 15:30:00", tz="UTC"))

    index = pd.DatetimeIndex(index_values)
    return pd.DataFrame(
        {
            "Open": [100.0 + i for i in range(len(index))],
            "High": [101.0 + i for i in range(len(index))],
            "Low": [99.0 + i for i in range(len(index))],
            "Close": [100.5 + i for i in range(len(index))],
            "Volume": [1000 + i for i in range(len(index))],
        },
        index=index,
    )


def test_fetch_ohlc_day_period_backfills_until_target_trading_days(monkeypatch) -> None:
    fixed_now = datetime(2026, 2, 17, 20, 0, 0)
    four_day_df = _make_intraday_df(["2026-02-12", "2026-02-13", "2026-02-14", "2026-02-17"])
    five_day_df = _make_intraday_df(["2026-02-11", "2026-02-12", "2026-02-13", "2026-02-14", "2026-02-17"])
    calls: list[dict[str, object]] = []

    class FakeTicker:
        def history(self, **kwargs: object) -> pd.DataFrame:
            calls.append(kwargs)
            start = kwargs.get("start")
            if start is None:
                return four_day_df.copy()
            lookback_days = (fixed_now - pd.Timestamp(start).to_pydatetime()).days
            return five_day_df.copy() if lookback_days >= 12 else four_day_df.copy()

    monkeypatch.setattr(data_module.yf, "Ticker", lambda symbol: FakeTicker())
    monkeypatch.setattr(data_module, "_utc_now", lambda: fixed_now)
    data_module.fetch_ohlc.clear()

    out = data_module.fetch_ohlc(symbol="TSLA", interval="2m", period="5d")
    session_days = pd.DatetimeIndex(out.index).normalize().unique()

    assert len(session_days) == 5
    assert pd.Timestamp("2026-02-11", tz="UTC") in session_days
    assert len(calls) >= 2
    assert all("start" in call and "end" in call for call in calls)


def test_fetch_ohlc_non_day_period_uses_period_request(monkeypatch) -> None:
    calls: list[dict[str, object]] = []
    month_df = _make_intraday_df(["2026-01-05", "2026-01-06", "2026-01-07"])

    class FakeTicker:
        def history(self, **kwargs: object) -> pd.DataFrame:
            calls.append(kwargs)
            return month_df.copy()

    monkeypatch.setattr(data_module.yf, "Ticker", lambda symbol: FakeTicker())
    data_module.fetch_ohlc.clear()

    out = data_module.fetch_ohlc(symbol="AAPL", interval="1h", period="1mo")

    assert len(out) == len(month_df)
    assert len(calls) == 1
    assert calls[0].get("period") == "1mo"
    assert "start" not in calls[0]
    assert "end" not in calls[0]
