"""Configuration validation tests."""

from __future__ import annotations

import pytest
from pydantic import ValidationError

from app.config import Settings, normalize_domain
from tests.helpers import build_settings


def test_valid_settings_and_summary_has_no_token(tmp_path) -> None:
    settings = build_settings(tmp_path)
    assert settings.bot_token.get_secret_value().startswith("123456789:")
    assert settings.admin_ids == [4242, 4243]
    assert settings.allowed_domains == ["example.com"]
    summary = settings.safe_summary()
    joined = repr(summary)
    assert "A" * 20 not in joined
    assert "bot_token" not in summary


def test_normalize_domain_accepts_subdomain_and_idna() -> None:
    assert normalize_domain("Example.COM.") == "example.com"
    assert normalize_domain("münich.example") == "xn--mnich-kva.example"


@pytest.mark.parametrize(
    "value",
    [
        "http://example.com",
        "example.com/path",
        "user@example.com",
        "localhost",
        "foo.local",
        "*.example.com",
        "[::1]",
        "127.0.0.1",
        "10.0.0.5",
        "example.com?x=1",
        "exa mple.com",
    ],
)
def test_normalize_domain_rejects_unsafe_values(value: str) -> None:
    with pytest.raises(ValueError):
        normalize_domain(value)


def test_missing_token_and_admin_ids_fail(tmp_path) -> None:
    with pytest.raises(ValidationError) as token_error:
        Settings(
            _env_file=None,
            bot_token="not-a-token",
            admin_ids="1",
            allowed_domains="example.com",
            database_path=tmp_path / "db.sqlite",
        )
    assert "BOT_TOKEN" in str(token_error.value)

    with pytest.raises(ValidationError) as admin_error:
        Settings(
            _env_file=None,
            bot_token="123456789:" + "A" * 35,
            admin_ids="abc",
            allowed_domains="example.com",
            database_path=tmp_path / "db.sqlite",
        )
    assert "ADMIN_IDS" in str(admin_error.value)


def test_empty_allowlist_is_rejected(tmp_path) -> None:
    with pytest.raises(ValidationError):
        build_settings(tmp_path, allowed_domains="")


def test_limits_are_bounded(tmp_path) -> None:
    with pytest.raises(ValidationError):
        build_settings(tmp_path, max_concurrent_downloads=0)
    with pytest.raises(ValidationError):
        build_settings(tmp_path, max_file_size_mb=100_000)
    with pytest.raises(ValidationError):
        build_settings(tmp_path, log_level="LOUD")


def test_size_properties_and_directories(tmp_path) -> None:
    settings = build_settings(tmp_path, max_file_size_mb=3, max_html_mb=2)
    assert settings.max_file_size_bytes == 3 * 1024 * 1024
    assert settings.max_html_bytes == 2 * 1024 * 1024
    settings.ensure_directories()
    assert settings.database_path.parent.is_dir()
    assert settings.log_file.parent.is_dir()
    assert not (tmp_path / "downloads").exists()
    assert settings.safe_summary()["media_storage"] == "disabled (direct stream)"


def test_admin_ids_are_deduplicated(tmp_path) -> None:
    settings = build_settings(tmp_path, admin_ids="7, 7, 8")
    assert settings.admin_ids == [7, 8]
