"""FTS5 Suchindex-Management fuer KontaktWerk."""

import re

from sqlalchemy import text
from sqlalchemy.orm import Session


def sanitize_fts_query(query: str) -> str:
    """Bereinigt eine Suchanfrage fuer FTS5."""
    query = query.strip()
    if not query:
        return ""
    # Sonderzeichen entfernen die FTS5 stoeren
    query = re.sub(r'[^\w\s@.\-äöüÄÖÜß]', '', query)
    # Terme extrahieren und mit * und AND verbinden
    terms = query.split()
    if not terms:
        return ""
    fts_terms = [f'"{t}"*' for t in terms if len(t) >= 1]
    return " AND ".join(fts_terms)


def search(db: Session, query: str, limit: int = 25, entity_type: str = None):
    """Volltextsuche ueber den FTS5 Index."""
    fts_query = sanitize_fts_query(query)
    if not fts_query:
        return []

    type_filter = ""
    params = {"query": fts_query, "limit": limit}
    if entity_type:
        type_filter = "AND entity_type = :entity_type"
        params["entity_type"] = entity_type

    sql = text(f"""
        SELECT entity_type, entity_id, titel, untertitel, inhalt, tags,
               rank
        FROM search_index
        WHERE search_index MATCH :query
        {type_filter}
        ORDER BY rank
        LIMIT :limit
    """)

    result = db.execute(sql, params)
    return [
        {
            "entity_type": row[0],
            "entity_id": int(row[1]),
            "titel": row[2],
            "untertitel": row[3],
            "inhalt": row[4],
            "tags": row[5],
            "rank": row[6],
        }
        for row in result
    ]


def index_kontakt(db: Session, kontakt):
    """Kontakt in den Suchindex aufnehmen/aktualisieren."""
    _remove_from_index(db, "kontakt", kontakt.id)

    if kontakt.typ == "organisation":
        titel = kontakt.firmenname or ""
        untertitel = kontakt.firmenname2 or ""
    else:
        titel = kontakt.anzeigename
        untertitel = " ".join(filter(None, [kontakt.position, kontakt.firmenname]))

    inhalt_parts = [
        kontakt.strasse, kontakt.plz, kontakt.ort,
        kontakt.email1, kontakt.email2,
        kontakt.telefon, kontakt.mobil,
        kontakt.bemerkung,
    ]
    inhalt = " ".join(filter(None, inhalt_parts))

    tag_namen = [kt.tag.name for kt in kontakt.tags] if kontakt.tags else []
    tags = " ".join(tag_namen)

    _insert_index(db, "kontakt", kontakt.id, titel, untertitel, inhalt, tags)


def index_aktivitaet(db: Session, aktivitaet):
    """Aktivitaet in den Suchindex aufnehmen."""
    _remove_from_index(db, "aktivitaet", aktivitaet.id)
    inhalt_parts = [aktivitaet.bemerkung, aktivitaet.projekt]
    inhalt = " ".join(filter(None, inhalt_parts))
    kontakt_name = aktivitaet.kontakt.anzeigename if aktivitaet.kontakt else ""
    _insert_index(
        db, "aktivitaet", aktivitaet.id,
        aktivitaet.betreff or "",
        kontakt_name,
        inhalt, ""
    )


def index_veranstaltung(db: Session, veranstaltung):
    """Veranstaltung in den Suchindex aufnehmen."""
    _remove_from_index(db, "veranstaltung", veranstaltung.id)
    inhalt_parts = [veranstaltung.beschreibung, veranstaltung.ort, veranstaltung.projekt]
    _insert_index(
        db, "veranstaltung", veranstaltung.id,
        veranstaltung.titel,
        veranstaltung.typ or "",
        " ".join(filter(None, inhalt_parts)), ""
    )


def index_kampagne(db: Session, kampagne):
    """Kampagne in den Suchindex aufnehmen."""
    _remove_from_index(db, "kampagne", kampagne.id)
    inhalt_parts = [kampagne.beschreibung, kampagne.projekt]
    _insert_index(
        db, "kampagne", kampagne.id,
        kampagne.titel,
        kampagne.typ or "",
        " ".join(filter(None, inhalt_parts)), ""
    )


def rebuild_index(db: Session):
    """Kompletten Suchindex neu aufbauen."""
    from models.kontakt import Kontakt
    from models.aktivitaet import Aktivitaet
    from models.veranstaltung import Veranstaltung
    from models.kampagne import Kampagne

    db.execute(text("DELETE FROM search_index"))

    for kontakt in db.query(Kontakt).all():
        index_kontakt(db, kontakt)

    for akt in db.query(Aktivitaet).all():
        index_aktivitaet(db, akt)

    for va in db.query(Veranstaltung).all():
        index_veranstaltung(db, va)

    for ka in db.query(Kampagne).all():
        index_kampagne(db, ka)

    db.commit()


def _insert_index(db: Session, entity_type: str, entity_id: int,
                  titel: str, untertitel: str, inhalt: str, tags: str):
    db.execute(text("""
        INSERT INTO search_index(entity_type, entity_id, titel, untertitel, inhalt, tags)
        VALUES(:entity_type, :entity_id, :titel, :untertitel, :inhalt, :tags)
    """), {
        "entity_type": entity_type,
        "entity_id": str(entity_id),
        "titel": titel,
        "untertitel": untertitel,
        "inhalt": inhalt,
        "tags": tags,
    })


def _remove_from_index(db: Session, entity_type: str, entity_id: int):
    db.execute(text("""
        DELETE FROM search_index
        WHERE entity_type = :entity_type AND entity_id = :entity_id
    """), {"entity_type": entity_type, "entity_id": str(entity_id)})
