"""
API Routes fuer Alerts Agent.

Endpoints:
- POST /alerts/ingest - Manuell Alerts importieren
- POST /alerts/run - Scoring Pipeline starten
- GET /alerts/inbox - Inbox Items abrufen
- POST /alerts/feedback - Relevanz-Feedback geben
- GET /alerts/profile - User Relevance Profile
- PUT /alerts/profile - Profile aktualisieren
"""

import os
from datetime import datetime
from typing import Optional
from fastapi import APIRouter, HTTPException, Query

from ..models.alert_item import AlertItem, AlertStatus
from ..models.relevance_profile import RelevanceProfile, PriorityItem
from ..processing.relevance_scorer import RelevanceDecision, RelevanceScorer
from .schemas import (
    AlertIngestRequest, AlertIngestResponse,
    AlertRunRequest, AlertRunResponse,
    InboxItem, InboxResponse,
    FeedbackRequest, FeedbackResponse,
    ProfilePriorityRequest, ProfileUpdateRequest, ProfileResponse,
)


router = APIRouter(prefix="/alerts", tags=["alerts"])

# LLM Scorer Konfiguration aus Umgebungsvariablen
LLM_GATEWAY_URL = os.getenv("LLM_GATEWAY_URL", "http://localhost:8000/llm")
LLM_API_KEY = os.getenv("LLM_API_KEYS", "").split(",")[0] if os.getenv("LLM_API_KEYS") else ""
ALERTS_USE_LLM = os.getenv("ALERTS_USE_LLM", "false").lower() == "true"


# ============================================================================
# In-Memory Storage (spaeter durch DB ersetzen)
# ============================================================================

_alerts_store: dict[str, AlertItem] = {}
_profile_store: dict[str, RelevanceProfile] = {}


# ============================================================================
# Endpoints
# ============================================================================

@router.post("/ingest", response_model=AlertIngestResponse)
async def ingest_alert(request: AlertIngestRequest):
    """
    Manuell einen Alert importieren.

    Nuetzlich fuer Tests oder manuelles Hinzufuegen von Artikeln.
    """
    alert = AlertItem(
        title=request.title,
        url=request.url,
        snippet=request.snippet or "",
        topic_label=request.topic_label,
        published_at=request.published_at,
    )

    _alerts_store[alert.id] = alert

    return AlertIngestResponse(
        id=alert.id,
        status="created",
        message=f"Alert '{alert.title[:50]}...' importiert"
    )


@router.post("/run", response_model=AlertRunResponse)
async def run_scoring_pipeline(request: AlertRunRequest):
    """
    Scoring-Pipeline fuer neue Alerts starten.

    Bewertet alle unbewerteten Alerts und klassifiziert sie
    in KEEP, DROP oder REVIEW.

    Wenn ALERTS_USE_LLM=true, wird das LLM Gateway fuer Scoring verwendet.
    Sonst wird ein schnelles Keyword-basiertes Scoring durchgefuehrt.
    """
    import time
    start = time.time()

    # Alle unbewerteten Alerts holen
    alerts_to_score = [
        a for a in _alerts_store.values()
        if a.status == AlertStatus.NEW or (not request.skip_scored and a.status == AlertStatus.SCORED)
    ][:request.limit]

    if not alerts_to_score:
        return AlertRunResponse(
            processed=0, keep=0, drop=0, review=0, errors=0,
            duration_ms=int((time.time() - start) * 1000)
        )

    keep = drop = review = errors = 0

    # Profil fuer Scoring laden
    profile = _profile_store.get("default")
    if not profile:
        profile = RelevanceProfile.create_default_education_profile()
        profile.id = "default"
        _profile_store["default"] = profile

    if ALERTS_USE_LLM and LLM_API_KEY:
        # LLM-basiertes Scoring ueber Gateway
        scorer = RelevanceScorer(
            gateway_url=LLM_GATEWAY_URL,
            api_key=LLM_API_KEY,
            model="breakpilot-teacher-8b",
        )
        try:
            results = await scorer.score_batch(alerts_to_score, profile=profile)
            for result in results:
                if result.error:
                    errors += 1
                elif result.decision == RelevanceDecision.KEEP:
                    keep += 1
                elif result.decision == RelevanceDecision.DROP:
                    drop += 1
                else:
                    review += 1
        finally:
            await scorer.close()
    else:
        # Fallback: Keyword-basiertes Scoring (schnell, ohne LLM)
        for alert in alerts_to_score:
            title_lower = alert.title.lower()
            snippet_lower = (alert.snippet or "").lower()
            combined = title_lower + " " + snippet_lower

            # Ausschluesse aus Profil pruefen
            if any(excl.lower() in combined for excl in profile.exclusions):
                alert.relevance_score = 0.15
                alert.relevance_decision = RelevanceDecision.DROP.value
                drop += 1
            # Prioritaeten aus Profil pruefen
            elif any(
                p.label.lower() in combined or
                any(kw.lower() in combined for kw in (p.keywords if hasattr(p, 'keywords') else []))
                for p in profile.priorities
            ):
                alert.relevance_score = 0.85
                alert.relevance_decision = RelevanceDecision.KEEP.value
                keep += 1
            else:
                alert.relevance_score = 0.55
                alert.relevance_decision = RelevanceDecision.REVIEW.value
                review += 1

            alert.status = AlertStatus.SCORED

    duration_ms = int((time.time() - start) * 1000)

    return AlertRunResponse(
        processed=len(alerts_to_score),
        keep=keep,
        drop=drop,
        review=review,
        errors=errors,
        duration_ms=duration_ms,
    )


