from __future__ import annotations

from typing import Any, Callable

from ._config import SurfinguardConfig
from ._http import SurfinguardHTTPClient
from .decorators import _make_protect_decorator
from .enums import Policy, RiskLevel
from .exceptions import NotAllowedError
from .models import CheckResult, HealthResponse


class Guard:
    """Main entry point for the Surfinguard Python SDK.

    Args:
        api_key: Your Surfinguard API key (sg_live_... or sg_test_...).
        base_url: API base URL. Defaults to https://api.surfinguard.com.
        policy: Enforcement policy. PERMISSIVE, MODERATE (default), or STRICT.
        environment: 'live' or 'test'.
        timeout: HTTP request timeout in seconds.
        local_only: If True, raises NotImplementedError (reserved for future local engine).
    """

    def __init__(
        self,
        api_key: str,
        *,
        base_url: str = "https://api.surfinguard.com",
        policy: Policy = Policy.MODERATE,
        environment: str = "live",
        timeout: float = 5.0,
        local_only: bool = False,
    ) -> None:
        if local_only:
            raise NotImplementedError(
                "Local-only mode is not yet supported in the Python SDK. "
                "Use api_key with the hosted API."
            )

        self._config = SurfinguardConfig(
            api_key=api_key,
            base_url=base_url,
            policy=policy,
            environment=environment,
            timeout=timeout,
            local_only=local_only,
        )
        self._http = SurfinguardHTTPClient(self._config)

    def check_url(self, url: str) -> CheckResult:
        """Check a URL for phishing, scams, and malware."""
        data = self._http.post("/v2/check/url", {"url": url})
        result = CheckResult.model_validate(data)
        self._enforce_policy(result)
        return result

    def check_command(self, command: str) -> CheckResult:
        """Check a shell command for destructive or malicious operations."""
        data = self._http.post("/v2/check/command", {"command": command})
        result = CheckResult.model_validate(data)
        self._enforce_policy(result)
        return result

    def check_text(self, text: str) -> CheckResult:
        """Check text for prompt injection attempts."""
        data = self._http.post("/v2/check/text", {"text": text})
        result = CheckResult.model_validate(data)
        self._enforce_policy(result)
        return result

    def check_file_read(self, path: str) -> CheckResult:
        """Check a file read path for sensitive data access."""
        data = self._http.post("/v2/check/file", {"path": path, "operation": "read"})
        result = CheckResult.model_validate(data)
        self._enforce_policy(result)
        return result

    def check_file_write(self, path: str, content: str | None = None) -> CheckResult:
        """Check a file write operation for destructive or persistence risks."""
        payload: dict[str, Any] = {"path": path, "operation": "write"}
        if content is not None:
            payload["content"] = content
        data = self._http.post("/v2/check/file", payload)
        result = CheckResult.model_validate(data)
        self._enforce_policy(result)
        return result

    def check(self, action_type: str, value: str, **metadata: Any) -> CheckResult:
        """Universal check — pass any action type and value."""
        payload: dict[str, Any] = {"type": action_type, "value": value}
        if metadata:
            payload["metadata"] = metadata
        data = self._http.post("/v2/check", payload)
        result = CheckResult.model_validate(data)
        self._enforce_policy(result)
        return result

    def health(self) -> HealthResponse:
        """Check API health and version."""
        data = self._http.get("/v2/health")
        return HealthResponse.model_validate(data)

    def protect(self, action_type: str = "command") -> Callable[..., Any]:
        """Decorator that checks the first argument of a function before execution.

        Args:
            action_type: The action type to check ('url', 'command', 'text', etc.)

        Returns:
            A decorator function.
        """
        return _make_protect_decorator(self, action_type)

    def _enforce_policy(self, result: CheckResult) -> None:
        """Enforce the configured policy. Raises NotAllowedError if blocked."""
        policy = self._config.policy

        if policy == Policy.PERMISSIVE:
            return

        if policy == Policy.MODERATE and result.level == RiskLevel.DANGER:
            raise NotAllowedError(result)

        if policy == Policy.STRICT and result.level in (RiskLevel.CAUTION, RiskLevel.DANGER):
            raise NotAllowedError(result)

    def close(self) -> None:
        """Close the underlying HTTP client."""
        self._http.close()

    def __enter__(self) -> Guard:
        return self

    def __exit__(self, *args: Any) -> None:
        self.close()
