"""Bridge self-monitoring service provider — emits internal-failure events.

This is a passive provider: it does not connect to anything, never polls,
and never subscribes. It exists so the rest of the bridge's CRUD / config /
template / target plumbing has a single ``ServiceProvider`` to attach
self-monitoring trackers and notification slots to.

Events are constructed by the server-side helper
``services/bridge_self.emit_bridge_self_event`` and pushed into
``dispatch_provider_event`` directly — the provider itself is not asked
to produce events.
"""

from __future__ import annotations

from typing import Any

from notify_bridge_core.models.events import ServiceEvent
from notify_bridge_core.providers.base import (
    ServiceProvider,
    ServiceProviderType,
)
from notify_bridge_core.templates.variables import TemplateVariableDefinition


# Configuration keys recognised on the bridge_self provider's ``config`` JSON.
DEFAULT_POLL_FAILURE_THRESHOLD = 3
DEFAULT_DEFERRED_BACKLOG_THRESHOLD = 100
DEFAULT_TARGET_FAILURE_THRESHOLD = 5


# Template variables exposed to bridge_self templates.
BRIDGE_SELF_VARIABLES: list[TemplateVariableDefinition] = [
    TemplateVariableDefinition(
        name="failure_type",
        type="string",
        description="Which self-monitoring condition fired",
        example="poll_failures",
        provider_type=ServiceProviderType.BRIDGE_SELF,
    ),
    TemplateVariableDefinition(
        name="subject_id",
        type="int",
        description="ID of the affected entity (tracker_id, target_id, or 0)",
        example="42",
        provider_type=ServiceProviderType.BRIDGE_SELF,
    ),
    TemplateVariableDefinition(
        name="subject_name",
        type="string",
        description="Human-readable name of the affected entity",
        example="My Immich Tracker",
        provider_type=ServiceProviderType.BRIDGE_SELF,
    ),
    TemplateVariableDefinition(
        name="count",
        type="int",
        description="Consecutive failure count or current backlog size",
        example="3",
        provider_type=ServiceProviderType.BRIDGE_SELF,
    ),
    TemplateVariableDefinition(
        name="threshold",
        type="int",
        description="Configured threshold that was crossed",
        example="3",
        provider_type=ServiceProviderType.BRIDGE_SELF,
    ),
    TemplateVariableDefinition(
        name="last_error",
        type="string",
        description="Last underlying error message (truncated)",
        example="Connection refused",
        provider_type=ServiceProviderType.BRIDGE_SELF,
    ),
    TemplateVariableDefinition(
        name="details",
        type="dict",
        description="Extra structured context for the event",
        example='{"provider_id": 7}',
        provider_type=ServiceProviderType.BRIDGE_SELF,
    ),
]


class BridgeSelfServiceProvider(ServiceProvider):
    """Passive provider — exposes nothing remote, holds only thresholds.

    Polling is a no-op and ``connect`` always succeeds; the bridge itself
    is what generates events for this provider.
    """

    provider_type = ServiceProviderType.BRIDGE_SELF
    supports_subscription = False

    def __init__(self, name: str = "Bridge Self-Monitoring") -> None:
        self._name = name

    async def connect(self) -> bool:
        return True

    async def disconnect(self) -> None:
        return None

    async def poll(
        self,
        collection_ids: list[str],
        tracker_state: dict[str, Any],
    ) -> tuple[list[ServiceEvent], dict[str, Any]]:
        # No external service to poll. Returning empty keeps the contract
        # so accidental scheduling no-ops cleanly.
        return [], tracker_state

    def get_available_variables(self) -> list[TemplateVariableDefinition]:
        return list(BRIDGE_SELF_VARIABLES)

    def get_provider_config_schema(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "poll_failure_threshold": {
                    "type": "integer",
                    "minimum": 1,
                    "default": DEFAULT_POLL_FAILURE_THRESHOLD,
                    "description": "Consecutive tracker poll failures before alerting",
                },
                "deferred_backlog_threshold": {
                    "type": "integer",
                    "minimum": 1,
                    "default": DEFAULT_DEFERRED_BACKLOG_THRESHOLD,
                    "description": "Pending deferred_dispatch rows before alerting",
                },
                "target_failure_threshold": {
                    "type": "integer",
                    "minimum": 1,
                    "default": DEFAULT_TARGET_FAILURE_THRESHOLD,
                    "description": "Consecutive target send failures before alerting",
                },
            },
            "required": [],
        }

    async def list_collections(self) -> list[dict[str, Any]]:
        # No collection concept — operators don't pick anything for this provider.
        return []

    async def test_connection(self) -> dict[str, Any]:
        return {"ok": True, "message": "Bridge self-monitoring is always available"}
