"""
Tests for Security Module
"""

import pytest
import os
import tempfile
import time
from api.security import (
    TokenManager, RateLimiter, SecurityValidator
)


class TestTokenManager:
    """Tests pour TokenManager"""

    def test_generate_token(self):
        """Générer un token"""
        with tempfile.TemporaryDirectory() as tmpdir:
            tm = TokenManager(tmpdir)
            token = tm.get_token()

            assert token is not None
            assert len(token) > 20
            assert tm._token_hash is not None

    def test_token_persistence(self):
        """Token persistant entre instances"""
        with tempfile.TemporaryDirectory() as tmpdir:
            tm1 = TokenManager(tmpdir)
            token1 = tm1.get_token()

            tm2 = TokenManager(tmpdir)
            token2 = tm2.get_token()

            assert token1 == token2

    def test_verify_token(self):
        """Vérifier un token"""
        with tempfile.TemporaryDirectory() as tmpdir:
            tm = TokenManager(tmpdir)
            token = tm.get_token()

            assert tm.verify_token(token) is True
            assert tm.verify_token("invalid_token") is False


class TestRateLimiter:
    """Tests pour RateLimiter"""

    def test_allow_requests(self):
        """Autoriser les requêtes"""
        limiter = RateLimiter(max_requests=5, window_seconds=1)

        for i in range(5):
            allowed, retry = limiter.is_allowed('127.0.0.1')
            assert allowed is True

        # 6ème requête bloquée
        allowed, retry = limiter.is_allowed('127.0.0.1')
        assert allowed is False
        assert retry is not None

    def test_window_reset(self):
        """Reset après fenêtre"""
        limiter = RateLimiter(max_requests=2, window_seconds=1)

        # 2 requêtes OK
        limiter.is_allowed('127.0.0.1')
        limiter.is_allowed('127.0.0.1')

        # 3ème bloquée
        allowed, _ = limiter.is_allowed('127.0.0.1')
        assert allowed is False

        # Attendre reset
        time.sleep(1.1)

        # Nouvelle requête OK
        allowed, _ = limiter.is_allowed('127.0.0.1')
        assert allowed is True

    def test_different_ips(self):
        """IPs différentes indépendantes"""
        limiter = RateLimiter(max_requests=2, window_seconds=1)

        # IP 1: 2 requêtes
        limiter.is_allowed('192.168.1.1')
        limiter.is_allowed('192.168.1.1')

        # IP 2: toujours OK
        allowed, _ = limiter.is_allowed('192.168.1.2')
        assert allowed is True


class TestSecurityValidator:
    """Tests pour SecurityValidator"""

    def test_safe_filename(self):
        """Noms de fichiers sûrs"""
        validator = SecurityValidator()

        assert validator.is_safe_filename('config.json') is True
        assert validator.is_safe_filename('data_2024.csv') is True

        # Dangereux
        assert validator.is_safe_filename('../etc/passwd') is False
        assert validator.is_safe_filename('file\x00.txt') is False
        assert validator.is_safe_filename('') is False

    def test_safe_symbol(self):
        """Symboles crypto valides"""
        validator = SecurityValidator()

        assert validator.is_safe_symbol('BTCUSDT') is True
        assert validator.is_safe_symbol('ETHUSDT') is True

        # Invalides
        assert validator.is_safe_symbol('BTC') is False
        assert validator.is_safe_symbol('btcusdt') is False  # Minuscules
        assert validator.is_safe_symbol('BTC/USDT') is False
        assert validator.is_safe_symbol('') is False

    def test_sanitize_log(self):
        """Nettoyer messages de log"""
        validator = SecurityValidator()

        # Caractères de contrôle
        msg = "Test\nwith\nnewlines"
        sanitized = validator.sanitize_log_message(msg)
        assert '\n' not in sanitized

        # Longueur
        long_msg = 'A' * 1000
        sanitized = validator.sanitize_log_message(long_msg)
        assert len(sanitized) <= 500
