from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session import logging from app.database import get_db from app.models.db_models import Account, FilterAction, FilterCondition, FilterRule, ProcessedMail from app.schemas.schemas import FilterRuleCreate, FilterRuleResponse, FilterRuleUpdate logger = logging.getLogger(__name__) def _reset_processed_for_folder(db: Session, account_id: int, folder: str) -> int: """Reset processed mails for a specific account/folder so they get re-evaluated.""" count = ( db.query(ProcessedMail) .filter(ProcessedMail.account_id == account_id, ProcessedMail.folder == folder) .delete() ) if count: logger.info("Filter geändert: %d verarbeitete Mails in '%s' zurückgesetzt (Account %d)", count, folder, account_id) return count router = APIRouter(prefix="/api/filters", tags=["filters"]) @router.get("/account/{account_id}", response_model=list[FilterRuleResponse]) def list_filters(account_id: int, db: Session = Depends(get_db)): account = db.get(Account, account_id) if not account: raise HTTPException(404, "Konto nicht gefunden") rules = ( db.query(FilterRule) .filter(FilterRule.account_id == account_id) .order_by(FilterRule.priority) .all() ) return rules @router.get("/{rule_id}", response_model=FilterRuleResponse) def get_filter(rule_id: int, db: Session = Depends(get_db)): rule = db.get(FilterRule, rule_id) if not rule: raise HTTPException(404, "Filterregel nicht gefunden") return rule @router.post("/", response_model=FilterRuleResponse, status_code=201) def create_filter(data: FilterRuleCreate, db: Session = Depends(get_db)): account = db.get(Account, data.account_id) if not account: raise HTTPException(404, "Konto nicht gefunden") rule = FilterRule( account_id=data.account_id, name=data.name, priority=data.priority, enabled=data.enabled, stop_processing=data.stop_processing, source_folder=data.source_folder, ) db.add(rule) db.flush() for cond_data in data.conditions: cond = FilterCondition(rule_id=rule.id, **cond_data.model_dump()) db.add(cond) for action_data in data.actions: action = FilterAction(rule_id=rule.id, **action_data.model_dump()) db.add(action) # Neue Regel → Ordner zurücksetzen damit bestehende Mails geprüft werden _reset_processed_for_folder(db, data.account_id, data.source_folder) db.commit() db.refresh(rule) return rule @router.put("/{rule_id}", response_model=FilterRuleResponse) def update_filter(rule_id: int, data: FilterRuleUpdate, db: Session = Depends(get_db)): rule = db.get(FilterRule, rule_id) if not rule: raise HTTPException(404, "Filterregel nicht gefunden") old_folder = rule.source_folder update_data = data.model_dump(exclude_unset=True) # Update conditions if provided if "conditions" in update_data: for cond in rule.conditions: db.delete(cond) for cond_data in data.conditions: cond = FilterCondition(rule_id=rule.id, **cond_data.model_dump()) db.add(cond) del update_data["conditions"] # Update actions if provided if "actions" in update_data: for action in rule.actions: db.delete(action) for action_data in data.actions: action = FilterAction(rule_id=rule.id, **action_data.model_dump()) db.add(action) del update_data["actions"] for key, value in update_data.items(): setattr(rule, key, value) # Regel geändert → betroffene Ordner zurücksetzen _reset_processed_for_folder(db, rule.account_id, old_folder) new_folder = rule.source_folder if new_folder != old_folder: _reset_processed_for_folder(db, rule.account_id, new_folder) db.commit() db.refresh(rule) return rule @router.delete("/{rule_id}", status_code=204) def delete_filter(rule_id: int, db: Session = Depends(get_db)): rule = db.get(FilterRule, rule_id) if not rule: raise HTTPException(404, "Filterregel nicht gefunden") # Ordner zurücksetzen — andere Regeln könnten jetzt anders greifen _reset_processed_for_folder(db, rule.account_id, rule.source_folder) db.delete(rule) db.commit() @router.put("/reorder/{account_id}") def reorder_filters(account_id: int, rule_ids: list[int], db: Session = Depends(get_db)): for priority, rule_id in enumerate(rule_ids): rule = db.get(FilterRule, rule_id) if rule and rule.account_id == account_id: rule.priority = priority db.commit() return {"message": "Reihenfolge aktualisiert"}