# backend/app/worker/jobs/proactive.py — 능동 감지 잡 → ProactiveCard (phase-14)
import json

from sqlmodel import Session, select

from ...automation.event_bus import bus
from ...config import get_settings
from ...models import CalEvent, FinanceCategory, ProactiveCard, ProactiveKind


def _dumps(d: dict) -> str:
    return json.dumps(d, ensure_ascii=False)


def _tomorrow() -> int:
    return get_settings().risk_today + 1


def run_proactive(session: Session) -> list[ProactiveCard]:
    """작업·일정·금융을 훑어 능동 카드를 만든다(임계값 기반 → 결정적).
    같은 시드에서 항상 같은 카드(id 고정 upsert)."""
    cards: list[ProactiveCard] = []
    cards += _detect_meeting_streak(session)
    cards += _detect_pricey_bill(session)
    out: list[ProactiveCard] = []
    for c in cards:
        existing = session.get(ProactiveCard, c.id)
        if existing:
            if existing.status == "dismissed":
                continue
            out.append(existing)
            continue
        session.add(c)
        out.append(c)
        bus.publish("proactive.detected", {"id": c.id, "kind": c.kind})
    session.commit()
    return out


def _detect_meeting_streak(s: Session) -> list[ProactiveCard]:
    """내일 회의가 3건 이상이면 점심 보호 카드."""
    day = _tomorrow()
    events = s.exec(select(CalEvent).where(CalEvent.day == day)).all()
    if len(events) >= 3:
        return [
            ProactiveCard(
                id="pc-streak",
                kind=ProactiveKind.schedule.value,
                icon="cal",
                tone="violet",
                title="내일 미팅 3연속 — 점심 비워뒀어요",
                why="연속 일정 사이 12시 공백을 보호 블록으로 잡았어요",
                cta="그대로 둘게요",
                action_kind="focus_block",
                action_payload=_dumps(
                    {
                        "day": day,
                        "start": "12:00",
                        "end": "13:00",
                        "type": "light",
                        "title": "점심·재충전 보호",
                    }
                ),
                detected_at="방금",
            )
        ]
    return []


def _detect_pricey_bill(s: Session) -> list[ProactiveCard]:
    """예산 초과 카테고리가 있으면 사유 확인 카드."""
    out: list[ProactiveCard] = []
    for cat in s.exec(select(FinanceCategory).where(FinanceCategory.over.is_(True))).all():
        out.append(
            ProactiveCard(
                id=f"pc-bill-{cat.id}",
                kind=ProactiveKind.finance.value,
                icon="wallet",
                tone="amber",
                title=f"{cat.name} 지출이 평소보다 많아요",
                why=f"이번 달 {cat.amt:,}원 · 예산을 넘었어요 — 사유 확인 권장",
                cta="자세히",
                action_kind="task",
                action_payload=_dumps({"title": f"{cat.name} 지출 사유 확인", "project_id": "me"}),
                detected_at="방금",
            )
        )
    return out
