"""
Topic API Routes für Alerts Agent.

CRUD-Operationen für Alert-Topics (Feed-Quellen).
"""
from typing import List, Optional
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, BackgroundTasks
from pydantic import BaseModel, Field, HttpUrl

from sqlalchemy.orm import Session as DBSession
from alerts_agent.db import get_db
from alerts_agent.db.repository import TopicRepository, AlertItemRepository
from alerts_agent.db.models import FeedTypeEnum


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


# =============================================================================
# PYDANTIC MODELS
# =============================================================================

class TopicCreate(BaseModel):
    """Request-Model für Topic-Erstellung."""
    name: str = Field(..., min_length=1, max_length=255)
    description: str = Field(default="", max_length=2000)
    feed_url: Optional[str] = Field(default=None, max_length=2000)
    feed_type: str = Field(default="rss")  # rss, email, webhook
    fetch_interval_minutes: int = Field(default=60, ge=5, le=1440)
    is_active: bool = Field(default=True)


class TopicUpdate(BaseModel):
    """Request-Model für Topic-Update."""
    name: Optional[str] = Field(default=None, min_length=1, max_length=255)
    description: Optional[str] = Field(default=None, max_length=2000)
    feed_url: Optional[str] = Field(default=None, max_length=2000)
    feed_type: Optional[str] = None
    fetch_interval_minutes: Optional[int] = Field(default=None, ge=5, le=1440)
    is_active: Optional[bool] = None


class TopicResponse(BaseModel):
    """Response-Model für Topic."""
    id: str
    name: str
    description: str
    feed_url: Optional[str]
    feed_type: str
    is_active: bool
    fetch_interval_minutes: int
    last_fetched_at: Optional[datetime]
    last_fetch_error: Optional[str]
    total_items_fetched: int
    items_kept: int
    items_dropped: int
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class TopicListResponse(BaseModel):
    """Response-Model für Topic-Liste."""
    topics: List[TopicResponse]
    total: int


class TopicStatsResponse(BaseModel):
    """Response-Model für Topic-Statistiken."""
    topic_id: str
    name: str
    total_alerts: int
    by_status: dict
    by_decision: dict
    keep_rate: Optional[float]


class FetchResultResponse(BaseModel):
    """Response-Model für manuellen Fetch."""
    success: bool
    topic_id: str
    new_items: int
    duplicates_skipped: int
    error: Optional[str] = None


# =============================================================================
# API ENDPOINTS
# =============================================================================

@router.post("", response_model=TopicResponse, status_code=201)
async def create_topic(
    topic: TopicCreate,
    db: DBSession = Depends(get_db),
) -> TopicResponse:
    """
    Erstellt ein neues Topic (Feed-Quelle).

    Topics repräsentieren Google Alerts RSS-Feeds oder andere Feed-Quellen.
    """
    repo = TopicRepository(db)

    created = repo.create(
        name=topic.name,
        description=topic.description,
        feed_url=topic.feed_url,
        feed_type=topic.feed_type,
        fetch_interval_minutes=topic.fetch_interval_minutes,
        is_active=topic.is_active,
    )

    return TopicResponse(
        id=created.id,
        name=created.name,
        description=created.description or "",
        feed_url=created.feed_url,
        feed_type=created.feed_type.value if created.feed_type else "rss",
        is_active=created.is_active,
        fetch_interval_minutes=created.fetch_interval_minutes,
        last_fetched_at=created.last_fetched_at,
        last_fetch_error=created.last_fetch_error,
        total_items_fetched=created.total_items_fetched,
        items_kept=created.items_kept,
        items_dropped=created.items_dropped,
        created_at=created.created_at,
        updated_at=created.updated_at,
    )


