# backend/app/routers/automation.py
import uuid

from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select

from ..automation.event_bus import bus
from ..automation.events import AUTOMATION_MATCHED
from ..automation.nl_parser import EXAMPLES, parse_rule
from ..automation.suggester import scan
from ..db import get_session
from ..models import (
    AutomationRule,
    AutomationRunLog,
    AutomationStats,
    AutomationSuggestion,
)
from ..schemas import (
    AutomationPageOut,
    AutomationStatsOut,
    FlowOut,
    ParsePreviewOut,
    ParseRequest,
    RuleCreate,
    RuleOut,
    RulePatch,
    RunLogOut,
    SuggestionOut,
)

router = APIRouter()  # prefix 없음. main.py 에서 prefix="/api" 등록.


def _rule_out(r: AutomationRule) -> RuleOut:
    return RuleOut(
        id=r.id,
        name=r.name,
        cat=r.cat,
        trigger=r.trigger,
        cond=r.cond,
        action=r.action,
        on=r.on,
        last=r.last,
        runs=r.runs,
        fresh=r.fresh,
        source=r.source,
    )


def _sug_out(g: AutomationSuggestion) -> SuggestionOut:
    return SuggestionOut(
        id=g.id,
        pattern=g.pattern,
        offer=FlowOut(trigger=g.offer_trigger, cond=g.offer_cond, action=g.offer_action),
        offer_name=g.offer_name,
        offer_cat=g.offer_cat,
        status=g.status,
    )


@router.get("/automation", response_model=AutomationPageOut)
def get_page(s: Session = Depends(get_session)):
    rules = s.exec(select(AutomationRule).order_by(AutomationRule.created_at)).all()
    sugs = s.exec(select(AutomationSuggestion).where(AutomationSuggestion.status == "open")).all()
    logs = s.exec(select(AutomationRunLog).order_by(AutomationRunLog.sort_order)).all()
    st = s.exec(select(AutomationStats)).first()
    active = sum(1 for r in rules if r.on)
    stats = AutomationStatsOut(
        active=active,
        runs_week=(st.runs_week if st else 0),
        saved=(st.saved if st else ""),
    )
    examples = [
        ParsePreviewOut(
            matched=True,
            name=pr.name,
            cat=pr.cat,
            parse=FlowOut(trigger=pr.trigger, cond=pr.cond, action=pr.action),
            model=pr.model,
            confidence=pr.confidence,
        )
        for pr in EXAMPLES.values()
    ]
    return AutomationPageOut(
        stats=stats,
        rules=[_rule_out(r) for r in rules],
        suggests=[_sug_out(g) for g in sugs],
        log=[
            RunLogOut(id=log.id, time=log.time, rule=log.rule, text=log.text, undone=log.undone)
            for log in logs
        ],
        examples=examples,
    )


@router.post("/automation/parse", response_model=ParsePreviewOut)
def parse(body: ParseRequest):
    pr = parse_rule(body.text)
    return ParsePreviewOut(
        matched=pr.matched,
        name=pr.name,
        cat=pr.cat,
        parse=FlowOut(trigger=pr.trigger, cond=pr.cond, action=pr.action),
        model=pr.model,
        confidence=pr.confidence,
    )


@router.post("/automation/rules", response_model=RuleOut)
def create_rule(body: RuleCreate, s: Session = Depends(get_session)):
    r = AutomationRule(
        id="rule-" + uuid.uuid4().hex[:8],
        name=body.name,
        cat=body.cat,
        trigger=body.trigger,
        cond=body.cond,
        action=body.action,
        on=True,
        last="방금 만듦",
        runs=0,
        fresh=True,
        source=body.source or "user",
    )
    s.add(r)
    s.commit()
    s.refresh(r)
    return _rule_out(r)


@router.patch("/automation/rules/{rid}", response_model=RuleOut)
def patch_rule(rid: str, body: RulePatch, s: Session = Depends(get_session)):
    r = s.get(AutomationRule, rid)
    if not r:
        raise HTTPException(404, "rule not found")
    for k, v in body.model_dump(exclude_unset=True).items():
        setattr(r, k, v)
    s.add(r)
    s.commit()
    s.refresh(r)
    return _rule_out(r)


@router.post("/automation/rules/{rid}/toggle", response_model=RuleOut)
def toggle_rule(rid: str, s: Session = Depends(get_session)):
    r = s.get(AutomationRule, rid)
    if not r:
        raise HTTPException(404, "rule not found")
    r.on = not r.on
    s.add(r)
    s.commit()
    s.refresh(r)
    return _rule_out(r)


@router.delete("/automation/rules/{rid}")
def delete_rule(rid: str, s: Session = Depends(get_session)):
    r = s.get(AutomationRule, rid)
    if not r:
        raise HTTPException(404, "rule not found")
    s.delete(r)
    s.commit()
    return {"deleted": rid}


@router.post("/automation/suggestions/{sid}/accept", response_model=RuleOut)
def accept_suggestion(sid: str, s: Session = Depends(get_session)):
    g = s.get(AutomationSuggestion, sid)
    if not g:
        raise HTTPException(404, "suggestion not found")
    g.status = "accepted"
    s.add(g)
    r = AutomationRule(
        id="rule-" + uuid.uuid4().hex[:8],
        name=g.offer_name,
        cat=g.offer_cat,
        trigger=g.offer_trigger,
        cond=g.offer_cond,
        action=g.offer_action,
        on=True,
        last="방금 만듦",
        runs=0,
        fresh=True,
        source="suggestion",
    )
    s.add(r)
    s.commit()
    s.refresh(r)
    return _rule_out(r)


@router.post("/automation/suggestions/{sid}/dismiss")
def dismiss_suggestion(sid: str, s: Session = Depends(get_session)):
    g = s.get(AutomationSuggestion, sid)
    if not g:
        raise HTTPException(404, "suggestion not found")
    g.status = "dismissed"
    s.add(g)
    s.commit()
    return {"dismissed": sid}


@router.post("/automation/suggest/scan")
def suggest_scan(s: Session = Depends(get_session)):
    created = scan(s, bus)  # 생성 제안마다 automation.suggested 발행
    return {"created": [g.id for g in created]}


@router.get("/automation/log", response_model=list[RunLogOut])
def get_log(s: Session = Depends(get_session)):
    logs = s.exec(select(AutomationRunLog).order_by(AutomationRunLog.sort_order)).all()
    return [
        RunLogOut(id=log.id, time=log.time, rule=log.rule, text=log.text, undone=log.undone)
        for log in logs
    ]


@router.post("/automation/trigger")
def manual_trigger(trigger_key: str, s: Session = Depends(get_session)):
    """데모/테스트용 수동 트리거 — AUTOMATION_MATCHED 발행(스케줄러는 phase-14).
    evaluator 가 구독해 매칭 규칙을 승인 큐에 enqueue 한다."""
    ev = bus.publish(
        AUTOMATION_MATCHED,
        {"trigger_key": trigger_key, "ctx": {"title": f"{trigger_key} 규칙 실행"}},
    )
    return {"published": ev.type, "trigger_key": trigger_key}
