"""GENERATED by witgen — DO NOT EDIT.

Re-generate with: uv run python -m tools.witgen
"""

from __future__ import annotations

import threading
from typing import Any

from wasmtime import Engine, Store
from wasmtime import component as cm

from ._convert import (
    from_wasm_detect_bot,
    from_wasm_detect_sensitive_info,
    from_wasm_generate_fingerprint,
    from_wasm_is_valid_email,
    from_wasm_match_filters,
    from_wasm_validate_characteristics,
    to_wasm_bot_config,
    to_wasm_email_validation_config,
    to_wasm_sensitive_info_config,
)
from ._imports import ImportCallbacks, wire_imports
from ._types import (
    BotConfig,
    BotResult,
    EmailValidationConfig,
    EmailValidationResult,
    FilterResult,
    Result,
    SensitiveInfoConfig,
    SensitiveInfoResult,
)


class AnalyzeComponentBase:
    """Reusable wrapper around the full arcjet-analyze WASM component."""

    def __init__(
        self,
        wasm_path: str,
        callbacks: ImportCallbacks | None = None,
    ) -> None:
        self._engine = Engine()
        self._component = cm.Component.from_file(self._engine, wasm_path)
        self._linker = cm.Linker(self._engine)
        self._linker.allow_shadowing = True

        wire_imports(self._linker, self._component, callbacks)

        # Lock for thread safety: wasmtime-py wrappers have unprotected
        # mutable state (Slab globals, attribute reads). A per-instance
        # lock around _call() provides defensive safety at negligible
        # cost (WASM calls are 1-5ms).
        self._call_lock = threading.Lock()
        self._closed = False

    def _call(self, export_name: str, *args: Any) -> Any:
        """Call a named export with a fresh Store."""
        if self._closed:
            raise RuntimeError("AnalyzeComponent is closed")
        with self._call_lock:
            store = Store(self._engine)
            instance = self._linker.instantiate(store, self._component)
            func = instance.get_func(store, export_name)
            if func is None:
                raise RuntimeError(f"{export_name} export not found in component")
            return func(store, *args)

    def close(self) -> None:
        """Release WASM engine resources."""
        self._closed = True

    def __enter__(self) -> AnalyzeComponentBase:
        """Support use as a context manager."""
        return self

    def __exit__(self, *args: Any) -> None:
        """Close on context manager exit."""
        self.close()

    def detect_bot(
        self,
        request: str,
        options: BotConfig,
    ) -> Result[BotResult, str]:
        """Run ``detect-bot`` on the component."""
        raw = self._call("detect-bot", request, to_wasm_bot_config(options))
        return from_wasm_detect_bot(raw)

    def match_filters(
        self,
        request: str,
        local_fields: str,
        expressions: list[str],
        allow_if_match: bool,
    ) -> Result[FilterResult, str]:
        """Run ``match-filters`` on the component."""
        raw = self._call("match-filters", request, local_fields, expressions, allow_if_match)
        return from_wasm_match_filters(raw)

    def generate_fingerprint(
        self,
        request: str,
        characteristics: list[str],
    ) -> Result[str, str]:
        """Run ``generate-fingerprint`` on the component."""
        raw = self._call("generate-fingerprint", request, characteristics)
        return from_wasm_generate_fingerprint(raw)

    def validate_characteristics(
        self,
        request: str,
        characteristics: list[str],
    ) -> Result[None, str]:
        """Run ``validate-characteristics`` on the component."""
        raw = self._call("validate-characteristics", request, characteristics)
        return from_wasm_validate_characteristics(raw)

    def is_valid_email(
        self,
        candidate: str,
        options: EmailValidationConfig,
    ) -> Result[EmailValidationResult, str]:
        """Run ``is-valid-email`` on the component."""
        raw = self._call("is-valid-email", candidate, to_wasm_email_validation_config(options))
        return from_wasm_is_valid_email(raw)

    def detect_sensitive_info(
        self,
        content: str,
        options: SensitiveInfoConfig,
    ) -> SensitiveInfoResult:
        """Run ``detect-sensitive-info`` on the component."""
        raw = self._call("detect-sensitive-info", content, to_wasm_sensitive_info_config(options))
        return from_wasm_detect_sensitive_info(raw)