@router.get("", response_model=TopicListResponse)
async def list_topics(
    is_active: Optional[bool] = None,
    db: DBSession = Depends(get_db),
) -> TopicListResponse:
    """
    Listet alle Topics auf.

    Optional nach aktivem Status filterbar.
    """
    repo = TopicRepository(db)
    topics = repo.get_all(is_active=is_active)

    return TopicListResponse(
        topics=[
            TopicResponse(
                id=t.id,
                name=t.name,
                description=t.description or "",
                feed_url=t.feed_url,
                feed_type=t.feed_type.value if t.feed_type else "rss",
                is_active=t.is_active,
                fetch_interval_minutes=t.fetch_interval_minutes,
                last_fetched_at=t.last_fetched_at,
                last_fetch_error=t.last_fetch_error,
                total_items_fetched=t.total_items_fetched,
                items_kept=t.items_kept,
                items_dropped=t.items_dropped,
                created_at=t.created_at,
                updated_at=t.updated_at,
            )
            for t in topics
        ],
        total=len(topics),
    )


@router.get("/{topic_id}", response_model=TopicResponse)
async def get_topic(
    topic_id: str,
    db: DBSession = Depends(get_db),
) -> TopicResponse:
    """
    Ruft ein Topic nach ID ab.
    """
    repo = TopicRepository(db)
    topic = repo.get_by_id(topic_id)

    if not topic:
        raise HTTPException(status_code=404, detail="Topic nicht gefunden")

    return TopicResponse(
        id=topic.id,
        name=topic.name,
        description=topic.description or "",
        feed_url=topic.feed_url,
        feed_type=topic.feed_type.value if topic.feed_type else "rss",
        is_active=topic.is_active,
        fetch_interval_minutes=topic.fetch_interval_minutes,
        last_fetched_at=topic.last_fetched_at,
        last_fetch_error=topic.last_fetch_error,
        total_items_fetched=topic.total_items_fetched,
        items_kept=topic.items_kept,
        items_dropped=topic.items_dropped,
        created_at=topic.created_at,
        updated_at=topic.updated_at,
    )


@router.put("/{topic_id}", response_model=TopicResponse)
async def update_topic(
    topic_id: str,
    updates: TopicUpdate,
    db: DBSession = Depends(get_db),
) -> TopicResponse:
    """
    Aktualisiert ein Topic.
    """
    repo = TopicRepository(db)

    # Nur übergebene Werte updaten
    update_dict = {k: v for k, v in updates.model_dump().items() if v is not None}

    if not update_dict:
        raise HTTPException(status_code=400, detail="Keine Updates angegeben")

    updated = repo.update(topic_id, **update_dict)

    if not updated:
        raise HTTPException(status_code=404, detail="Topic nicht gefunden")

    return TopicResponse(
        id=updated.id,
        name=updated.name,
        description=updated.description or "",
        feed_url=updated.feed_url,
        feed_type=updated.feed_type.value if updated.feed_type else "rss",
        is_active=updated.is_active,
        fetch_interval_minutes=updated.fetch_interval_minutes,
        last_fetched_at=updated.last_fetched_at,
        last_fetch_error=updated.last_fetch_error,
        total_items_fetched=updated.total_items_fetched,
        items_kept=updated.items_kept,
        items_dropped=updated.items_dropped,
        created_at=updated.created_at,
        updated_at=updated.updated_at,
    )


@router.delete("/{topic_id}", status_code=204)
async def delete_topic(
    topic_id: str,
    db: DBSession = Depends(get_db),
):
    """
    Löscht ein Topic und alle zugehörigen Alerts (CASCADE).
    """
    repo = TopicRepository(db)

    success = repo.delete(topic_id)

    if not success:
        raise HTTPException(status_code=404, detail="Topic nicht gefunden")

    return None


@router.get("/{topic_id}/stats", response_model=TopicStatsResponse)
async def get_topic_stats(
    topic_id: str,
    db: DBSession = Depends(get_db),
) -> TopicStatsResponse:
    """
    Ruft Statistiken für ein Topic ab.
    """
    topic_repo = TopicRepository(db)
    alert_repo = AlertItemRepository(db)

    topic = topic_repo.get_by_id(topic_id)
    if not topic:
        raise HTTPException(status_code=404, detail="Topic nicht gefunden")

    by_status = alert_repo.count_by_status(topic_id)
    by_decision = alert_repo.count_by_decision(topic_id)

    total = sum(by_status.values())
    keep_count = by_decision.get("KEEP", 0)

    return TopicStatsResponse(
        topic_id=topic_id,
        name=topic.name,
        total_alerts=total,
        by_status=by_status,
        by_decision=by_decision,
        keep_rate=keep_count / total if total > 0 else None,
    )


