"""Tests for Hive node sharing controls (issue #149)."""

from __future__ import annotations

from datetime import datetime, timezone
from typing import TYPE_CHECKING

import pytest

if TYPE_CHECKING:
    from pathlib import Path

from llmhosts.hive.models import HiveMember, HiveRole
from llmhosts.hive.sharing import can_share_model


def _member(
    sharing_enabled: bool = True,
    sharing_schedule: str | None = None,
    shared_models: list[str] | None = None,
) -> HiveMember:
    return HiveMember(
        id="m1",
        name="Test",
        role=HiveRole.MEMBER,
        joined_at=datetime.now(timezone.utc),
        sharing_enabled=sharing_enabled,
        sharing_schedule=sharing_schedule,
        shared_models=shared_models or [],
    )


# ---------------------------------------------------------------------------
# can_share_model: sharing_enabled
# ---------------------------------------------------------------------------


@pytest.mark.unit
def test_can_share_model_disabled() -> None:
    """When sharing_enabled is False, can_share_model is False."""
    m = _member(sharing_enabled=False)
    assert can_share_model(m, "llama3:8b") is False


@pytest.mark.unit
def test_can_share_model_enabled_no_restrictions() -> None:
    """When enabled and no schedule/whitelist, any model can be shared."""
    m = _member(sharing_enabled=True)
    assert can_share_model(m, "llama3:8b") is True
    assert can_share_model(m, "any:model") is True


# ---------------------------------------------------------------------------
# can_share_model: shared_models whitelist
# ---------------------------------------------------------------------------


@pytest.mark.unit
def test_can_share_model_whitelist_included() -> None:
    """When shared_models is non-empty, only listed models are shareable."""
    m = _member(shared_models=["llama3:8b", "mistral:7b"])
    assert can_share_model(m, "llama3:8b") is True
    assert can_share_model(m, "mistral:7b") is True


@pytest.mark.unit
def test_can_share_model_whitelist_excluded() -> None:
    """When shared_models is non-empty, unlisted model is not shareable."""
    m = _member(shared_models=["llama3:8b"])
    assert can_share_model(m, "other:model") is False


# ---------------------------------------------------------------------------
# can_share_model: schedule window
# ---------------------------------------------------------------------------


@pytest.mark.unit
def test_can_share_model_schedule_within_window() -> None:
    """When now is inside the daily window, model can be shared."""
    m = _member(sharing_schedule="09:00-17:00")
    noon = datetime(2025, 6, 15, 12, 0, 0, tzinfo=timezone.utc)
    assert can_share_model(m, "llama3:8b", now=noon) is True


@pytest.mark.unit
def test_can_share_model_schedule_outside_window() -> None:
    """When now is outside the daily window, model cannot be shared."""
    m = _member(sharing_schedule="09:00-17:00")
    evening = datetime(2025, 6, 15, 20, 0, 0, tzinfo=timezone.utc)
    assert can_share_model(m, "llama3:8b", now=evening) is False


@pytest.mark.unit
def test_can_share_model_schedule_overnight_in_window() -> None:
    """Overnight window 22:00-08:00: 02:00 is in window."""
    m = _member(sharing_schedule="22:00-08:00")
    two_am = datetime(2025, 6, 15, 2, 0, 0, tzinfo=timezone.utc)
    assert can_share_model(m, "llama3:8b", now=two_am) is True


@pytest.mark.unit
def test_can_share_model_schedule_overnight_outside_window() -> None:
    """Overnight window 22:00-08:00: 14:00 is outside window."""
    m = _member(sharing_schedule="22:00-08:00")
    two_pm = datetime(2025, 6, 15, 14, 0, 0, tzinfo=timezone.utc)
    assert can_share_model(m, "llama3:8b", now=two_pm) is False


# ---------------------------------------------------------------------------
# HiveRouter respects sharing (integration)
# ---------------------------------------------------------------------------


@pytest.mark.asyncio
@pytest.mark.unit
async def test_hive_router_skips_member_with_sharing_off(tmp_path: Path) -> None:
    """When the only other member has sharing_enabled=False, route does not use Hive."""
    from llmhosts.hive.karma import KarmaEngine
    from llmhosts.hive.manager import HiveManager
    from llmhosts.hive.privacy import PrivacyClassifier
    from llmhosts.hive.router import HiveRouter

    hive_dir = tmp_path / ".llmhosts"
    hive_dir.mkdir(parents=True)
    registry = hive_dir / "hive_registry"
    mgr_a = HiveManager(hive_dir, registry_path=registry)
    mgr_b = HiveManager(hive_dir / "b", registry_path=registry)
    await mgr_a.initialize()
    hive = await mgr_a.create_hive("Share Route Hive", "Alice")
    alice_id = hive.members[0].id
    await mgr_b.initialize()
    await mgr_b.join_hive(hive.invite_code, "Bob")
    # Simulate Alice having disabled sharing (as would be in registry after she runs share --off)
    hive_b = await mgr_b.get_hive()
    assert hive_b is not None
    for m in hive_b.members:
        if m.id == alice_id:
            m.sharing_enabled = False
            break

    router = HiveRouter(mgr_b, PrivacyClassifier(), KarmaEngine(mgr_b))
    decision = await router.route("What is 2+2?", "llama3.2")
    assert decision.use_hive is False
    assert "sharing" in decision.reason.lower() or "available" in decision.reason.lower()
