"""
Integration test for IP Management feature with HTTP server.

Tests the complete flow from HTTP request to IP tracking and access control.
"""

import os
import sys
import time
import threading
import requests
import tempfile
import json

# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from core.http_server import RateLoaderHTTPServer
from core.ip_manager import IPManager


def test_http_server_integration():
    """Test IP Management integration with HTTP server."""
    print("Testing HTTP server integration with IP Management...")
    
    # Create temporary IP manager for testing
    with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
        temp_file = f.name
        json.dump({"global_access": "allowed", "ips": {}}, f)
    
    try:
        # Create IP manager and HTTP server
        ip_manager = IPManager(temp_file)
        server = RateLoaderHTTPServer(port=0)  # Use port 0 to get random free port
        server.set_ip_manager(ip_manager)
        
        # Start server in background thread
        if server.start():
            # Get the actual port assigned
            port = server.server.server_address[1]
            base_url = f"http://localhost:{port}"
            
            try:
                # Test 1: Normal request should be allowed in global allowed mode
                response = requests.get(f"{base_url}/ping", timeout=5)
                assert response.status_code == 200, f"Expected 200, got {response.status_code}"
                print("✓ Request allowed in global allowed mode")
                
                # Test 2: Check that IP was recorded
                time.sleep(0.1)  # Give time for async recording
                ips = ip_manager.get_all_ips()
                assert len(ips["ips"]) > 0, "IP should be recorded"
                print("✓ IP address was recorded")
                
                # Test 3: Switch to restricted mode
                ip_manager.set_global_access("restricted")
                
                # Test 4: Existing IP should still be allowed in restricted mode
                # (since it was recorded when mode was allowed)
                response = requests.get(f"{base_url}/ping", timeout=5)
                assert response.status_code == 200, f"Expected 200, got {response.status_code}"
                print("✓ Existing IP allowed in global restricted mode")
                
                # Test 5: Allow the IP explicitly
                client_ip = "127.0.0.1"  # Localhost
                ip_manager.set_ip_status(client_ip, "allowed")
                
                # Test 6: Now the request should be allowed
                response = requests.get(f"{base_url}/ping", timeout=5)
                assert response.status_code == 200, f"Expected 200, got {response.status_code}"
                print("✓ Explicitly allowed IP permitted in restricted mode")
                
                # Test 7: Switch back to allowed mode and restrict the IP
                ip_manager.set_global_access("allowed")
                ip_manager.set_ip_status(client_ip, "restricted")
                
                # Test 8: Now the request should be denied
                response = requests.get(f"{base_url}/ping", timeout=5)
                assert response.status_code == 403, f"Expected 403, got {response.status_code}"
                print("✓ Restricted IP denied in global allowed mode")
                
                print("✓ HTTP server integration tests passed")
                
            finally:
                server.stop()
        else:
            print("✗ Failed to start HTTP server")
            return False
            
    except Exception as e:
        print(f"✗ HTTP server integration test failed: {str(e)}")
        return False
    finally:
        os.unlink(temp_file)
    
    return True


def test_post_request_tracking():
    """Test that POST requests are properly tracked."""
    print("Testing POST request tracking...")
    
    with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
        temp_file = f.name
        json.dump({"global_access": "allowed", "ips": {}}, f)
    
    try:
        ip_manager = IPManager(temp_file)
        server = RateLoaderHTTPServer(port=0)
        server.set_ip_manager(ip_manager)
        
        if server.start():
            port = server.server.server_address[1]
            base_url = f"http://localhost:{port}"
            
            try:
                # Send a POST request
                test_data = {"test": "data"}
                response = requests.post(f"{base_url}/load", json=test_data, timeout=5)
                
                # Should get 200 (even if data processing fails, IP should be tracked)
                assert response.status_code in [200, 400], f"Unexpected status code: {response.status_code}"
                
                # Check that POST request was recorded
                time.sleep(0.1)
                ips = ip_manager.get_all_ips()
                client_ip = "127.0.0.1"
                
                if client_ip in ips["ips"]:
                    ip_data = ips["ips"][client_ip]
                    assert ip_data["last_request_type"] == "POST", "Request type should be POST"
                    print("✓ POST request properly tracked")
                else:
                    print("⚠ IP not found in tracking (may be expected if request failed early)")
                
                print("✓ POST request tracking tests passed")
                
            finally:
                server.stop()
        else:
            print("✗ Failed to start HTTP server")
            return False
            
    except Exception as e:
        print(f"✗ POST request tracking test failed: {str(e)}")
        return False
    finally:
        os.unlink(temp_file)
    
    return True


def test_concurrent_requests():
    """Test handling of concurrent requests."""
    print("Testing concurrent request handling...")
    
    with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
        temp_file = f.name
        json.dump({"global_access": "allowed", "ips": {}}, f)
    
    try:
        ip_manager = IPManager(temp_file)
        server = RateLoaderHTTPServer(port=0)
        server.set_ip_manager(ip_manager)
        
        if server.start():
            port = server.server.server_address[1]
            base_url = f"http://localhost:{port}"
            
            try:
                # Make multiple concurrent requests
                def make_request():
                    try:
                        requests.get(f"{base_url}/ping", timeout=5)
                    except:
                        pass  # Ignore errors for this test
                
                threads = []
                for i in range(10):
                    thread = threading.Thread(target=make_request)
                    threads.append(thread)
                    thread.start()
                
                # Wait for all threads to complete
                for thread in threads:
                    thread.join()
                
                # Check that all requests were handled
                time.sleep(0.2)  # Give time for async operations
                ips = ip_manager.get_all_ips()
                client_ip = "127.0.0.1"
                
                if client_ip in ips["ips"]:
                    ip_data = ips["ips"][client_ip]
                    assert ip_data["request_count"] >= 5, f"Expected at least 5 requests, got {ip_data['request_count']}"
                    print(f"✓ Handled {ip_data['request_count']} concurrent requests")
                else:
                    print("⚠ No requests tracked (may indicate an issue)")
                
                print("✓ Concurrent request tests passed")
                
            finally:
                server.stop()
        else:
            print("✗ Failed to start HTTP server")
            return False
            
    except Exception as e:
        print(f"✗ Concurrent request test failed: {str(e)}")
        return False
    finally:
        os.unlink(temp_file)
    
    return True


def main():
    """Run all integration tests."""
    print("Running IP Management integration tests...\n")
    
    try:
        success = True
        
        if not test_http_server_integration():
            success = False
        
        if not test_post_request_tracking():
            success = False
        
        if not test_concurrent_requests():
            success = False
        
        if success:
            print("\n✓ All IP Management integration tests completed successfully!")
        else:
            print("\n✗ Some integration tests failed")
        
        return success
        
    except Exception as e:
        print(f"\n✗ Integration test failed: {str(e)}")
        import traceback
        traceback.print_exc()
        return False


if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)