"""Import-Service fuer Cobra-Daten (Excel-Dateien)."""

import logging
from datetime import datetime
from io import BytesIO

from openpyxl import load_workbook
from sqlalchemy.orm import Session

from config import AKTIVITAET_ART_MAPPING
from models.aktivitaet import Aktivitaet
from models.beziehung import Beziehung
from models.kontakt import Kontakt
import search

logger = logging.getLogger("kontaktwerk.import")

# Spalten-Mapping: Cobra Excel Header -> Kontakt-Felder
KONTAKT_FELD_MAPPING = {
    "Adr.-Nr.": "cobra_id",
    "Anrede": "anrede",
    "Titel": "titel",
    "Vorname": "vorname",
    "Name": "nachname",
    "Briefanrede": "briefanrede",
    "Firma": "firmenname",
    "Firma2": "firmenname2",
    "Straße": "strasse",
    "Strasse": "strasse",
    "PLZ": "plz",
    "Ort": "ort",
    "Land": "land",
    "E-Mail": "email1",
    "E-Mail2": "email2",
    "Telefon": "telefon",
    "Telefon-Direkt": "telefon_direkt",
    "Mobiltelefon": "mobil",
    "Telefax": "telefax",
    "Internet": "webseite",
    "Position": "position",
    "Abteilung": "abteilung",
    "Bemerkung": "bemerkung",
    "Eigentümer": "eigentuemer",
    "Eigentuemer": "eigentuemer",
    "Betreuer": "betreuer",
    "Newsletter": "newsletter",
    "Keine Mails": "keine_mails",
    "Keine Briefe": "keine_briefe",
    "Keine Anrufe": "keine_anrufe",
}

AKTIVITAET_FELD_MAPPING = {
    "Akt.-Nr.": "cobra_id",
    "Adr.-Nr.": "_kontakt_cobra_id",
    "Art": "_art_code",
    "Betreff": "betreff",
    "Bemerkung": "bemerkung",
    "Status": "status",
    "Datum": "_datum",
    "Fällig am": "_faellig_am",
    "Faellig am": "_faellig_am",
    "Projekt": "projekt",
    "Eigentümer": "erfasst_von",
    "Eigentuemer": "erfasst_von",
}


def import_kontakte_excel(db: Session, datei: BytesIO) -> str:
    """Kontakte aus Cobra-Excel importieren."""
    wb = load_workbook(datei, read_only=True, data_only=True)
    ws = wb.active

    rows = list(ws.iter_rows(values_only=True))
    if not rows:
        return "Leere Datei."

    header = [str(h).strip() if h else "" for h in rows[0]]
    col_map = {}
    for idx, h in enumerate(header):
        if h in KONTAKT_FELD_MAPPING:
            col_map[idx] = KONTAKT_FELD_MAPPING[h]

    # Stichwort-Spalten identifizieren
    stichwort_cols = []
    for idx, h in enumerate(header):
        if h and h.startswith("Stichwort"):
            stichwort_cols.append(idx)

    importiert = 0
    uebersprungen = 0
    uebersprungen_blacklist = 0
    firmen_set = set()
    stichworte_gesamt = set()

    for row in rows[1:]:
        daten = {}
        for idx, feld in col_map.items():
            wert = row[idx] if idx < len(row) else None
            if wert is not None:
                daten[feld] = str(wert).strip()

        if not daten.get("nachname") and not daten.get("firmenname"):
            uebersprungen += 1
            continue

        cobra_id = daten.get("cobra_id")
        if cobra_id:
            existing = db.query(Kontakt).filter(Kontakt.cobra_id == cobra_id).first()
            if existing:
                uebersprungen += 1
                continue

        # Blacklist-Check nach cobra_id
        if cobra_id:
            blacklisted = db.query(Kontakt).filter(
                Kontakt.cobra_id == cobra_id, Kontakt.ist_blacklisted == True
            ).first()
            if blacklisted:
                uebersprungen_blacklist += 1
                continue

        # Blacklist-Check nach Name
        nachname = daten.get("nachname", "").strip()
        vorname = daten.get("vorname", "").strip()
        if nachname:
            bl_query = db.query(Kontakt).filter(
                Kontakt.ist_blacklisted == True,
                Kontakt.nachname.ilike(nachname),
            )
            if vorname:
                bl_query = bl_query.filter(Kontakt.vorname.ilike(vorname))
            if bl_query.first():
                uebersprungen_blacklist += 1
                continue

        # Typ bestimmen
        daten["typ"] = "person"
        daten["erfasst_am"] = datetime.now()

        kontakt = Kontakt(**{k: v for k, v in daten.items() if hasattr(Kontakt, k) and v})
        db.add(kontakt)

        # Firma merken
        if daten.get("firmenname"):
            firmen_set.add(daten["firmenname"].strip())

        # Stichworte sammeln
        for sc in stichwort_cols:
            val = row[sc] if sc < len(row) else None
            if val and str(val).strip():
                stichworte_gesamt.add(str(val).strip())

        importiert += 1

    db.flush()

    # Organisationen aus Firmennamen extrahieren
    org_count = 0
    for firma in firmen_set:
        existing = db.query(Kontakt).filter(
            Kontakt.typ == "organisation",
            Kontakt.firmenname == firma,
        ).first()
        if not existing:
            org = Kontakt(typ="organisation", firmenname=firma, erfasst_am=datetime.now())
            db.add(org)
            org_count += 1

    db.flush()

    # Beziehungen: Person -> Organisation
    bez_count = 0
    personen = db.query(Kontakt).filter(Kontakt.typ == "person", Kontakt.firmenname.isnot(None)).all()
    for person in personen:
        if not person.firmenname:
            continue
        org = db.query(Kontakt).filter(
            Kontakt.typ == "organisation",
            Kontakt.firmenname == person.firmenname,
        ).first()
        if org:
            existing_bez = db.query(Beziehung).filter(
                Beziehung.kontakt_a_id == person.id,
                Beziehung.kontakt_b_id == org.id,
            ).first()
            if not existing_bez:
                bez = Beziehung(
                    kontakt_a_id=person.id,
                    kontakt_b_id=org.id,
                    typ="mitarbeiter_von",
                    rolle_a="Mitarbeiter",
                    rolle_b="Arbeitgeber",
                    ist_aktiv=True,
                )
                db.add(bez)
                bez_count += 1

    db.commit()

    # Suchindex aufbauen fuer importierte Kontakte
    for kontakt in db.query(Kontakt).all():
        search.index_kontakt(db, kontakt)
    db.commit()

    wb.close()

    bericht = f"""Import abgeschlossen:
- {importiert} Kontakte importiert
- {uebersprungen} uebersprungen (bereits vorhanden oder leer)
- {uebersprungen_blacklist} uebersprungen (Blacklist)
- {org_count} Organisationen extrahiert
- {bez_count} Beziehungen erstellt
- {len(stichworte_gesamt)} einzigartige Stichworte gefunden"""

    return bericht


