"""KontaktWerk CRM - Hauptanwendung."""

import logging
from contextlib import asynccontextmanager
from pathlib import Path

from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

from config import APP_NAME, APP_VERSION, GRUPPEN_SEED, LOG_DIR
from database import init_db, SessionLocal
from models.benutzer import Benutzer
from models.gruppe import Gruppe
from models.kategorie_option import KategorieOption

# Logging konfigurieren
LOG_DIR.mkdir(parents=True, exist_ok=True)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
    handlers=[
        logging.FileHandler(LOG_DIR / "kontaktwerk.log", encoding="utf-8"),
        logging.StreamHandler(),
    ],
)
logger = logging.getLogger("kontaktwerk")


KATEGORIE_SEED = [
    # aktivitaet_art
    ("aktivitaet_art", "email_aus", "E-Mail ausgehend", "\U0001f4e4", None, 0),
    ("aktivitaet_art", "email_ein", "E-Mail eingehend", "\U0001f4e5", None, 1),
    ("aktivitaet_art", "telefon", "Telefonat", "\U0001f4de", None, 2),
    ("aktivitaet_art", "persoenlich", "Persönliches Gespräch", "\U0001f91d", None, 3),
    ("aktivitaet_art", "serienbrief", "Serienbrief", "\U0001f4e8", None, 4),
    ("aktivitaet_art", "schriftverkehr", "Schriftverkehr", "\u2709\ufe0f", None, 5),
    ("aktivitaet_art", "aufgabe", "Aufgabe", "\u2705", None, 6),
    ("aktivitaet_art", "bewerbung", "Bewerbung", "\U0001f4cb", None, 7),
    ("aktivitaet_art", "brief_ein", "Brief eingehend", "\U0001f4ec", None, 8),
    ("aktivitaet_art", "fax_aus", "Fax ausgehend", "\U0001f4e0", None, 9),
    ("aktivitaet_art", "notiz", "Notiz", "\U0001f4dd", None, 10),
    ("aktivitaet_art", "sonstiges", "Sonstiges", "\U0001f4cc", None, 11),
    # aktivitaet_status
    ("aktivitaet_status", "information", "Information", None, "#2196F3", 0),
    ("aktivitaet_status", "offen", "Offen", None, "#dd6b20", 1),
    ("aktivitaet_status", "erledigt", "Erledigt", None, "#9E9E9E", 2),
    # kampagne_typ
    ("kampagne_typ", "mailing", "Mailing", None, None, 0),
    ("kampagne_typ", "telefonaktion", "Telefonaktion", None, None, 1),
    ("kampagne_typ", "einladung", "Einladung", None, None, 2),
    ("kampagne_typ", "sonstiges", "Sonstiges", None, None, 3),
    # kampagne_status
    ("kampagne_status", "entwurf", "Entwurf", None, "#2196F3", 0),
    ("kampagne_status", "aktiv", "Aktiv", None, "#4CAF50", 1),
    ("kampagne_status", "abgeschlossen", "Abgeschlossen", None, "#9E9E9E", 2),
    # kampagne_kontakt_status
    ("kampagne_kontakt_status", "neu", "Neu", None, "#607D8B", 0),
    ("kampagne_kontakt_status", "kontaktiert", "Kontaktiert", None, "#2196F3", 1),
    ("kampagne_kontakt_status", "reagiert", "Reagiert", None, "#4CAF50", 2),
    ("kampagne_kontakt_status", "abgelehnt", "Abgelehnt", None, "#e53e3e", 3),
    ("kampagne_kontakt_status", "abgemeldet", "Abgemeldet", None, "#FF9800", 4),
    ("kampagne_kontakt_status", "erledigt", "Erledigt", None, "#9E9E9E", 5),
    # veranstaltung_typ
    ("veranstaltung_typ", "workshop", "Workshop", None, None, 0),
    ("veranstaltung_typ", "vortrag", "Vortrag", None, None, 1),
    ("veranstaltung_typ", "netzwerktreffen", "Netzwerktreffen", None, None, 2),
    ("veranstaltung_typ", "seminar", "Seminar", None, None, 3),
    ("veranstaltung_typ", "konferenz", "Konferenz", None, None, 4),
    ("veranstaltung_typ", "sonstiges", "Sonstiges", None, None, 5),
    # veranstaltung_status
    ("veranstaltung_status", "geplant", "Geplant", None, "#2196F3", 0),
    ("veranstaltung_status", "laufend", "Laufend", None, "#4CAF50", 1),
    ("veranstaltung_status", "abgeschlossen", "Abgeschlossen", None, "#9E9E9E", 2),
    ("veranstaltung_status", "abgesagt", "Abgesagt", None, "#e53e3e", 3),
    # teilnehmer_rolle
    ("teilnehmer_rolle", "teilnehmer", "Teilnehmer", "\U0001f464", None, 0),
    ("teilnehmer_rolle", "referent", "Referent", "\U0001f3a4", None, 1),
    ("teilnehmer_rolle", "organisator", "Organisator", "\u2699\ufe0f", None, 2),
    # teilnehmer_status
    ("teilnehmer_status", "eingeladen", "Eingeladen", None, "#607D8B", 0),
    ("teilnehmer_status", "zugesagt", "Zugesagt", None, "#4CAF50", 1),
    ("teilnehmer_status", "abgelehnt", "Abgelehnt", None, "#e53e3e", 2),
    ("teilnehmer_status", "abgesagt", "Abgesagt", None, "#FF9800", 3),
    ("teilnehmer_status", "hat_teilgenommen", "Hat teilgenommen", None, "#1565C0", 4),
    ("teilnehmer_status", "nicht_erschienen", "Nicht erschienen", None, "#9E9E9E", 5),
    ("teilnehmer_status", "angemeldet", "Angemeldet", None, "#2196F3", 6),
    ("teilnehmer_status", "teilgenommen", "Teilgenommen", None, "#388E3C", 7),
    # beziehung_typ
    ("beziehung_typ", "mitarbeiter_von", "Mitarbeiter von", None, None, 0),
    ("beziehung_typ", "vorstand_von", "Vorstand von", None, None, 1),
    ("beziehung_typ", "mitglied_von", "Mitglied von", None, None, 2),
    ("beziehung_typ", "kennt", "Kennt", None, None, 3),
    ("beziehung_typ", "partner_von", "Partner von", None, None, 4),
    ("beziehung_typ", "sonstiges", "Sonstiges", None, None, 5),
    # kontakt_anrede
    ("kontakt_anrede", "Herr", "Herr", None, None, 0),
    ("kontakt_anrede", "Frau", "Frau", None, None, 1),
    # kontakt_titel
    ("kontakt_titel", "Dr.", "Dr.", None, None, 0),
    ("kontakt_titel", "Prof.", "Prof.", None, None, 1),
    ("kontakt_titel", "Prof. Dr.", "Prof. Dr.", None, None, 2),
    ("kontakt_titel", "Dipl.-Ing.", "Dipl.-Ing.", None, None, 3),
    # spende_typ
    ("spende_typ", "einzelspende", "Einzelspende", None, None, 0),
    ("spende_typ", "dauerspende", "Dauerspende", None, None, 1),
    # spende_zahlungsart
    ("spende_zahlungsart", "ueberweisung", "Überweisung", None, None, 0),
    ("spende_zahlungsart", "bar", "Bar", None, None, 1),
    ("spende_zahlungsart", "lastschrift", "Lastschrift", None, None, 2),
    # spende_quittung
    ("spende_quittung", "keine", "Keine", None, None, 0),
    ("spende_quittung", "erstellt", "Erstellt", None, None, 1),
    ("spende_quittung", "versendet", "Versendet", None, None, 2),
    # app_einstellungen
    ("app_einstellungen", "app_name", "KontaktWerk", None, None, 0),
]