@router.get("/inbox", response_model=InboxResponse)
async def get_inbox(
    decision: Optional[str] = Query(default=None, description="Filter: KEEP, DROP, REVIEW"),
    page: int = Query(default=1, ge=1),
    page_size: int = Query(default=20, ge=1, le=100),
):
    """
    Inbox Items abrufen.

    Filtert nach Relevanz-Entscheidung. Standard zeigt KEEP und REVIEW.
    """
    # Filter Alerts
    alerts = list(_alerts_store.values())

    if decision:
        alerts = [a for a in alerts if a.relevance_decision == decision.upper()]
    else:
        # Standard: KEEP und REVIEW zeigen
        alerts = [a for a in alerts if a.relevance_decision in ["KEEP", "REVIEW"]]

    # Sortieren nach Score (absteigend)
    alerts.sort(key=lambda a: a.relevance_score or 0, reverse=True)

    # Pagination
    total = len(alerts)
    start_idx = (page - 1) * page_size
    end_idx = start_idx + page_size
    page_alerts = alerts[start_idx:end_idx]

    items = [
        InboxItem(
            id=a.id,
            title=a.title,
            url=a.url,
            snippet=a.snippet,
            topic_label=a.topic_label,
            published_at=a.published_at,
            relevance_score=a.relevance_score,
            relevance_decision=a.relevance_decision,
            relevance_summary=a.relevance_summary,
            status=a.status.value,
        )
        for a in page_alerts
    ]

    return InboxResponse(
        items=items,
        total=total,
        page=page,
        page_size=page_size,
    )


@router.post("/feedback", response_model=FeedbackResponse)
async def submit_feedback(request: FeedbackRequest):
    """
    Feedback zu einem Alert geben.

    Das Feedback wird verwendet um das Relevanzprofil zu verbessern.
    """
    alert = _alerts_store.get(request.alert_id)
    if not alert:
        raise HTTPException(status_code=404, detail="Alert nicht gefunden")

    # Alert Status aktualisieren
    alert.status = AlertStatus.REVIEWED

    # Profile aktualisieren (Default-Profile fuer Demo)
    profile = _profile_store.get("default")
    if not profile:
        profile = RelevanceProfile.create_default_education_profile()
        profile.id = "default"
        _profile_store["default"] = profile

    profile.update_from_feedback(
        alert_title=alert.title,
        alert_url=alert.url,
        is_relevant=request.is_relevant,
        reason=request.reason or "",
    )

    return FeedbackResponse(
        success=True,
        message="Feedback gespeichert",
        profile_updated=True,
    )


