"""Integration tests for trigger and retention settings loading."""

from __future__ import annotations

import pytest

from noteflow.config.settings import Settings, get_settings, get_trigger_settings
from tests.conftest import approx_float

pytestmark = [pytest.mark.integration, pytest.mark.usefixtures("clear_settings_cache")]


@pytest.fixture
def clear_settings_cache() -> None:
    get_trigger_settings.cache_clear()
    get_settings.cache_clear()


@pytest.mark.parametrize(
    "attr,expected",
    [
        ("trigger_meeting_apps", ["zoom", "teams"]),
        ("trigger_suppressed_apps", ["spotify"]),
        ("trigger_audio_min_samples", 5),
    ],
)
def test_trigger_settings_env_parsing(
    monkeypatch: pytest.MonkeyPatch, attr: str, expected: list[str] | int
) -> None:
    """TriggerSettings should parse CSV lists from environment variables."""
    monkeypatch.setenv("NOTEFLOW_TRIGGER_MEETING_APPS", "zoom, teams")
    monkeypatch.setenv("NOTEFLOW_TRIGGER_SUPPRESSED_APPS", "spotify")
    monkeypatch.setenv("NOTEFLOW_TRIGGER_AUDIO_MIN_SAMPLES", "5")
    monkeypatch.setenv("NOTEFLOW_TRIGGER_POLL_INTERVAL_SECONDS", "1.5")
    settings = get_trigger_settings()
    actual = getattr(settings, attr)
    assert actual == expected, f"TriggerSettings.{attr}: expected {expected!r}, got {actual!r}"


def test_trigger_settings_poll_interval_parsing(monkeypatch: pytest.MonkeyPatch) -> None:
    """TriggerSettings parses poll interval as float."""
    monkeypatch.setenv("NOTEFLOW_TRIGGER_POLL_INTERVAL_SECONDS", "1.5")
    settings = get_trigger_settings()
    actual = settings.trigger_poll_interval_seconds
    assert actual == approx_float(1.5), f"poll_interval_seconds: expected 1.5, got {actual}"


class TestRetentionSettings:
    """Tests for retention settings."""

    def test_retention_defaults(self) -> None:
        """Retention settings should have correct defaults."""
        # Access via class to check field defaults without loading from env
        expected_retention_days_default = 90
        expected_check_interval_default = 24
        retention_enabled_default = Settings.model_fields["retention_enabled"].default
        retention_days_default = Settings.model_fields["retention_days"].default
        check_interval_default = Settings.model_fields["retention_check_interval_hours"].default
        assert retention_enabled_default is False, (
            f"retention_enabled default: expected False, got {retention_enabled_default!r}"
        )
        assert retention_days_default == expected_retention_days_default, (
            f"retention_days default: expected {expected_retention_days_default}, got {retention_days_default}"
        )
        assert check_interval_default == expected_check_interval_default, (
            f"retention_check_interval_hours default: expected {expected_check_interval_default}, "
            f"got {check_interval_default}"
        )

    def test_retention_env_parsing(self, monkeypatch: pytest.MonkeyPatch) -> None:
        """Retention settings should parse from environment variables."""
        monkeypatch.setenv("NOTEFLOW_DATABASE_URL", "postgresql+asyncpg://user:pass@localhost/db")
        monkeypatch.setenv("NOTEFLOW_RETENTION_ENABLED", "true")
        expected_retention_days = 30
        expected_check_interval = 12
        monkeypatch.setenv("NOTEFLOW_RETENTION_DAYS", str(expected_retention_days))
        monkeypatch.setenv("NOTEFLOW_RETENTION_CHECK_INTERVAL_HOURS", str(expected_check_interval))

        settings = get_settings()

        assert settings.retention_enabled is True, (
            f"retention_enabled: expected True, got {settings.retention_enabled!r}"
        )
        assert settings.retention_days == expected_retention_days, (
            f"retention_days: expected {expected_retention_days}, got {settings.retention_days}"
        )
        assert settings.retention_check_interval_hours == expected_check_interval, (
            f"retention_check_interval_hours: expected {expected_check_interval}, "
            f"got {settings.retention_check_interval_hours}"
        )

    def test_retention_days_validation(self) -> None:
        """Retention days should be validated within range."""
        from pydantic import ValidationError

        # ge=1, le=3650
        with pytest.raises(ValidationError, match="retention_days"):
            Settings.model_validate(
                {"database_url": "postgresql+asyncpg://x:x@x/x", "retention_days": 0}
            )
        with pytest.raises(ValidationError, match="retention_days"):
            Settings.model_validate(
                {"database_url": "postgresql+asyncpg://x:x@x/x", "retention_days": 4000}
            )

    def test_retention_check_interval_validation(self) -> None:
        """Retention check interval should be validated within range."""
        from pydantic import ValidationError

        # ge=1, le=168
        with pytest.raises(ValidationError, match="retention_check_interval_hours"):
            Settings.model_validate(
                {
                    "database_url": "postgresql+asyncpg://x:x@x/x",
                    "retention_check_interval_hours": 0,
                }
            )
        with pytest.raises(ValidationError, match="retention_check_interval_hours"):
            Settings.model_validate(
                {
                    "database_url": "postgresql+asyncpg://x:x@x/x",
                    "retention_check_interval_hours": 200,
                }
            )
