"""Tests for configuration loading and validation."""

from __future__ import annotations

from typing import TYPE_CHECKING

import pytest

from curadise_agent.config.loader import load_config, load_yaml_file, validate_config_file
from curadise_agent.config.schema import AgentConfig, ServerConfig
from curadise_agent.config.settings import Settings
from curadise_agent.errors import ConfigurationError

if TYPE_CHECKING:
    from pathlib import Path


class TestConfigLoader:
    """Tests for configuration loading."""

    def test_load_yaml_file(self, temp_dir: Path) -> None:
        """Test loading a YAML file."""
        config_file = temp_dir / "config.yaml"
        config_file.write_text(
            """
server:
  url: https://test.example.com
  timeout: 30
"""
        )

        data = load_yaml_file(config_file)
        assert data["server"]["url"] == "https://test.example.com"
        assert data["server"]["timeout"] == 30

    def test_load_yaml_with_jinja2(self, temp_dir: Path, monkeypatch: pytest.MonkeyPatch) -> None:
        """Test loading YAML with Jinja2 templating."""
        monkeypatch.setenv("TEST_URL", "https://templated.example.com")

        config_file = temp_dir / "config.yaml"
        config_file.write_text(
            """
server:
  url: "{{ env('TEST_URL') }}"
"""
        )

        data = load_yaml_file(config_file)
        assert data["server"]["url"] == "https://templated.example.com"

    def test_load_yaml_file_not_found(self, temp_dir: Path) -> None:
        """Test error when file not found."""
        with pytest.raises(ConfigurationError, match="not found"):
            load_yaml_file(temp_dir / "nonexistent.yaml")

    def test_load_config_minimal(self, temp_dir: Path) -> None:
        """Test loading minimal configuration."""
        config_file = temp_dir / "config.yaml"
        config_file.write_text(
            """
server:
  url: https://test.example.com
"""
        )

        config = load_config(config_path=config_file)
        assert isinstance(config, AgentConfig)
        assert config.server.url == "https://test.example.com"
        assert config.server.timeout == 30.0  # Default

    def test_load_config_with_env_override(
        self, temp_dir: Path, monkeypatch: pytest.MonkeyPatch
    ) -> None:
        """Test that environment variables override file config."""
        monkeypatch.setenv("CURADISE_SERVER_URL", "https://env.example.com")

        config_file = temp_dir / "config.yaml"
        config_file.write_text(
            """
server:
  url: https://file.example.com
"""
        )

        settings = Settings()
        config = load_config(config_path=config_file, settings=settings)
        assert config.server.url == "https://env.example.com"

    def test_validate_config_file_valid(self, temp_dir: Path) -> None:
        """Test validating a valid configuration file."""
        config_file = temp_dir / "config.yaml"
        config_file.write_text(
            """
server:
  url: https://test.example.com
"""
        )

        is_valid, errors = validate_config_file(config_file)
        assert is_valid
        assert errors == []

    def test_validate_config_file_invalid(self, temp_dir: Path) -> None:
        """Test validating an invalid configuration file."""
        config_file = temp_dir / "config.yaml"
        config_file.write_text(
            """
server:
  url: not-a-valid-url
"""
        )

        is_valid, errors = validate_config_file(config_file)
        assert not is_valid
        assert len(errors) > 0


class TestServerConfig:
    """Tests for server configuration validation."""

    def test_valid_https_url(self) -> None:
        """Test valid HTTPS URL."""
        config = ServerConfig(url="https://test.example.com")
        assert config.url == "https://test.example.com"

    def test_valid_http_url(self) -> None:
        """Test valid HTTP URL."""
        config = ServerConfig(url="http://localhost:8080")
        assert config.url == "http://localhost:8080"

    def test_url_trailing_slash_removed(self) -> None:
        """Test that trailing slashes are removed."""
        config = ServerConfig(url="https://test.example.com/")
        assert config.url == "https://test.example.com"

    def test_invalid_url(self) -> None:
        """Test invalid URL rejected."""
        with pytest.raises(ValueError, match="must start with"):
            ServerConfig(url="not-a-url")

    def test_timeout_range(self) -> None:
        """Test timeout validation."""
        config = ServerConfig(url="https://test.example.com", timeout=60.0)
        assert config.timeout == 60.0

        with pytest.raises(ValueError):
            ServerConfig(url="https://test.example.com", timeout=0)

        with pytest.raises(ValueError):
            ServerConfig(url="https://test.example.com", timeout=500)


class TestSettings:
    """Tests for environment-based settings."""

    def test_default_settings(self) -> None:
        """Test default settings values."""
        settings = Settings()
        assert settings.server_url is None
        assert settings.server_timeout == 30.0
        assert settings.log_level == "INFO"

    def test_settings_from_env(self, monkeypatch: pytest.MonkeyPatch) -> None:
        """Test loading settings from environment."""
        monkeypatch.setenv("CURADISE_SERVER_URL", "https://env.example.com")
        monkeypatch.setenv("CURADISE_LOG_LEVEL", "DEBUG")

        settings = Settings()
        assert settings.server_url == "https://env.example.com"
        assert settings.log_level == "DEBUG"

    def test_to_config_overrides(self, monkeypatch: pytest.MonkeyPatch) -> None:
        """Test converting settings to config overrides."""
        monkeypatch.setenv("CURADISE_SERVER_URL", "https://env.example.com")
        monkeypatch.setenv("CURADISE_LOG_LEVEL", "DEBUG")

        settings = Settings()
        overrides = settings.to_config_overrides()

        assert "server" in overrides
        assert overrides["server"]["url"] == "https://env.example.com"
        assert "logging" in overrides
        assert overrides["logging"]["level"] == "DEBUG"
