from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from cyberbrain26.security_plane.egress import DataClassification, EgressRequest

class ExtensionPoint(ABC):
    """Základní rozhraní pro pluggable bezpečnostní brány."""

    @abstractmethod
    def evaluate(self, request: EgressRequest) -> bool:
        """Vrátí True, pokud je požadavek povolen, jinak False."""


class RemoteClassificationGate(ExtensionPoint):
    """Rozhoduje, zda jsou klasifikace dovoleny pro vzdálený egress.

    Default je fail-closed: pokud není povolena ani jedna klasifikace,
    všechny vzdálené výstupy jsou odmíttnuty.
    """

    def __init__(self, allowed: frozenset[DataClassification] | None = None):
        if allowed is None:
            allowed = frozenset()
        if not isinstance(allowed, frozenset):
            allowed = frozenset(allowed)
        self.allowed = allowed

    def evaluate(self, request: EgressRequest) -> bool:
        # Prázdná množina znamená, že klasifikace není definována
        # (defaultní chování volajícího). To je přijatelné pouze
        # pokud nejde o vzdálený egress — volající si to musí uvědomit.
        if not request.classifications:
            return False
        return all(c in self.allowed for c in request.classifications)


class LocalClassificationGate(ExtensionPoint):
    """Rozhoduje, zda jsou klasifikace dovoleny pro lokální egress.

    Default je povoleno {PUBLIC} — lokální proxy běžně pracují
    s veřejnými daty.
    """

    def __init__(self, allowed: frozenset[DataClassification] | None = None):
        if allowed is None:
            from cyberbrain26.security_plane.egress import DataClassification
            allowed = frozenset({DataClassification.PUBLIC})
        if not isinstance(allowed, frozenset):
            allowed = frozenset(allowed)
        self.allowed = allowed

    def evaluate(self, request: EgressRequest) -> bool:
        if not request.classifications:
            return False  # neklasifikovaná data nesmějí projít klasifikační bránou
        return all(c in self.allowed for c in request.classifications)


class EgressPermissionGate(ExtensionPoint):
    """Celkové rozhodnutí o tom, zda má být egress vůbec povolen.

    Default je False (zakázáno, fail-closed), lze ho změnit na True pouze
    jako nouzové vypnutí bezpečnostních omezení (např. po incidentu)
    bez změny jiných politik.
    """

    def __init__(self, base_decision: bool = False):
        self.base_decision = base_decision

    def evaluate(self, request: EgressRequest) -> bool:
        return self.base_decision