"""Applicability-Gate fuer den Cookie-Policy-Scan.

Schliesst Controls aus dem Cookie-Findings-Scan aus, die laut
`compliance.control_classification` NICHT gegen eine Cookie-Policy laufen
('COOKIE_POLICY' nicht in applicable_artifacts). Diese gehoeren zu einem
anderen Artefakt/Pruefer — Banner (BEHAVIOR/Playwright), Security/TOM/Audit
(PROCESS) — und erzeugen sonst Unsinn-Findings (z.B. 'TOMs nicht dokumentiert'
gegen eine Cookie-Richtlinie). Sie werden NICHT geloescht, sondern als
Routing-Liste zurueckgegeben.

Anders als das DSE-Gate OHNE needs_review-Ausnahme: das Artefakt-Signal ist
hier entscheidend und per Inventar (2026-06-21) belegt; die mis-scopeten 11
sind geprueft. Fail-safe: fehlt die Tabelle / DB nicht erreichbar -> leeres
Dict -> es wird NICHT gefiltert (kein stiller Recall-Verlust).
"""

from __future__ import annotations

import logging
import os
from typing import Any

logger = logging.getLogger(__name__)


async def load_cookie_gate(db_url: str = "") -> dict[str, dict[str, Any]]:
    """Liefert {control_id: meta} fuer Controls, die aus dem Cookie-Findings-
    Scan auszuschliessen sind (kein COOKIE_POLICY-Artefakt). 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
                   FROM compliance.control_classification
                   WHERE is_active
                     AND NOT ('COOKIE_POLICY' = ANY(applicable_artifacts))""")
        finally:
            await conn.close()
    except Exception as e:  # Tabelle fehlt / DB weg -> kein Filter
        logger.info("cookie 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 []),
        }
        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 (kept, routed_out).

    kept: laufen normal durch den Cookie-Scan.
    routed_out: aus dem Scan genommen (control_id + title + Klassifikations-
    Metadaten fuer das Routing zu Banner/Security/Audit).
    """
    kept: list[dict[str, Any]] = []
    routed_out: list[dict[str, Any]] = []
    for c in controls:
        cid = c.get("control_id")
        meta = gate.get(cid) if cid else None
        if meta:
            routed_out.append({"control_id": cid, "title": c.get("title"), **meta})
        else:
            kept.append(c)
    return kept, routed_out
