"""
05 연동: 최신 봉에서 matched 규칙 평가.
"""

from __future__ import annotations

import time
from typing import Any

import pandas as pd

from config import CHART_LOOKBACK_DAYS, MATCH_LIVE_CACHE_SEC, MATCH_LIVE_LOOKBACK_DAYS, SYMBOL
from deepcoin.data.mtf_bb import load_frames_from_db
from deepcoin.matching.load_rules import load_monitor_rules
from deepcoin.matching.rule_eval import (
    build_mtf_scan_frame,
    conditions_columns,
    eval_conditions,
)
from deepcoin.ops.monitor import Monitor

_cache: dict[str, Any] = {"ts": 0.0, "frame": None, "rules_key": ""}


def evaluate_live_rules(
    rules: list[dict[str, Any]] | None = None,
    *,
    lookback_days: int | None = None,
    force_refresh: bool = False,
) -> list[dict[str, Any]]:
    """
    최신 완성 3분봉에서 활성 규칙 발화 여부를 검사합니다.

    Args:
        rules: 규칙 목록. None이면 matched_rules에서 로드.
        lookback_days: DB 조회 일수(기본 MATCH_LIVE_LOOKBACK_DAYS).
        force_refresh: 캐시 무시.

    Returns:
        발화한 규칙 정보 리스트 (rule_id, side, dt, close).
    """
    active = rules if rules is not None else load_monitor_rules()
    if not active:
        return []

    lb = lookback_days if lookback_days is not None else MATCH_LIVE_LOOKBACK_DAYS
    rules_key = ",".join(r["rule_id"] for r in active)
    now = time.time()
    global _cache
    if (
        not force_refresh
        and _cache.get("frame") is not None
        and now - float(_cache.get("ts", 0)) < MATCH_LIVE_CACHE_SEC
        and _cache.get("rules_key") == rules_key
    ):
        frame = _cache["frame"]
    else:
        mon = Monitor(cooldown_file=None)
        days = min(lb, CHART_LOOKBACK_DAYS)
        frames = load_frames_from_db(mon, SYMBOL, lookback_days=days)
        needed = conditions_columns(active)
        frame = build_mtf_scan_frame(frames, needed)
        _cache["ts"] = now
        _cache["frame"] = frame
        _cache["rules_key"] = rules_key

    if frame.empty:
        return []

    ts = frame.index[-1]
    row_frame = frame.iloc[[-1]]
    fired: list[dict[str, Any]] = []
    close_col = "close"
    for rule in active:
        if not eval_conditions(row_frame, rule["conditions"]).iloc[0]:
            continue
        fired.append(
            {
                "rule_id": rule["rule_id"],
                "side": rule["side"],
                "kind": rule.get("kind", ""),
                "dt": ts.strftime("%Y-%m-%d %H:%M:%S"),
                "close": float(row_frame[close_col].iloc[0]),
            }
        )
    return fired