def import_aktivitaeten_excel(db: Session, datei: BytesIO) -> str:
    """Aktivitaeten aus Cobra-Excel importieren."""
    wb = load_workbook(datei, read_only=True, data_only=True)
    ws = wb.active

    rows = list(ws.iter_rows(values_only=True))
    if not rows:
        return "Leere Datei."

    header = [str(h).strip() if h else "" for h in rows[0]]
    col_map = {}
    for idx, h in enumerate(header):
        if h in AKTIVITAET_FELD_MAPPING:
            col_map[idx] = AKTIVITAET_FELD_MAPPING[h]

    # Kontakt-Lookup-Map (cobra_id -> id)
    kontakt_map = {}
    for k in db.query(Kontakt).filter(Kontakt.cobra_id.isnot(None)).all():
        kontakt_map[k.cobra_id] = k.id

    importiert = 0
    uebersprungen = 0

    for row in rows[1:]:
        daten = {}
        for idx, feld in col_map.items():
            wert = row[idx] if idx < len(row) else None
            if wert is not None:
                daten[feld] = wert

        cobra_id = str(daten.get("cobra_id", "")).strip()
        if cobra_id:
            existing = db.query(Aktivitaet).filter(Aktivitaet.cobra_id == cobra_id).first()
            if existing:
                uebersprungen += 1
                continue

        # Kontakt zuordnen
        kontakt_cobra_id = str(daten.get("_kontakt_cobra_id", "")).strip()
        kontakt_id = kontakt_map.get(kontakt_cobra_id)
        if not kontakt_id:
            uebersprungen += 1
            continue

        # Art mappen
        art_code = str(daten.get("_art_code", "")).strip()
        art = AKTIVITAET_ART_MAPPING.get(art_code, "sonstiges")

        # Datum parsen
        datum = None
        raw_datum = daten.get("_datum")
        if isinstance(raw_datum, datetime):
            datum = raw_datum
        elif raw_datum:
            try:
                datum = datetime.fromisoformat(str(raw_datum))
            except (ValueError, TypeError):
                pass

        faellig_am = None
        raw_faellig = daten.get("_faellig_am")
        if isinstance(raw_faellig, datetime):
            faellig_am = raw_faellig

        akt = Aktivitaet(
            cobra_id=cobra_id if cobra_id else None,
            kontakt_id=kontakt_id,
            art=art,
            betreff=str(daten.get("betreff", "")).strip() or None,
            bemerkung=str(daten.get("bemerkung", "")).strip() or None,
            status=str(daten.get("status", "erledigt")).strip() or "erledigt",
            datum=datum,
            faellig_am=faellig_am,
            projekt=str(daten.get("projekt", "")).strip() or None,
            erfasst_von=str(daten.get("erfasst_von", "")).strip() or None,
            erfasst_am=datum or datetime.now(),
        )
        db.add(akt)
        importiert += 1

        # Batch commit alle 500
        if importiert % 500 == 0:
            db.flush()

    db.commit()

    # Suchindex fuer Aktivitaeten aufbauen
    for akt in db.query(Aktivitaet).all():
        search.index_aktivitaet(db, akt)
    db.commit()

    wb.close()

    bericht = f"""Aktivitaeten-Import abgeschlossen:
- {importiert} Aktivitaeten importiert
- {uebersprungen} uebersprungen (kein Kontakt gefunden oder bereits vorhanden)"""

    return bericht
