"""
Test script for IP Management functionality.

Tests IP address validation, access control logic, and basic operations.
"""

import os
import sys
import tempfile
import json
from datetime import datetime

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

from core.ip_manager import IPManager
from core.config import get_config


def test_ip_validation():
    """Test IP address validation."""
    print("Testing IP address validation...")
    
    # 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:
        ip_manager = IPManager(temp_file)
        
        # Test valid IPs
        valid_ips = ["192.168.1.1", "10.0.0.1", "172.16.0.1", "127.0.0.1"]
        for ip in valid_ips:
            assert ip_manager._validate_ip(ip), f"Valid IP {ip} was rejected"
        
        # Test invalid IPs
        invalid_ips = ["256.256.256.256", "invalid.ip", "192.168.1", ""]
        for ip in invalid_ips:
            assert not ip_manager._validate_ip(ip), f"Invalid IP {ip} was accepted"
        
        print("✓ IP address validation tests passed")
        
    finally:
        os.unlink(temp_file)


def test_access_control_logic():
    """Test access control logic."""
    print("Testing access control logic...")
    
    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)
        
        # Test global allowed mode (blacklist)
        ip_manager.set_global_access("allowed")
        
        # New IP should be allowed in allowed mode
        assert ip_manager.is_ip_allowed("192.168.1.100"), "New IP should be allowed in global allowed mode"
        
        # Add IP and restrict it
        ip_manager.set_ip_status("192.168.1.100", "restricted")
        assert not ip_manager.is_ip_allowed("192.168.1.100"), "Restricted IP should be denied in global allowed mode"
        
        # Test global restricted mode (whitelist)
        ip_manager.set_global_access("restricted")
        
        # New IP should be denied in restricted mode
        assert not ip_manager.is_ip_allowed("10.0.0.50"), "New IP should be denied in global restricted mode"
        
        # Add IP and allow it
        ip_manager.set_ip_status("10.0.0.50", "allowed")
        assert ip_manager.is_ip_allowed("10.0.0.50"), "Allowed IP should be permitted in global restricted mode"
        
        print("✓ Access control logic tests passed")
        
    finally:
        os.unlink(temp_file)


def test_request_recording():
    """Test request recording functionality."""
    print("Testing request recording...")
    
    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)
        
        # Record first request
        ip_manager.record_request("192.168.1.100", "POST")
        
        ips = ip_manager.get_all_ips()
        ip_data = ips["ips"]["192.168.1.100"]
        
        assert ip_data["status"] == "allowed", "New IP should have allowed status"
        assert ip_data["request_count"] == 1, "Request count should be 1"
        assert ip_data["last_request_type"] == "POST", "Last request type should be POST"
        assert "first_seen" in ip_data, "First seen should be set"
        assert "last_seen" in ip_data, "Last seen should be set"
        
        # Record second request
        ip_manager.record_request("192.168.1.100", "GET")
        
        ips = ip_manager.get_all_ips()
        ip_data = ips["ips"]["192.168.1.100"]
        
        assert ip_data["request_count"] == 2, "Request count should be 2"
        assert ip_data["last_request_type"] == "GET", "Last request type should be GET"
        
        print("✓ Request recording tests passed")
        
    finally:
        os.unlink(temp_file)


def test_ip_status_management():
    """Test IP status management."""
    print("Testing IP status management...")
    
    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)
        
        # Add new IP with restricted status
        ip_manager.set_ip_status("192.168.1.100", "restricted")
        
        ips = ip_manager.get_all_ips()
        ip_data = ips["ips"]["192.168.1.100"]
        
        assert ip_data["status"] == "restricted", "IP should have restricted status"
        
        # Change status to allowed
        ip_manager.set_ip_status("192.168.1.100", "allowed")
        
        ips = ip_manager.get_all_ips()
        ip_data = ips["ips"]["192.168.1.100"]
        
        assert ip_data["status"] == "allowed", "IP status should be changed to allowed"
        
        # Remove IP
        ip_manager.remove_ip("192.168.1.100")
        
        ips = ip_manager.get_all_ips()
        assert "192.168.1.100" not in ips["ips"], "IP should be removed"
        
        print("✓ IP status management tests passed")
        
    finally:
        os.unlink(temp_file)


def test_file_operations():
    """Test file read/write operations."""
    print("Testing file operations...")
    
    with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
        temp_file = f.name
    
    try:
        # Test creating new file
        os.unlink(temp_file)  # Remove the file so IP manager creates it
        
        ip_manager = IPManager(temp_file)
        
        # Verify default structure
        ips = ip_manager.get_all_ips()
        assert ips["global_access"] == "allowed", "Default global access should be allowed"
        assert isinstance(ips["ips"], dict), "IPs should be a dictionary"
        
        # Test saving data
        ip_manager.set_global_access("restricted")
        ip_manager.set_ip_status("192.168.1.100", "allowed")
        
        # Create new instance to test loading
        ip_manager2 = IPManager(temp_file)
        ips2 = ip_manager2.get_all_ips()
        
        assert ips2["global_access"] == "restricted", "Global access should be persisted"
        assert "192.168.1.100" in ips2["ips"], "IP should be persisted"
        
        print("✓ File operations tests passed")
        
    finally:
        if os.path.exists(temp_file):
            os.unlink(temp_file)


def test_integration_with_config():
    """Test integration with configuration system."""
    print("Testing integration with configuration system...")
    
    try:
        config = get_config()
        
        # Test that IP management settings are available
        assert config.get("ip_file") is not None, "ip_file setting should be available"
        assert config.get_bool("auto_add_new_ips") is not None, "auto_add_new_ips setting should be available"
        assert config.get_bool("log_denied_requests") is not None, "log_denied_requests setting should be available"
        assert config.get_int("max_tracked_ips") is not None, "max_tracked_ips setting should be available"
        
        print("✓ Configuration integration tests passed")
        
    except Exception as e:
        print(f"✗ Configuration integration test failed: {str(e)}")
        return False
    
    return True


def main():
    """Run all tests."""
    print("Running IP Management tests...\n")
    
    try:
        test_ip_validation()
        test_access_control_logic()
        test_request_recording()
        test_ip_status_management()
        test_file_operations()
        
        if not test_integration_with_config():
            print("\n⚠ Some tests failed due to configuration issues")
        
        print("\n✓ All IP Management tests completed successfully!")
        return True
        
    except Exception as e:
        print(f"\n✗ Test failed: {str(e)}")
        import traceback
        traceback.print_exc()
        return False


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