"""Tests for scheduler interval logic."""
from datetime import datetime

import pytest

from ai_trade.scheduler import _next_interval, _is_market_day, KST


def _kst(year, month, day, hour, minute=0):
    return datetime(year, month, day, hour, minute, tzinfo=KST)


def test_next_interval_pre_market_5min():
    now = _kst(2026, 5, 18, 8, 30)  # Monday 08:30
    assert _next_interval(now) == 300


def test_next_interval_market_open_1min():
    now = _kst(2026, 5, 18, 10, 0)  # Monday 10:00
    assert _next_interval(now) == 60


def test_next_interval_post_market_5min():
    now = _kst(2026, 5, 18, 17, 0)  # Monday 17:00
    assert _next_interval(now) == 300


def test_next_interval_overnight_skip_to_next_morning():
    now = _kst(2026, 5, 18, 2, 30)  # Monday 02:30 (dead zone, not NXT window)
    interval = _next_interval(now)
    # Dead zone 23:30-04:30 → next 04:30 is ~2h away
    assert 2 * 3600 - 60 < interval < 2 * 3600 + 60


def test_next_interval_holiday_skip():
    # 2026-05-05 어린이날 (Tuesday holiday)
    now = _kst(2026, 5, 5, 10, 0)
    assert _is_market_day(now) is False
    interval = _next_interval(now)
    # Next: 2026-05-06 (Wed) 07:00, ~21h away
    assert 20 * 3600 < interval < 22 * 3600


def test_next_interval_at_market_open_boundary():
    """09:00:00 정확 second → 60초 (market 구간 진입)."""
    now = _kst(2026, 5, 18, 9, 0)  # Monday 09:00:00
    assert _next_interval(now) == 60


def test_next_interval_at_market_close_boundary():
    """15:30:00 정확 second → 300초 (post-market 구간 진입)."""
    now = _kst(2026, 5, 18, 15, 30)  # Monday 15:30:00
    assert _next_interval(now) == 300


def test_next_interval_at_polling_window_end_boundary():
    """23:30:00 정확 second → dead zone skip (다음 04:30 까지)."""
    now = _kst(2026, 5, 18, 23, 30)  # Monday 23:30:00 (NXT_PRE_END boundary)
    interval = _next_interval(now)
    # Dead zone 23:30-04:30 → next 04:30 is ~5h away
    assert 5 * 3600 - 60 < interval < 5 * 3600 + 60


def test_next_interval_nxt_evening_5min():
    """22:00 평일 (NXT 야간) → 300 (5분)."""
    now = _kst(2026, 5, 18, 22, 0)
    assert _next_interval(now) == 300


def test_next_interval_nxt_dawn_5min():
    """05:30 평일 (NXT 새벽) → 300 (5분)."""
    now = _kst(2026, 5, 18, 5, 30)
    assert _next_interval(now) == 300


def test_next_interval_dead_zone_skip():
    """02:00 평일 (dead zone 23:30-04:30) → 다음 04:30 까지 (~9000s)."""
    now = _kst(2026, 5, 18, 2, 0)
    interval = _next_interval(now)
    # 02:00 → 04:30 = 2.5h = 9000s
    assert 9000 - 60 < interval < 9000 + 60


# ----- F3 post-close 상태기반 트리거 -----

from datetime import date as _date  # noqa: E402
from ai_trade.scheduler import _is_post_close_trigger  # noqa: E402


def test_post_close_trigger_fires_at_1601_if_not_yet_today():
    """F3 — 16:01에 깬 cycle도 오늘 아직 안 돌렸으면 trigger."""
    now = _kst(2026, 5, 18, 16, 1)
    assert _is_post_close_trigger(now, last_post_close_date=None) is True


def test_post_close_trigger_skips_if_already_today():
    """F3 — 이미 오늘 돌렸으면 trigger 안 함."""
    now = _kst(2026, 5, 18, 16, 5)
    today = _date(2026, 5, 18)
    assert _is_post_close_trigger(now, last_post_close_date=today) is False


def test_post_close_trigger_skips_before_1600():
    """F3 — 16:00 전에는 trigger 안 함."""
    now = _kst(2026, 5, 18, 15, 59)
    assert _is_post_close_trigger(now, last_post_close_date=None) is False


def test_post_close_trigger_fires_next_day_after_reset():
    """F3 — 다음 영업일이 되면 다시 trigger."""
    now = _kst(2026, 5, 19, 16, 0)
    yesterday = _date(2026, 5, 18)
    assert _is_post_close_trigger(now, last_post_close_date=yesterday) is True


def test_post_close_trigger_skips_on_holiday():
    """F3 — 휴장일에는 trigger 안 함 (2026-05-05 어린이날)."""
    now = _kst(2026, 5, 5, 16, 30)
    assert _is_post_close_trigger(now, last_post_close_date=None) is False
