"""
Security Module Tests
Tests for HMAC authentication and signature generation
"""
import pytest
import time
import hmac
import hashlib


class TestSignatureGeneration:
    """Tests for HMAC signature generation"""
    
    def test_generate_signature_get_request(self, test_settings):
        """Should generate valid signature for GET requests"""
        from security import generate_signature
        
        timestamp = str(int(time.time()))
        path = "/api/catalog"
        method = "GET"
        
        signature = generate_signature(timestamp, path, method)
        
        assert signature is not None
        assert len(signature) == 64  # SHA256 hex digest length
    
    def test_generate_signature_post_request(self, test_settings):
        """Should generate valid signature for POST requests with body"""
        from security import generate_signature
        
        timestamp = str(int(time.time()))
        path = "/api/extract"
        method = "POST"
        body = b'{"url": "https://example.com/video"}'
        
        signature = generate_signature(timestamp, path, method, body)
        
        assert signature is not None
        assert len(signature) == 64
    
    def test_different_timestamps_produce_different_signatures(self, test_settings):
        """Different timestamps should produce different signatures"""
        from security import generate_signature
        
        sig1 = generate_signature("1000000000", "/api/test", "GET")
        sig2 = generate_signature("1000000001", "/api/test", "GET")
        
        assert sig1 != sig2
    
    def test_different_paths_produce_different_signatures(self, test_settings):
        """Different paths should produce different signatures"""
        from security import generate_signature
        
        timestamp = str(int(time.time()))
        
        sig1 = generate_signature(timestamp, "/api/path1", "GET")
        sig2 = generate_signature(timestamp, "/api/path2", "GET")
        
        assert sig1 != sig2
    
    def test_different_methods_produce_different_signatures(self, test_settings):
        """Different HTTP methods should produce different signatures"""
        from security import generate_signature
        
        timestamp = str(int(time.time()))
        path = "/api/test"
        
        sig_get = generate_signature(timestamp, path, "GET")
        sig_post = generate_signature(timestamp, path, "POST")
        
        assert sig_get != sig_post
    
    def test_body_affects_signature(self, test_settings):
        """Request body should affect the signature"""
        from security import generate_signature
        
        timestamp = str(int(time.time()))
        path = "/api/test"
        method = "POST"
        
        sig_empty = generate_signature(timestamp, path, method, b"")
        sig_with_body = generate_signature(timestamp, path, method, b'{"key": "value"}')
        
        assert sig_empty != sig_with_body


class TestSignatureVerification:
    """Tests for signature verification logic"""
    
    def test_valid_signature_passes(self, test_client, auth_headers):
        """Valid signature should pass authentication"""
        headers = auth_headers("/api/health", "GET")
        
        # Health doesn't require auth, but this tests the header generation
        response = test_client.get("/api/health", headers=headers)
        
        assert response.status_code == 200
    
    def test_missing_headers_rejected(self, test_client):
        """Requests without auth headers should be rejected on protected endpoints"""
        response = test_client.get("/api/admin/version")
        
        assert response.status_code == 401
        assert "Authentication headers missing" in response.json()["detail"]
    
    def test_invalid_signature_rejected(self, test_client):
        """Invalid signature should be rejected"""
        headers = {
            "X-Timestamp": str(int(time.time())),
            "X-Signature": "invalid_signature_here"
        }
        
        response = test_client.get("/api/admin/version", headers=headers)
        
        assert response.status_code == 401
        assert "Invalid signature" in response.json()["detail"]
    
    def test_expired_timestamp_rejected(self, test_client, test_settings):
        """Expired timestamps should be rejected"""
        from security import generate_signature
        
        # Timestamp from 10 minutes ago (beyond 5 min window)
        old_timestamp = str(int(time.time()) - 600)
        path = "/api/admin/version"
        signature = generate_signature(old_timestamp, path, "GET")
        
        headers = {
            "X-Timestamp": old_timestamp,
            "X-Signature": signature
        }
        
        response = test_client.get(path, headers=headers)
        
        assert response.status_code == 401
        assert "expired" in response.json()["detail"].lower()
    
    def test_invalid_timestamp_format_rejected(self, test_client):
        """Non-numeric timestamps should be rejected"""
        headers = {
            "X-Timestamp": "not-a-number",
            "X-Signature": "some_signature"
        }
        
        response = test_client.get("/api/admin/version", headers=headers)
        
        assert response.status_code == 401
        assert "Invalid timestamp" in response.json()["detail"]
