"""Tests for utils module."""

import pytest

from src.utils.config import Settings, load_settings
from src.utils.logger import get_logger
from src.utils.rate_limiter import TokenBucketRateLimiter
from src.utils.validators import (
    validate_content_length,
    validate_keyword,
    validate_platform,
    validate_url,
)


def test_settings_defaults():
    """Test default settings."""
    settings = Settings()
    assert settings.rate_limit_requests == 100
    assert settings.rate_limit_window == 60
    assert settings.cache_ttl_hours == 24
    assert settings.log_level == "INFO"


def test_settings_from_env(monkeypatch):
    """Test settings from environment variables."""
    monkeypatch.setenv("RATE_LIMIT_REQUESTS", "200")
    monkeypatch.setenv("LOG_LEVEL", "DEBUG")
    settings = Settings()
    assert settings.rate_limit_requests == 200
    assert settings.log_level == "DEBUG"


def test_load_settings_from_yaml(tmp_path):
    """Test loading settings from YAML file."""
    config_file = tmp_path / "test_config.yaml"
    config_file.write_text("log_level: WARNING\ncache_ttl_hours: 48\n")
    settings = load_settings(str(config_file))
    assert settings.log_level == "WARNING"
    assert settings.cache_ttl_hours == 48


def test_validate_keyword():
    """Test keyword validation."""
    # Valid keywords
    assert validate_keyword("digital marketing")[0] is True
    assert validate_keyword("SEO tools")[0] is True

    # Invalid keywords
    assert validate_keyword("a")[0] is False  # Too short
    assert validate_keyword("a" * 101)[0] is False  # Too long
    assert validate_keyword("")[0] is False  # Empty
    assert validate_keyword(None)[0] is False  # None
    assert validate_keyword("test<script>")[0] is False  # Invalid chars


def test_validate_url():
    """Test URL validation."""
    # Valid URLs
    assert validate_url("https://example.com")[0] is True
    assert validate_url("http://localhost:8000")[0] is True

    # Invalid URLs
    assert validate_url("ftp://example.com")[0] is False  # Wrong scheme
    assert validate_url("not-a-url")[0] is False  # Invalid format
    assert validate_url("")[0] is False  # Empty
    assert validate_url(None)[0] is False  # None


def test_validate_content_length():
    """Test content length validation."""
    # Valid content
    assert validate_content_length("Short content")[0] is True
    assert validate_content_length("x" * 1000)[0] is True

    # Invalid content
    assert validate_content_length("", min_length=1)[0] is False
    assert validate_content_length("x" * 50001)[0] is False  # Too long
    assert validate_content_length(None)[0] is False
    assert validate_content_length(123)[0] is False  # Not a string


def test_validate_platform():
    """Test platform validation."""
    # Valid platforms
    assert validate_platform("twitter")[0] is True
    assert validate_platform("medium")[0] is True
    assert validate_platform("linkedin")[0] is True

    # Invalid platforms
    assert validate_platform("unknown")[0] is False
    assert validate_platform("")[0] is False
    assert validate_platform(None)[0] is False


@pytest.mark.asyncio
async def test_rate_limiter_singleton():
    """Test rate limiter is singleton."""
    limiter1 = TokenBucketRateLimiter()
    limiter2 = TokenBucketRateLimiter()
    assert limiter1 is limiter2


@pytest.mark.asyncio
async def test_rate_limiter_acquire():
    """Test rate limiter acquire."""
    limiter = TokenBucketRateLimiter()
    await limiter.acquire()
    assert limiter.tokens >= 0


@pytest.mark.asyncio
async def test_rate_limiter_context_manager():
    """Test rate limiter async context manager."""
    async with TokenBucketRateLimiter():
        pass


def test_get_logger():
    """Test logger creation."""
    import logging

    logger = get_logger("test_logger")
    assert isinstance(logger, logging.Logger)
    assert logger.name == "test_logger"


def test_get_logger_with_file(tmp_path):
    """Test logger with file output."""
    log_file = tmp_path / "test.log"
    logger = get_logger("file_test", log_file=str(log_file))
    logger.info("Test message")
    assert log_file.exists()