@router.get("/profile", response_model=ProfileResponse)
async def get_profile(user_id: Optional[str] = Query(default=None)):
    """
    Relevanz-Profil abrufen.

    Ohne user_id wird das Default-Profil zurueckgegeben.
    """
    profile_id = user_id or "default"
    profile = _profile_store.get(profile_id)

    if not profile:
        # Default-Profile erstellen
        profile = RelevanceProfile.create_default_education_profile()
        profile.id = profile_id
        _profile_store[profile_id] = profile

    return ProfileResponse(
        id=profile.id,
        priorities=[p.to_dict() if isinstance(p, PriorityItem) else p
                    for p in profile.priorities],
        exclusions=profile.exclusions,
        policies=profile.policies,
        total_scored=profile.total_scored,
        total_kept=profile.total_kept,
        total_dropped=profile.total_dropped,
        accuracy_estimate=profile.accuracy_estimate,
    )


@router.put("/profile", response_model=ProfileResponse)
async def update_profile(
    request: ProfileUpdateRequest,
    user_id: Optional[str] = Query(default=None),
):
    """
    Relevanz-Profil aktualisieren.

    Erlaubt Anpassung von Prioritaeten, Ausschluessen und Policies.
    """
    profile_id = user_id or "default"
    profile = _profile_store.get(profile_id)

    if not profile:
        profile = RelevanceProfile()
        profile.id = profile_id

    # Updates anwenden
    if request.priorities is not None:
        profile.priorities = [
            PriorityItem(
                label=p.label,
                weight=p.weight,
                keywords=p.keywords,
                description=p.description,
            )
            for p in request.priorities
        ]

    if request.exclusions is not None:
        profile.exclusions = request.exclusions

    if request.policies is not None:
        profile.policies = request.policies

    profile.updated_at = datetime.utcnow()
    _profile_store[profile_id] = profile

    return ProfileResponse(
        id=profile.id,
        priorities=[p.to_dict() if isinstance(p, PriorityItem) else p
                    for p in profile.priorities],
        exclusions=profile.exclusions,
        policies=profile.policies,
        total_scored=profile.total_scored,
        total_kept=profile.total_kept,
        total_dropped=profile.total_dropped,
        accuracy_estimate=profile.accuracy_estimate,
    )


@router.get("/stats")
async def get_stats():
    """
    Statistiken ueber Alerts und Scoring.
    """
    alerts = list(_alerts_store.values())
    total = len(alerts)

    new_alerts = sum(1 for a in alerts if a.status == AlertStatus.NEW)
    kept_alerts = sum(1 for a in alerts if a.relevance_decision == "KEEP")
    review_alerts = sum(1 for a in alerts if a.relevance_decision == "REVIEW")
    dropped_alerts = sum(1 for a in alerts if a.relevance_decision == "DROP")

    total_topics = 0
    active_topics = 0
    total_rules = 0

    try:
        from alerts_agent.db import get_db
        from alerts_agent.db.repository import TopicRepository, RuleRepository

        db_gen = get_db()
        db = next(db_gen, None)
        if db:
            try:
                topic_repo = TopicRepository(db)
                rule_repo = RuleRepository(db)

                all_topics = topic_repo.get_all()
                total_topics = len(all_topics)
                active_topics = len([t for t in all_topics if t.is_active])

                all_rules = rule_repo.get_all()
                total_rules = len(all_rules)
            finally:
                try:
                    next(db_gen, None)
                except StopIteration:
                    pass
    except Exception:
        pass

    scored_alerts = [a for a in alerts if a.relevance_score is not None]
    avg_score = sum(a.relevance_score for a in scored_alerts) / len(scored_alerts) if scored_alerts else 0.0

    return {
        "total_alerts": total,
        "new_alerts": new_alerts,
        "kept_alerts": kept_alerts,
        "review_alerts": review_alerts,
        "dropped_alerts": dropped_alerts,
        "total_topics": total_topics,
        "active_topics": active_topics,
        "total_rules": total_rules,
        "avg_score": avg_score,
        "by_status": {
            "new": new_alerts,
            "scored": sum(1 for a in alerts if a.status == AlertStatus.SCORED),
            "reviewed": sum(1 for a in alerts if a.status == AlertStatus.REVIEWED),
        },
        "by_decision": {
            "KEEP": kept_alerts,
            "REVIEW": review_alerts,
            "DROP": dropped_alerts,
        },
    }