@router.post("/{topic_id}/fetch", response_model=FetchResultResponse)
async def fetch_topic(
    topic_id: str,
    background_tasks: BackgroundTasks,
    db: DBSession = Depends(get_db),
) -> FetchResultResponse:
    """
    Löst einen manuellen Fetch für ein Topic aus.

    Der Fetch wird im Hintergrund ausgeführt. Das Ergebnis zeigt
    die Anzahl neuer Items und übersprungener Duplikate.
    """
    topic_repo = TopicRepository(db)

    topic = topic_repo.get_by_id(topic_id)
    if not topic:
        raise HTTPException(status_code=404, detail="Topic nicht gefunden")

    if not topic.feed_url:
        raise HTTPException(
            status_code=400,
            detail="Topic hat keine Feed-URL konfiguriert"
        )

    # Import hier um zirkuläre Imports zu vermeiden
    from alerts_agent.ingestion.rss_fetcher import fetch_and_store_feed

    try:
        result = await fetch_and_store_feed(
            topic_id=topic_id,
            feed_url=topic.feed_url,
            db=db,
        )

        return FetchResultResponse(
            success=True,
            topic_id=topic_id,
            new_items=result.get("new_items", 0),
            duplicates_skipped=result.get("duplicates_skipped", 0),
        )
    except Exception as e:
        # Fehler im Topic speichern
        topic_repo.update(topic_id, last_fetch_error=str(e))

        return FetchResultResponse(
            success=False,
            topic_id=topic_id,
            new_items=0,
            duplicates_skipped=0,
            error=str(e),
        )


@router.post("/{topic_id}/activate", response_model=TopicResponse)
async def activate_topic(
    topic_id: str,
    db: DBSession = Depends(get_db),
) -> TopicResponse:
    """
    Aktiviert ein Topic für automatisches Fetching.
    """
    repo = TopicRepository(db)
    updated = repo.update(topic_id, is_active=True)

    if not updated:
        raise HTTPException(status_code=404, detail="Topic nicht gefunden")

    return TopicResponse(
        id=updated.id,
        name=updated.name,
        description=updated.description or "",
        feed_url=updated.feed_url,
        feed_type=updated.feed_type.value if updated.feed_type else "rss",
        is_active=updated.is_active,
        fetch_interval_minutes=updated.fetch_interval_minutes,
        last_fetched_at=updated.last_fetched_at,
        last_fetch_error=updated.last_fetch_error,
        total_items_fetched=updated.total_items_fetched,
        items_kept=updated.items_kept,
        items_dropped=updated.items_dropped,
        created_at=updated.created_at,
        updated_at=updated.updated_at,
    )


@router.post("/{topic_id}/deactivate", response_model=TopicResponse)
async def deactivate_topic(
    topic_id: str,
    db: DBSession = Depends(get_db),
) -> TopicResponse:
    """
    Deaktiviert ein Topic (stoppt automatisches Fetching).
    """
    repo = TopicRepository(db)
    updated = repo.update(topic_id, is_active=False)

    if not updated:
        raise HTTPException(status_code=404, detail="Topic nicht gefunden")

    return TopicResponse(
        id=updated.id,
        name=updated.name,
        description=updated.description or "",
        feed_url=updated.feed_url,
        feed_type=updated.feed_type.value if updated.feed_type else "rss",
        is_active=updated.is_active,
        fetch_interval_minutes=updated.fetch_interval_minutes,
        last_fetched_at=updated.last_fetched_at,
        last_fetch_error=updated.last_fetch_error,
        total_items_fetched=updated.total_items_fetched,
        items_kept=updated.items_kept,
        items_dropped=updated.items_dropped,
        created_at=updated.created_at,
        updated_at=updated.updated_at,
    )
