"""Graph-Builder: builds reference graph for navigation between Vorlagen."""

from __future__ import annotations

import sqlite3


def get_references_for_vorlage(conn: sqlite3.Connection, vorlage_id: int) -> dict:
    """Get all references (incoming and outgoing) for a Vorlage.

    Returns dict with 'ausgehend' (outgoing) and 'eingehend' (incoming) lists.
    """
    ausgehend = conn.execute("""
        SELECT r.id, r.ziel_id as vorlage_id, r.typ, r.konfidenz, r.kontext,
               v.aktenzeichen, v.betreff, v.typ as vorlage_typ, v.datum_eingang
        FROM referenzen r
        JOIN vorlagen v ON r.ziel_id = v.id
        WHERE r.quelle_id = ?
        ORDER BY v.datum_eingang
    """, (vorlage_id,)).fetchall()

    eingehend = conn.execute("""
        SELECT r.id, r.quelle_id as vorlage_id, r.typ, r.konfidenz, r.kontext,
               v.aktenzeichen, v.betreff, v.typ as vorlage_typ, v.datum_eingang
        FROM referenzen r
        JOIN vorlagen v ON r.quelle_id = v.id
        WHERE r.ziel_id = ?
        ORDER BY v.datum_eingang
    """, (vorlage_id,)).fetchall()

    return {
        "ausgehend": [_ref_to_dict(r) for r in ausgehend],
        "eingehend": [_ref_to_dict(r) for r in eingehend],
    }


def get_kette_graph(conn: sqlite3.Connection, kette_id: int) -> dict:
    """Build the Perlenschnur graph data for a Kette.

    Returns nodes (Vorlagen) and edges (Referenzen) for visualization.
    """
    # Get all Vorlagen in this chain
    glieder = conn.execute("""
        SELECT kg.position, kg.rolle, v.id, v.aktenzeichen, v.typ, v.betreff,
               v.datum_eingang, v.ist_verwaltungsvorlage
        FROM ketten_glieder kg
        JOIN vorlagen v ON kg.vorlage_id = v.id
        WHERE kg.kette_id = ?
        ORDER BY kg.position
    """, (kette_id,)).fetchall()

    vorlage_ids = [g["id"] for g in glieder]
    if not vorlage_ids:
        return {"nodes": [], "edges": []}

    placeholders = ",".join("?" * len(vorlage_ids))

    # Get all references between chain members
    edges_internal = conn.execute(f"""
        SELECT r.id, r.quelle_id, r.ziel_id, r.typ, r.konfidenz
        FROM referenzen r
        WHERE r.quelle_id IN ({placeholders})
          AND r.ziel_id IN ({placeholders})
    """, vorlage_ids + vorlage_ids).fetchall()

    # Get references to/from external Vorlagen (for side-links)
    edges_external = conn.execute(f"""
        SELECT r.id, r.quelle_id, r.ziel_id, r.typ, r.konfidenz,
               v.aktenzeichen, v.betreff, v.typ as vorlage_typ, v.datum_eingang
        FROM referenzen r
        JOIN vorlagen v ON CASE
            WHEN r.quelle_id IN ({placeholders}) THEN r.ziel_id = v.id
            ELSE r.quelle_id = v.id
        END
        WHERE (r.quelle_id IN ({placeholders}) AND r.ziel_id NOT IN ({placeholders}))
           OR (r.ziel_id IN ({placeholders}) AND r.quelle_id NOT IN ({placeholders}))
    """, vorlage_ids * 5).fetchall()

    # Get Beratungen for each chain Vorlage
    beratungen = conn.execute(f"""
        SELECT b.vorlage_id, b.sitzung_datum, b.rolle, b.ergebnis,
               g.name as gremium_name
        FROM beratungen b
        LEFT JOIN gremien g ON b.gremium_id = g.id
        WHERE b.vorlage_id IN ({placeholders})
        ORDER BY b.sitzung_datum
    """, vorlage_ids).fetchall()

    beratungen_map: dict[int, list] = {}
    for b in beratungen:
        vid = b["vorlage_id"]
        if vid not in beratungen_map:
            beratungen_map[vid] = []
        beratungen_map[vid].append({
            "sitzung_datum": b["sitzung_datum"],
            "rolle": b["rolle"],
            "ergebnis": b["ergebnis"],
            "gremium_name": b["gremium_name"],
        })

    # Get Antragsteller for Ursprung
    antragsteller = conn.execute(f"""
        SELECT a.vorlage_id, p.kuerzel, p.name, p.farbe
        FROM antragsteller a
        JOIN parteien p ON a.partei_id = p.id
        WHERE a.vorlage_id IN ({placeholders})
    """, vorlage_ids).fetchall()

    antragsteller_map: dict[int, list] = {}
    for a in antragsteller:
        vid = a["vorlage_id"]
        if vid not in antragsteller_map:
            antragsteller_map[vid] = []
        antragsteller_map[vid].append({
            "kuerzel": a["kuerzel"],
            "name": a["name"],
            "farbe": a["farbe"],
        })

    nodes = [
        {
            "id": g["id"],
            "aktenzeichen": g["aktenzeichen"],
            "typ": g["typ"],
            "betreff": g["betreff"],
            "datum_eingang": g["datum_eingang"],
            "position": g["position"],
            "rolle": g["rolle"],
            "ist_verwaltungsvorlage": bool(g["ist_verwaltungsvorlage"]),
            "beratungen": beratungen_map.get(g["id"], []),
            "antragsteller": antragsteller_map.get(g["id"], []),
        }
        for g in glieder
    ]

    edges = [
        {
            "quelle_id": e["quelle_id"],
            "ziel_id": e["ziel_id"],
            "typ": e["typ"],
            "konfidenz": e["konfidenz"],
        }
        for e in edges_internal
    ]

    external_nodes = []
    for e in edges_external:
        ext_id = e["ziel_id"] if e["quelle_id"] in vorlage_ids else e["quelle_id"]
        if not any(n["id"] == ext_id for n in external_nodes):
            external_nodes.append({
                "id": ext_id,
                "aktenzeichen": e["aktenzeichen"],
                "typ": e["vorlage_typ"],
                "betreff": e["betreff"],
                "datum_eingang": e["datum_eingang"],
                "extern": True,
            })
        edges.append({
            "quelle_id": e["quelle_id"],
            "ziel_id": e["ziel_id"],
            "typ": e["typ"],
            "konfidenz": e["konfidenz"],
        })

    return {
        "nodes": nodes + external_nodes,
        "edges": edges,
    }


def _ref_to_dict(r: sqlite3.Row) -> dict:
    return {
        "vorlage_id": r["vorlage_id"],
        "aktenzeichen": r["aktenzeichen"],
        "betreff": r["betreff"],
        "vorlage_typ": r["vorlage_typ"],
        "datum_eingang": r["datum_eingang"],
        "ref_typ": r["typ"],
        "konfidenz": r["konfidenz"],
        "kontext": r["kontext"],
    }
