"""
봉 간격 상수·빗썸(Upbit 호환) 캔들 API 경로.

분봉·일봉 외 주봉(10080)·월봉(43200)은 DB 테이블명 `{symbol}_{interval}` 에 그대로 사용합니다.
"""

from __future__ import annotations

from dateutil.relativedelta import relativedelta

from config import DAILY_INTERVAL_MIN, MONTH_INTERVAL_MIN, WEEK_INTERVAL_MIN

WM_INTERVALS: frozenset[int] = frozenset({WEEK_INTERVAL_MIN, MONTH_INTERVAL_MIN})

# 01_download·ops_sync 대상에서 제외 (DB 적재 안 함)
DOWNLOAD_EXCLUDED_INTERVALS: frozenset[int] = frozenset({1})


def is_excluded_from_download(interval: int) -> bool:
    """01_download·ops_sync에서 건너뛸 간격(1분봉 등)."""
    return interval in DOWNLOAD_EXCLUDED_INTERVALS


def is_week_or_month(interval: int) -> bool:
    """주봉·월봉 여부."""
    return interval in WM_INTERVALS


def candle_api_segment(interval: int) -> str:
    """
    REST 경로 세그먼트 (minutes/{n} 제외).

    Returns:
        'weeks' | 'months' | 'days' | minutes/{interval}
    """
    if interval == WEEK_INTERVAL_MIN:
        return "weeks"
    if interval == MONTH_INTERVAL_MIN:
        return "months"
    if interval >= DAILY_INTERVAL_MIN:
        return "days"
    return f"minutes/{interval}"


def interval_display_label(interval: int) -> str:
    """로그·UI용 라벨."""
    if interval == WEEK_INTERVAL_MIN:
        return "주봉"
    if interval == MONTH_INTERVAL_MIN:
        return "월봉"
    if interval >= DAILY_INTERVAL_MIN:
        return "일봉(1440)"
    return f"{interval}분봉"


def pagination_step(interval: int, chunk_bars: int) -> relativedelta:
    """
    get_coin_more_data 역순 수집 시 `to` 감소 단위.

    Args:
        interval: 봉 간격(분 표기).
        chunk_bars: API 1회 최대 봉 수(겹침 청크).

    Returns:
        relativedelta.
    """
    if interval == WEEK_INTERVAL_MIN:
        return relativedelta(weeks=chunk_bars)
    if interval == MONTH_INTERVAL_MIN:
        return relativedelta(months=chunk_bars)
    return relativedelta(minutes=interval * chunk_bars)


def bars_for_months(interval: int, months: int, *, extra_days: int = 0) -> int:
    """
    N개월치 예상 봉 수(여유 포함).

    Args:
        interval: 봉 간격.
        months: 보관·적재 개월 수.
        extra_days: 일봉 계열 여유 일수.

    Returns:
        API 요청 목표 봉 수.
    """
    if interval == WEEK_INTERVAL_MIN:
        return int(months * 30 / 7) + max(extra_days // 7, 5)
    if interval == MONTH_INTERVAL_MIN:
        return months + max(extra_days // 30, 2)
    if interval >= DAILY_INTERVAL_MIN:
        return months * 30 + extra_days
    bars_per_day = (24 * 60) // interval
    return months * 30 * bars_per_day + 200
