"""Applicability-Gate fuer den DSE-Scan.

Schliesst Controls aus dem DSE-FINDINGS-Scan aus, die laut
`compliance.control_classification` NICHT gegen eine DSE laufen
('DSE' nicht in applicable_artifacts) UND sicher klassifiziert sind
(needs_review=false). Diese werden NICHT geloescht, sondern als
*organisatorische Checkliste* zurueckgegeben (Routing zu VVT/TOM/Audit).

Fail-safe: unsichere Klassifikationen (needs_review=true) bleiben im
Findings-Scan. Defensiv: fehlt die Tabelle (z.B. Prod ohne Migration),
liefert das Gate ein leeres Dict -> es wird NICHT gefiltert.
"""

from __future__ import annotations

import logging
import os
from typing import Any

logger = logging.getLogger(__name__)


async def load_dse_gate(db_url: str = "") -> dict[str, dict[str, Any]]:
    """Liefert {control_id: meta} fuer Controls, die aus dem DSE-Findings-Scan
    auszuschliessen sind (hochsicher organisatorisch). Leeres Dict = kein Filter.
    """
    dsn = (db_url or os.getenv("DATABASE_URL")
           or os.getenv("COMPLIANCE_DATABASE_URL") or "")
    if not dsn:
        return {}
    try:
        import asyncpg
        conn = await asyncpg.connect(dsn)
        try:
            rows = await conn.fetch(
                """SELECT control_id, obligation_type, check_intent,
                          applicable_artifacts, reference_allowed
                   FROM compliance.control_classification
                   WHERE is_active AND NOT needs_review
                     AND NOT ('DSE' = ANY(applicable_artifacts))""")
        finally:
            await conn.close()
    except Exception as e:  # Tabelle fehlt / DB nicht erreichbar -> kein Filter
        logger.info("dse classification gate inaktiv: %s", str(e)[:90])
        return {}
    return {
        r["control_id"]: {
            "obligation_type": r["obligation_type"],
            "check_intent": r["check_intent"],
            "applicable_artifacts": list(r["applicable_artifacts"] or []),
            "reference_allowed": r["reference_allowed"],
        }
        for r in rows if r["control_id"]
    }


def apply_gate(
    controls: list[dict[str, Any]],
    gate: dict[str, dict[str, Any]],
) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
    """Teilt geladene Controls in (findings_controls, organizational).

    findings_controls: laufen normal durch den DSE-Scan.
    organizational: aus dem Scan genommen, als Checkliste ausgegeben
    (control_id + title + Klassifikations-Metadaten fuer das Routing).
    """
    kept: list[dict[str, Any]] = []
    organizational: list[dict[str, Any]] = []
    for c in controls:
        cid = c.get("control_id")
        meta = gate.get(cid) if cid else None
        if meta:
            organizational.append({
                "control_id": cid,
                "title": c.get("title"),
                **meta,
            })
        else:
            kept.append(c)
    return kept, organizational
