"""Service-Schicht fuer Kontakt-Operationen."""

from sqlalchemy import and_, func, or_
from sqlalchemy.orm import Session, joinedload

from models.kontakt import Kontakt
from models.tag import KontaktTag
from models.gruppe import KontaktGruppe
from models.kampagne import KampagneKontakt
import search


def liste(db: Session, typ: str = None, seite: int = 1, pro_seite: int = 25,
          sortierung: str = "nachname", gruppe_id: int = None, tag_id: int = None,
          buchstabe: str = None, inkl_blacklist: bool = False,
          freitext: str = None, ort: str = None, email: str = None,
          plz: str = None, betreuer: str = None, eigentuemer: str = None,
          position: str = None, org_name: str = None):
    """Kontakte auflisten mit Filtern."""
    query = db.query(Kontakt)

    if not inkl_blacklist:
        query = query.filter(Kontakt.ist_blacklisted == False)

    if typ:
        query = query.filter(Kontakt.typ == typ)

    if gruppe_id:
        query = query.join(KontaktGruppe).filter(KontaktGruppe.gruppe_id == gruppe_id)

    if tag_id:
        query = query.join(KontaktTag).filter(KontaktTag.tag_id == tag_id)

    if buchstabe:
        if typ == "organisation":
            query = query.filter(Kontakt.firmenname.ilike(f"{buchstabe}%"))
        else:
            query = query.filter(Kontakt.nachname.ilike(f"{buchstabe}%"))

    if freitext:
        like = f"%{freitext}%"
        query = query.filter(or_(
            Kontakt.firmenname.ilike(like),
            Kontakt.nachname.ilike(like),
            Kontakt.vorname.ilike(like),
            Kontakt.email1.ilike(like),
        ))

    if ort:
        query = query.filter(Kontakt.ort.ilike(f"%{ort}%"))

    if email:
        query = query.filter(Kontakt.email1.ilike(f"%{email}%"))

    if plz:
        query = query.filter(Kontakt.plz.ilike(f"%{plz}%"))

    if betreuer:
        query = query.filter(Kontakt.betreuer.ilike(f"%{betreuer}%"))

    if eigentuemer:
        query = query.filter(Kontakt.eigentuemer.ilike(f"%{eigentuemer}%"))

    if position:
        query = query.filter(Kontakt.position.ilike(f"%{position}%"))

    if org_name:
        query = query.filter(Kontakt.firmenname.ilike(f"%{org_name}%"))

    if sortierung == "firmenname":
        query = query.order_by(Kontakt.firmenname)
    elif sortierung == "ort":
        query = query.order_by(Kontakt.ort, Kontakt.nachname)
    elif sortierung == "aktualisiert":
        query = query.order_by(Kontakt.aktualisiert_am.desc())
    else:
        query = query.order_by(Kontakt.nachname, Kontakt.vorname)

    gesamt = query.count()
    kontakte = query.offset((seite - 1) * pro_seite).limit(pro_seite).all()
    seiten = (gesamt + pro_seite - 1) // pro_seite

    return {
        "kontakte": kontakte,
        "gesamt": gesamt,
        "seite": seite,
        "seiten": seiten,
        "pro_seite": pro_seite,
    }


def detail(db: Session, kontakt_id: int):
    """Einzelnen Kontakt mit allen Beziehungen laden."""
    return db.query(Kontakt).options(
        joinedload(Kontakt.tags).joinedload(KontaktTag.tag),
        joinedload(Kontakt.gruppen).joinedload(KontaktGruppe.gruppe),
        joinedload(Kontakt.aktivitaeten),
        joinedload(Kontakt.spenden),
        joinedload(Kontakt.kampagnen).joinedload(KampagneKontakt.kampagne),
    ).filter(Kontakt.id == kontakt_id).first()


def erstellen(db: Session, daten: dict, erstellt_von: str = None) -> Kontakt:
    """Neuen Kontakt anlegen."""
    kontakt = Kontakt(**daten)
    if erstellt_von:
        kontakt.erfasst_von = erstellt_von
        kontakt.aktualisiert_von = erstellt_von
    db.add(kontakt)
    db.flush()
    search.index_kontakt(db, kontakt)
    db.commit()
    db.refresh(kontakt)
    return kontakt


def aktualisieren(db: Session, kontakt_id: int, daten: dict, aktualisiert_von: str = None) -> Kontakt:
    """Kontakt aktualisieren."""
    kontakt = db.query(Kontakt).filter(Kontakt.id == kontakt_id).first()
    if not kontakt:
        return None
    for key, value in daten.items():
        if hasattr(kontakt, key):
            setattr(kontakt, key, value)
    if aktualisiert_von:
        kontakt.aktualisiert_von = aktualisiert_von
    db.flush()
    search.index_kontakt(db, kontakt)
    db.commit()
    db.refresh(kontakt)
    return kontakt


def loeschen(db: Session, kontakt_id: int) -> bool:
    """Kontakt loeschen."""
    kontakt = db.query(Kontakt).filter(Kontakt.id == kontakt_id).first()
    if not kontakt:
        return False
    search._remove_from_index(db, "kontakt", kontakt_id)
    db.delete(kontakt)
    db.commit()
    return True


def tag_toggle(db: Session, kontakt_id: int, tag_id: int) -> bool:
    """Tag an/aus schalten. Gibt True zurueck wenn Tag jetzt gesetzt."""
    existing = db.query(KontaktTag).filter(
        KontaktTag.kontakt_id == kontakt_id,
        KontaktTag.tag_id == tag_id,
    ).first()

    if existing:
        db.delete(existing)
        db.commit()
        return False
    else:
        db.add(KontaktTag(kontakt_id=kontakt_id, tag_id=tag_id))
        db.commit()
        return True


def statistik(db: Session):
    """Kontakt-Statistiken fuers Dashboard."""
    return {
        "personen": db.query(Kontakt).filter(Kontakt.typ == "person", Kontakt.ist_blacklisted == False).count(),
        "organisationen": db.query(Kontakt).filter(Kontakt.typ == "organisation", Kontakt.ist_blacklisted == False).count(),
        "gesamt": db.query(Kontakt).filter(Kontakt.ist_blacklisted == False).count(),
    }


def blacklist_check(db: Session, daten: dict) -> list[Kontakt]:
    """Prueft ob Name/Firma/cobra_id auf der Blacklist steht."""
    bedingungen = []
    if daten.get("cobra_id"):
        bedingungen.append(Kontakt.cobra_id == daten["cobra_id"])
    if daten.get("nachname") and daten.get("vorname"):
        bedingungen.append(and_(Kontakt.nachname.ilike(daten["nachname"]), Kontakt.vorname.ilike(daten["vorname"])))
    elif daten.get("nachname"):
        bedingungen.append(Kontakt.nachname.ilike(daten["nachname"]))
    if daten.get("firmenname"):
        bedingungen.append(Kontakt.firmenname.ilike(daten["firmenname"]))
    if not bedingungen:
        return []
    return db.query(Kontakt).filter(Kontakt.ist_blacklisted == True, or_(*bedingungen)).all()


def blacklist_liste(db: Session):
    """Alle blacklisted Kontakte auflisten."""
    return db.query(Kontakt).filter(Kontakt.ist_blacklisted == True).order_by(Kontakt.nachname, Kontakt.firmenname).all()
