"""Compute the reaction date for a filing based on its time bucket."""
from __future__ import annotations

import datetime as dt

from libs.common.time_utils import is_trading_day


def _advance_to_next_trading_day(date: dt.date) -> dt.date:
    """Return the next calendar day that is a trading day (starting from date+1)."""
    check = date + dt.timedelta(days=1)
    for _ in range(30):  # guard against infinite loop
        if is_trading_day(check):
            return check
        check += dt.timedelta(days=1)
    raise RuntimeError(f"Could not find trading day within 30 days of {date}")


def _to_trading_day_on_or_after(date: dt.date) -> dt.date:
    """Return date itself if a trading day, else the next trading day."""
    for _ in range(30):
        if is_trading_day(date):
            return date
        date += dt.timedelta(days=1)
    raise RuntimeError("Could not find trading day within 30 days")


def compute_reaction_date(
    event_date: dt.date,
    filing_time_bucket: str,
) -> dt.date:
    """Return the first trading day on which the market can react to the filing.

    Rules:
    - pre_market / regular_hours → same day if it is a trading day, else next.
    - post_market / unknown → next trading day after event_date.

    Args:
        event_date: The calendar date of the filing.
        filing_time_bucket: One of pre_market, regular_hours, post_market, unknown.

    Returns:
        The reaction date (a trading day).
    """
    if filing_time_bucket in ("pre_market", "regular_hours"):
        return _to_trading_day_on_or_after(event_date)
    else:
        # post_market or unknown: market reacts next trading day
        return _advance_to_next_trading_day(event_date)
