"""
Repository für Alert Rules (Filterregeln).
"""
import uuid
from datetime import datetime
from typing import Optional, List, Dict, Any
from sqlalchemy.orm import Session as DBSession
from sqlalchemy import or_

from .models import AlertRuleDB, RuleActionEnum


class RuleRepository:
    """Repository für Alert Rules (Filterregeln)."""

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

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

    def create(
        self,
        name: str,
        conditions: List[Dict],
        action_type: str = "keep",
        action_config: Dict = None,
        topic_id: str = None,
        user_id: str = None,
        description: str = "",
        priority: int = 0,
    ) -> AlertRuleDB:
        """Erstellt eine neue Regel."""
        rule = AlertRuleDB(
            id=str(uuid.uuid4()),
            topic_id=topic_id,
            user_id=user_id,
            name=name,
            description=description,
            conditions=conditions,
            action_type=RuleActionEnum(action_type),
            action_config=action_config or {},
            priority=priority,
        )
        self.db.add(rule)
        self.db.commit()
        self.db.refresh(rule)
        return rule

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

    def get_by_id(self, rule_id: str) -> Optional[AlertRuleDB]:
        """Holt eine Regel nach ID."""
        return self.db.query(AlertRuleDB).filter(
            AlertRuleDB.id == rule_id
        ).first()

    def get_active(
        self,
        topic_id: str = None,
        user_id: str = None,
    ) -> List[AlertRuleDB]:
        """Holt alle aktiven Regeln, sortiert nach Priorität."""
        query = self.db.query(AlertRuleDB).filter(
            AlertRuleDB.is_active == True
        )

        if topic_id:
            # Topic-spezifische und globale Regeln
            query = query.filter(
                or_(
                    AlertRuleDB.topic_id == topic_id,
                    AlertRuleDB.topic_id.is_(None)
                )
            )

        if user_id:
            query = query.filter(
                or_(
                    AlertRuleDB.user_id == user_id,
                    AlertRuleDB.user_id.is_(None)
                )
            )

        return query.order_by(AlertRuleDB.priority.desc()).all()

    def get_all(
        self,
        user_id: str = None,
        topic_id: str = None,
        is_active: bool = None,
    ) -> List[AlertRuleDB]:
        """Holt alle Regeln mit optionalen Filtern."""
        query = self.db.query(AlertRuleDB)

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

        return query.order_by(AlertRuleDB.priority.desc()).all()

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

    def update(
        self,
        rule_id: str,
        name: str = None,
        description: str = None,
        conditions: List[Dict] = None,
        action_type: str = None,
        action_config: Dict = None,
        priority: int = None,
        is_active: bool = None,
    ) -> Optional[AlertRuleDB]:
        """Aktualisiert eine Regel."""
        rule = self.get_by_id(rule_id)
        if not rule:
            return None

        if name is not None:
            rule.name = name
        if description is not None:
            rule.description = description
        if conditions is not None:
            rule.conditions = conditions
        if action_type is not None:
            rule.action_type = RuleActionEnum(action_type)
        if action_config is not None:
            rule.action_config = action_config
        if priority is not None:
            rule.priority = priority
        if is_active is not None:
            rule.is_active = is_active

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

    def increment_match_count(self, rule_id: str) -> Optional[AlertRuleDB]:
        """Erhöht den Match-Counter einer Regel."""
        rule = self.get_by_id(rule_id)
        if not rule:
            return None

        rule.match_count += 1
        rule.last_matched_at = datetime.utcnow()

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

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

    def delete(self, rule_id: str) -> bool:
        """Löscht eine Regel."""
        rule = self.get_by_id(rule_id)
        if not rule:
            return False

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

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

    def to_dict(self, rule: AlertRuleDB) -> Dict[str, Any]:
        """Konvertiert DB-Model zu Dictionary."""
        return {
            "id": rule.id,
            "topic_id": rule.topic_id,
            "user_id": rule.user_id,
            "name": rule.name,
            "description": rule.description,
            "conditions": rule.conditions,
            "action_type": rule.action_type.value,
            "action_config": rule.action_config,
            "priority": rule.priority,
            "is_active": rule.is_active,
            "stats": {
                "match_count": rule.match_count,
                "last_matched_at": rule.last_matched_at.isoformat() if rule.last_matched_at else None,
            },
            "created_at": rule.created_at.isoformat() if rule.created_at else None,
            "updated_at": rule.updated_at.isoformat() if rule.updated_at else None,
        }