def refresh_model_dicts(db):
    """Aktualisiert die class-level Dicts der Models aus der DB."""
    from models.aktivitaet import Aktivitaet
    from models.kampagne import Kampagne, KampagneKontakt

    opts = db.query(KategorieOption).filter(
        KategorieOption.aktiv == True
    ).order_by(KategorieOption.position).all()

    by_gruppe = {}
    for o in opts:
        by_gruppe.setdefault(o.gruppe, []).append(o)

    if "aktivitaet_art" in by_gruppe:
        Aktivitaet.ART_LABELS = {o.wert: o.label for o in by_gruppe["aktivitaet_art"]}
        Aktivitaet.ART_ICONS = {o.wert: o.icon for o in by_gruppe["aktivitaet_art"] if o.icon}

    if "kampagne_typ" in by_gruppe:
        Kampagne.TYP_LABELS = {o.wert: o.label for o in by_gruppe["kampagne_typ"]}

    if "kampagne_status" in by_gruppe:
        Kampagne.STATUS_LABELS = {o.wert: o.label for o in by_gruppe["kampagne_status"]}

    if "kampagne_kontakt_status" in by_gruppe:
        KampagneKontakt.STATUS_LABELS = {o.wert: o.label for o in by_gruppe["kampagne_kontakt_status"]}


