"""
Repository für Alert Topics (Feed-Quellen).
"""
import uuid
from datetime import datetime
from typing import Optional, List, Dict, Any
from sqlalchemy.orm import Session as DBSession

from .models import AlertTopicDB, FeedTypeEnum


class TopicRepository:
    """Repository für Alert Topics (Feed-Quellen)."""

    def __init__(self, db: DBSession):
        self.db = db

    # ==================== CREATE ====================

    def create(
        self,
        name: str,
        feed_url: str = None,
        feed_type: str = "rss",
        user_id: str = None,
        description: str = "",
        fetch_interval_minutes: int = 60,
        is_active: bool = True,
    ) -> AlertTopicDB:
        """Erstellt ein neues Topic."""
        topic = AlertTopicDB(
            id=str(uuid.uuid4()),
            user_id=user_id,
            name=name,
            description=description,
            feed_url=feed_url,
            feed_type=FeedTypeEnum(feed_type),
            fetch_interval_minutes=fetch_interval_minutes,
            is_active=is_active,
        )
        self.db.add(topic)
        self.db.commit()
        self.db.refresh(topic)
        return topic

    # ==================== READ ====================

    def get_by_id(self, topic_id: str) -> Optional[AlertTopicDB]:
        """Holt ein Topic nach ID."""
        return self.db.query(AlertTopicDB).filter(
            AlertTopicDB.id == topic_id
        ).first()

    def get_all(
        self,
        user_id: str = None,
        is_active: bool = None,
        limit: int = 100,
        offset: int = 0,
    ) -> List[AlertTopicDB]:
        """Holt alle Topics mit optionalen Filtern."""
        query = self.db.query(AlertTopicDB)

        if user_id:
            query = query.filter(AlertTopicDB.user_id == user_id)
        if is_active is not None:
            query = query.filter(AlertTopicDB.is_active == is_active)

        return query.order_by(
            AlertTopicDB.created_at.desc()
        ).offset(offset).limit(limit).all()

    def get_active_for_fetch(self) -> List[AlertTopicDB]:
        """Holt alle aktiven Topics die gefetcht werden sollten."""
        return self.db.query(AlertTopicDB).filter(
            AlertTopicDB.is_active == True,
            AlertTopicDB.feed_url.isnot(None),
        ).all()

    # ==================== UPDATE ====================

    def update(
        self,
        topic_id: str,
        name: str = None,
        description: str = None,
        feed_url: str = None,
        feed_type: str = None,
        is_active: bool = None,
        fetch_interval_minutes: int = None,
    ) -> Optional[AlertTopicDB]:
        """Aktualisiert ein Topic."""
        topic = self.get_by_id(topic_id)
        if not topic:
            return None

        if name is not None:
            topic.name = name
        if description is not None:
            topic.description = description
        if feed_url is not None:
            topic.feed_url = feed_url
        if feed_type is not None:
            topic.feed_type = FeedTypeEnum(feed_type)
        if is_active is not None:
            topic.is_active = is_active
        if fetch_interval_minutes is not None:
            topic.fetch_interval_minutes = fetch_interval_minutes

        self.db.commit()
        self.db.refresh(topic)
        return topic

    def update_fetch_status(
        self,
        topic_id: str,
        last_fetch_error: str = None,
        items_fetched: int = 0,
    ) -> Optional[AlertTopicDB]:
        """Aktualisiert den Fetch-Status eines Topics."""
        topic = self.get_by_id(topic_id)
        if not topic:
            return None

        topic.last_fetched_at = datetime.utcnow()
        topic.last_fetch_error = last_fetch_error
        topic.total_items_fetched += items_fetched

        self.db.commit()
        self.db.refresh(topic)
        return topic

    def increment_stats(
        self,
        topic_id: str,
        kept: int = 0,
        dropped: int = 0,
    ) -> Optional[AlertTopicDB]:
        """Erhöht die Statistiken eines Topics."""
        topic = self.get_by_id(topic_id)
        if not topic:
            return None

        topic.items_kept += kept
        topic.items_dropped += dropped

        self.db.commit()
        self.db.refresh(topic)
        return topic

    # ==================== DELETE ====================

    def delete(self, topic_id: str) -> bool:
        """Löscht ein Topic (und alle zugehörigen Items via CASCADE)."""
        topic = self.get_by_id(topic_id)
        if not topic:
            return False

        self.db.delete(topic)
        self.db.commit()
        return True

    # ==================== CONVERSION ====================

    def to_dict(self, topic: AlertTopicDB) -> Dict[str, Any]:
        """Konvertiert DB-Model zu Dictionary."""
        return {
            "id": topic.id,
            "user_id": topic.user_id,
            "name": topic.name,
            "description": topic.description,
            "feed_url": topic.feed_url,
            "feed_type": topic.feed_type.value,
            "is_active": topic.is_active,
            "fetch_interval_minutes": topic.fetch_interval_minutes,
            "last_fetched_at": topic.last_fetched_at.isoformat() if topic.last_fetched_at else None,
            "last_fetch_error": topic.last_fetch_error,
            "stats": {
                "total_items_fetched": topic.total_items_fetched,
                "items_kept": topic.items_kept,
                "items_dropped": topic.items_dropped,
            },
            "created_at": topic.created_at.isoformat() if topic.created_at else None,
            "updated_at": topic.updated_at.isoformat() if topic.updated_at else None,
        }
