"""Coverage tests for notifications/url_builder.py — build_notification_url."""

from unittest.mock import MagicMock, patch

import pytest

from local_deep_research.notifications.url_builder import (
    build_notification_url,
)
from local_deep_research.security.url_validator import URLValidationError

MODULE = "local_deep_research.notifications.url_builder"


class TestBuildNotificationUrlWithSnapshot:
    def test_with_external_url(self):
        url = build_notification_url(
            "/research/123",
            settings_snapshot={"app.external_url": "https://myapp.com"},
            validate=False,
        )
        assert url == "https://myapp.com/research/123"

    def test_with_host_and_port(self):
        url = build_notification_url(
            "/research/456",
            settings_snapshot={
                "app.external_url": "",
                "app.host": "0.0.0.0",
                "app.port": 8080,
            },
            validate=False,
        )
        assert "8080" in url
        assert "/research/456" in url

    def test_fallback_base(self):
        url = build_notification_url(
            "/test",
            fallback_base="http://fallback:9999",
            validate=False,
        )
        assert url == "http://fallback:9999/test"


class TestBuildNotificationUrlWithManager:
    def test_with_settings_manager(self):
        mock_sm = MagicMock()
        mock_sm.get_setting.side_effect = lambda key, **kw: {
            "app.external_url": "https://managed.com",
            "app.host": "localhost",
            "app.port": 5000,
        }.get(key, kw.get("default"))

        url = build_notification_url(
            "/research/789",
            settings_manager=mock_sm,
            validate=False,
        )
        assert "managed.com" in url or "research/789" in url


class TestBuildNotificationUrlValidation:
    def test_valid_url_passes(self):
        url = build_notification_url(
            "/research/123",
            settings_snapshot={"app.external_url": "https://valid.example.com"},
            validate=True,
        )
        assert "valid.example.com" in url

    def test_invalid_url_raises(self):
        with pytest.raises(URLValidationError):
            build_notification_url(
                "/test",
                settings_snapshot={
                    "app.external_url": "not-a-valid-url://???",
                },
                validate=True,
            )

    def test_validation_disabled(self):
        url = build_notification_url(
            "/test",
            validate=False,
        )
        assert isinstance(url, str)


class TestBuildNotificationUrlExceptions:
    def test_build_error_wraps_as_url_validation_error(self):
        with (
            patch(
                f"{MODULE}.build_base_url_from_settings",
                side_effect=RuntimeError("build fail"),
            ),
            pytest.raises(URLValidationError),
        ):
            build_notification_url("/test")

    def test_url_validation_error_reraises(self):
        with (
            patch(
                f"{MODULE}.build_base_url_from_settings",
                side_effect=URLValidationError("bad url"),
            ),
            pytest.raises(URLValidationError, match="bad url"),
        ):
            build_notification_url("/test")


class TestBuildNotificationUrlDefaults:
    def test_default_fallback_base(self):
        url = build_notification_url("/path", validate=False)
        assert "localhost:5000" in url

    def test_empty_path(self):
        url = build_notification_url("", validate=False)
        assert isinstance(url, str)
