from .base import BaseAgent
from ..db import create_task, update_task_status, add_log
from ..curator.pipeline import curate_weekly, CuratorError


class LottoAgent(BaseAgent):
    agent_id = "lotto"
    display_name = "로또 큐레이터"

    async def on_schedule(self) -> None:
        if self.state != "idle":
            return
        await self._run(source="auto")

    async def on_command(self, action: str, params: dict) -> dict:
        if action in ("curate_now", "curate_weekly"):
            return await self._run(source="manual")
        if action == "status":
            return {"ok": True, "message": f"{self.state}: {self.state_detail}"}
        if action in ("signal_check", "light_check", "sim_check", "deep_check"):
            source = action.replace("_check", "") if action != "signal_check" else "light"
            return await self.run_signal_check(source=source)
        if action == "daily_digest":
            return await self.run_daily_digest()
        return {"ok": False, "message": f"unknown action: {action}"}

    async def on_approval(self, task_id: str, approved: bool, feedback: str = "") -> None:
        pass

    async def run_signal_check(self, source: str = "light") -> dict:
        """비-LLM 시그널 평가 (light/sim) 또는 deep_check (LLM 호출 후).

        Phase 3 (Task 9): urgent 시그널 텔레그램 발송 + throttle/daily-cap 추가.
        """
        from ..curator.signal_runner import run_signal_check
        from ..config import LOTTO_Z_NORMAL, LOTTO_Z_URGENT
        from ..db import add_log

        if self.state not in ("idle", "reporting"):
            return {"ok": False, "message": f"busy ({self.state})"}

        try:
            curate_result = None

            # 회차 단위 메트릭(drift/confidence) 가드를 위해 항상 최신 회차 가져옴
            from ..service_proxy import lotto_latest_draw
            current_draw_no = await lotto_latest_draw()

            if source == "deep":
                from ..curator.pipeline import curate_weekly
                cw = await curate_weekly(source="signal_deep")
                # curate_weekly returns {"ok", "draw_no", "confidence", "tokens", "payload"}
                curate_result = {"confidence": cw.get("confidence")}
                # deep_check 시 curate_weekly가 반환하는 draw_no를 우선 사용 (직접 수집)
                if cw.get("draw_no"):
                    current_draw_no = cw.get("draw_no")

            outcome = await run_signal_check(
                source=source,
                z_normal=LOTTO_Z_NORMAL,
                z_urgent=LOTTO_Z_URGENT,
                curate_result=curate_result,
                current_draw_no=current_draw_no,
            )
            add_log(
                self.agent_id,
                f"signal_check({source}) → overall={outcome['overall_fire']} results={len(outcome['results'])}",
            )

            # --- Throttle + 텔레그램 urgent 발송 ---
            from ..config import LOTTO_THROTTLE_HOURS, LOTTO_URGENT_DAILY_MAX
            from ..db import (
                get_last_signal_notification, get_recent_urgent_count,
                mark_signal_notified,
            )
            from ..notifiers.telegram_lotto import send_urgent_signal

            if outcome["overall_fire"] == "urgent":
                if get_recent_urgent_count(hours=24) >= LOTTO_URGENT_DAILY_MAX:
                    add_log(
                        self.agent_id,
                        "urgent daily cap 도달 → normal로 강등 (digest 합류)",
                        level="warning",
                    )
                else:
                    blocked = False
                    for r in outcome["results"]:
                        if r["fire_level"] in ("normal", "urgent"):
                            last = get_last_signal_notification(
                                metric=r["metric"], fire_level=r["fire_level"],
                                hours=LOTTO_THROTTLE_HOURS,
                            )
                            if last:
                                blocked = True
                                break
                    if not blocked:
                        from datetime import datetime, timezone
                        event = {
                            "fire_level": "urgent",
                            "triggered_at": datetime.now(timezone.utc).isoformat(),
                            "results": outcome["results"],
                        }
                        await send_urgent_signal(event)
                        for r in outcome["results"]:
                            if r["fire_level"] in ("normal", "urgent"):
                                mark_signal_notified(r["signal_id"])
                        add_log(self.agent_id, f"urgent 텔레그램 발송 완료 (시그널 {len(outcome['results'])}개 마킹)")

            return {"ok": True, **outcome}
        except Exception as e:
            add_log(self.agent_id, f"signal_check 예외: {e}", level="error")
            return {"ok": False, "message": f"{type(e).__name__}: {e}"}

    async def run_daily_digest(self) -> dict:
        """일일 요약 — 지난 24h normal/urgent 발화를 묶어 텔레그램 1통."""
        from ..db import (
            get_recent_lotto_signals, get_signals_history, add_log,
            get_baseline,
        )
        from ..notifiers.telegram_lotto import send_signal_summary

        sigs = get_recent_lotto_signals(hours=24, min_fire="normal")
        total_24h = get_signals_history(days=1)
        evaluated = len(total_24h)

        # weights_trend: drift_weights_cache의 prev/curr 차이
        trend = {}
        try:
            cache = get_baseline("drift_weights_cache")
            if cache and isinstance(cache["window_values"], list) and len(cache["window_values"]) >= 2:
                prev_w = cache["window_values"][-2]
                curr_w = cache["window_values"][-1]
                trend = {
                    k: curr_w.get(k, 0.0) - prev_w.get(k, 0.0)
                    for k in (set(prev_w) | set(curr_w))
                }
        except Exception as e:
            add_log(self.agent_id, f"weights_trend 계산 실패: {e}", level="warning")

        digest = {
            "evaluated": evaluated,
            "fired": len(sigs),
            "signals": sigs,
            "weights_trend": trend,
        }
        await send_signal_summary(digest)
        add_log(self.agent_id, f"daily_digest 발송: 평가 {evaluated} / 발화 {len(sigs)}")
        return {"ok": True, **digest}

    async def _run(self, source: str) -> dict:
        task_id = create_task(self.agent_id, "curate_weekly", {"source": source})
        await self.transition("working", "후보 수집 및 AI 큐레이션 중...", task_id)
        try:
            result = await curate_weekly(source=source)
            update_task_status(task_id, "succeeded", result_data={
                k: v for k, v in result.items() if k != "payload"
            })
            await self.transition("reporting", f"#{result['draw_no']} 브리핑 저장 완료")
            add_log(self.agent_id, f"큐레이션 완료: #{result['draw_no']} conf={result['confidence']}", task_id=task_id)

            # 텔레그램 헤드라인 푸시 (실패해도 큐레이션은 성공으로 마감)
            try:
                from ..notifiers.telegram_lotto import send_curator_briefing
                await send_curator_briefing(result["payload"])
            except Exception as e:
                add_log(self.agent_id, f"텔레그램 알림 실패: {e}", level="warning", task_id=task_id)

            await self.transition("idle", "대기 중")
            return {"ok": True, **{k: v for k, v in result.items() if k != "payload"}}
        except CuratorError as e:
            update_task_status(task_id, "failed", result_data={"error": str(e)})
            add_log(self.agent_id, f"큐레이션 실패: {e}", level="error", task_id=task_id)
            await self.transition("idle", "오류")
            return {"ok": False, "message": str(e)}
        except Exception as e:
            update_task_status(task_id, "failed", result_data={"error": str(e)})
            add_log(self.agent_id, f"큐레이션 예외: {e}", level="error", task_id=task_id)
            await self.transition("idle", "오류")
            return {"ok": False, "message": f"{type(e).__name__}: {e}"}
