"""Tests for the HA-specific tracker filter (entity_glob, domain_allowlist).

The Gitea filter is an intersection of senders/collections. The HA filter
is intentionally a *union* across the three keys — any match passes — so a
user can mix exact entity ids with glob patterns and domain allowlists
without each one narrowing the others.
"""

from __future__ import annotations

from datetime import datetime, timezone

from notify_bridge_core.models.events import EventType, ServiceEvent
from notify_bridge_core.providers.base import ServiceProviderType
from notify_bridge_server.services.ha_subscription import _ha_passes_filters


def _ha_event(entity_id: str, domain: str | None = None) -> ServiceEvent:
    return ServiceEvent(
        event_type=EventType.HA_STATE_CHANGED,
        provider_type=ServiceProviderType.HOME_ASSISTANT,
        provider_name="HA",
        collection_id=entity_id,
        collection_name=entity_id,
        timestamp=datetime.now(timezone.utc),
        extra={"domain": domain or (entity_id.split(".", 1)[0] if "." in entity_id else "")},
    )


def test_empty_filters_accept_everything() -> None:
    assert _ha_passes_filters(_ha_event("light.kitchen"), {}) is True


def test_exact_entity_match() -> None:
    filters = {"collections": ["light.kitchen", "switch.lamp"]}
    assert _ha_passes_filters(_ha_event("light.kitchen"), filters) is True
    assert _ha_passes_filters(_ha_event("light.bedroom"), filters) is False


def test_entity_glob_match() -> None:
    filters = {"entity_glob": ["binary_sensor.*_motion", "light.kitchen*"]}
    assert _ha_passes_filters(_ha_event("binary_sensor.hallway_motion"), filters) is True
    assert _ha_passes_filters(_ha_event("light.kitchen_main"), filters) is True
    assert _ha_passes_filters(_ha_event("light.bedroom"), filters) is False


def test_domain_allowlist() -> None:
    filters = {"domain_allowlist": ["light", "switch"]}
    assert _ha_passes_filters(_ha_event("light.kitchen"), filters) is True
    assert _ha_passes_filters(_ha_event("switch.lamp"), filters) is True
    assert _ha_passes_filters(_ha_event("sensor.temp"), filters) is False


def test_union_across_keys() -> None:
    """If collections names a specific sensor.* but domain_allowlist names
    'light', BOTH should be acceptable — that's the difference from the
    Gitea-style intersection filter."""
    filters = {
        "collections": ["sensor.outdoor_temp"],
        "domain_allowlist": ["light"],
    }
    assert _ha_passes_filters(_ha_event("sensor.outdoor_temp"), filters) is True
    assert _ha_passes_filters(_ha_event("light.kitchen"), filters) is True
    # Neither matches:
    assert _ha_passes_filters(_ha_event("binary_sensor.door"), filters) is False


def test_domain_derived_when_extra_missing() -> None:
    """If the parser didn't populate extra.domain (e.g. malformed event),
    the filter must still infer it from the entity_id prefix."""
    evt = ServiceEvent(
        event_type=EventType.HA_STATE_CHANGED,
        provider_type=ServiceProviderType.HOME_ASSISTANT,
        provider_name="HA",
        collection_id="light.kitchen",
        collection_name="light.kitchen",
        timestamp=datetime.now(timezone.utc),
        extra={},  # No 'domain' key.
    )
    assert _ha_passes_filters(evt, {"domain_allowlist": ["light"]}) is True