def seed_initial_data():
    """Erstellt Admin-Benutzer, Gruppen und Kategorie-Optionen beim ersten Start."""
    db = SessionLocal()
    try:
        # Admin-Benutzer anlegen falls keiner existiert
        if db.query(Benutzer).count() == 0:
            admin = Benutzer(
                kuerzel="ADMIN",
                name="Administrator",
                ist_aktiv=True,
                ist_admin=True,
            )
            admin.set_passwort("admin")
            db.add(admin)
            logger.info("Admin-Benutzer angelegt (Kuerzel: ADMIN, Passwort: admin)")

        # Gruppen seeden
        for g in GRUPPEN_SEED:
            existing = db.query(Gruppe).filter(Gruppe.kuerzel == g["kuerzel"]).first()
            if not existing:
                db.add(Gruppe(**g))

        # Kategorie-Optionen seeden
        for gruppe, wert, label, icon, farbe, position in KATEGORIE_SEED:
            existing = db.query(KategorieOption).filter(
                KategorieOption.gruppe == gruppe,
                KategorieOption.wert == wert,
            ).first()
            if not existing:
                db.add(KategorieOption(
                    gruppe=gruppe, wert=wert, label=label,
                    icon=icon, farbe=farbe, position=position,
                ))

        db.commit()

        # Model-Dicts aus DB aktualisieren
        refresh_model_dicts(db)
    finally:
        db.close()


@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    logger.info(f"{APP_NAME} v{APP_VERSION} startet...")
    init_db()
    seed_initial_data()
    logger.info(f"{APP_NAME} bereit: http://localhost:8000")
    yield
    # Shutdown
    logger.info(f"{APP_NAME} wird beendet.")


app = FastAPI(
    title=APP_NAME,
    version=APP_VERSION,
    lifespan=lifespan,
)

# Static Files
app.mount("/static", StaticFiles(directory=Path(__file__).parent / "static"), name="static")

# Auth Exception Handler
from dependencies import AuthRequired

@app.exception_handler(AuthRequired)
async def auth_redirect_handler(request: Request, exc: AuthRequired):
    return RedirectResponse(url="/login", status_code=303)

# --- Jinja2 Globals: kat_optionen() in allen Templates verfuegbar ---
from services.kategorie_service import get_optionen, get_optionen_dict, get_farben_dict, get_icons_dict

def _kat_optionen(gruppe: str):
    db = SessionLocal()
    try:
        return get_optionen(db, gruppe)
    finally:
        db.close()

def _kat_dict(gruppe: str):
    db = SessionLocal()
    try:
        return get_optionen_dict(db, gruppe)
    finally:
        db.close()

def _kat_farben(gruppe: str):
    db = SessionLocal()
    try:
        return get_farben_dict(db, gruppe)
    finally:
        db.close()

def _kat_icons(gruppe: str):
    db = SessionLocal()
    try:
        return get_icons_dict(db, gruppe)
    finally:
        db.close()

def _app_name():
    db = SessionLocal()
    try:
        opt = db.query(KategorieOption).filter(
            KategorieOption.gruppe == "app_einstellungen",
            KategorieOption.wert == "app_name",
        ).first()
        return opt.label if opt else "KontaktWerk"
    finally:
        db.close()

# Jinja2Templates patchen BEVOR Router importiert werden
_orig_jinja_init = Jinja2Templates.__init__
def _patched_jinja_init(self, *args, **kwargs):
    _orig_jinja_init(self, *args, **kwargs)
    self.env.globals["kat_optionen"] = _kat_optionen
    self.env.globals["kat_dict"] = _kat_dict
    self.env.globals["kat_farben"] = _kat_farben
    self.env.globals["kat_icons"] = _kat_icons
    self.env.globals["app_name"] = _app_name
Jinja2Templates.__init__ = _patched_jinja_init

# Router einbinden
from routers import auth, dashboard, kontakte, organisationen, aktivitaeten, suche, recherche, veranstaltungen, spenden, tags, dokumente, einstellungen, kampagnen, branchen, auswertungen, workflows, aufraemen, kategorien, gruppen

app.include_router(auth.router)
app.include_router(dashboard.router)
app.include_router(workflows.router)
app.include_router(aufraemen.router)
app.include_router(kontakte.router)
app.include_router(organisationen.router)
app.include_router(aktivitaeten.router)
app.include_router(suche.router)
app.include_router(recherche.router)
app.include_router(veranstaltungen.router)
app.include_router(spenden.router)
app.include_router(tags.router)
app.include_router(dokumente.router)
app.include_router(einstellungen.router)
app.include_router(kampagnen.router)
app.include_router(branchen.router)
app.include_router(kategorien.router)
app.include_router(gruppen.router)
app.include_router(auswertungen.router)
